Lines Matching +full:num +full:- +full:addresses
1 // SPDX-License-Identifier: GPL-2.0
8 #include "ingenic-drm.h"
9 #include "ingenic-ipu.h"
65 /* Signed 15.16 fixed-point math (for bicubic scaling coefficients) */
69 #define SHARPNESS_INCR (I2F(-1) / 8)
78 * and return value are 15.16 signed fixed-point.
80 * @f_a: Sharpness factor, typically in range [-4.0, -0.25].
82 * -2.0 might cause ringing artifacts to outweigh any improvement.
83 * Nice values on a 320x240 LCD are between -0.75 and -2.0.
88 * returns: Weight of this pixel within 4-pixel sample group. Range is
89 * [-2.0, +2.0]. For moderate (i.e. > -3.0) sharpness factors,
90 * range is within [-1.0, +1.0].
102 return FMUL((f_a + f_2), f_x3) - FMUL((f_a + f_3), f_x2) + f_1; in cubic_conv()
104 return FMUL(f_a, (f_x3 - 5 * f_x2 + 8 * f_x - f_4)); in cubic_conv()
124 s32 w0, w1, w2, w3; /* Pixel weights at X (or Y) offsets -1,0,1,2 */ in jz4760_set_coefs()
130 * When sharpness setting is 0, emulate nearest-neighbor. in jz4760_set_coefs()
138 w2 = 512 - weight; in jz4760_set_coefs()
146 * The resulting coefficients match a round-to-nearest-int in jz4760_set_coefs()
147 * double floating-point implementation. in jz4760_set_coefs()
150 weight = 512 - weight; in jz4760_set_coefs()
153 w2 = F2I(f_h + 512 * cubic_conv(f_a, I2F(512 - weight) / 512)); in jz4760_set_coefs()
154 w3 = F2I(f_h + 512 * cubic_conv(f_a, I2F(1024 - weight) / 512)); in jz4760_set_coefs()
155 w0 = clamp_val(w0, -1024, 1023); in jz4760_set_coefs()
156 w1 = clamp_val(w1, -1024, 1023); in jz4760_set_coefs()
157 w2 = clamp_val(w2, -1024, 1023); in jz4760_set_coefs()
158 w3 = clamp_val(w3, -1024, 1023); in jz4760_set_coefs()
163 regmap_write(ipu->map, reg, val); in jz4760_set_coefs()
168 regmap_write(ipu->map, reg, val); in jz4760_set_coefs()
187 regmap_write(ipu->map, reg, val); in jz4725b_set_coefs()
191 regmap_write(ipu->map, reg, JZ4725B_IPU_RSZ_LUT_IN_EN); in jz4725b_set_coefs()
197 unsigned int num, in ingenic_ipu_set_downscale_coefs() argument
202 for (i = 0; i < num; i++) { in ingenic_ipu_set_downscale_coefs()
203 weight_num = num + (weight_num - num) % (num * 2); in ingenic_ipu_set_downscale_coefs()
204 weight = 512 - 512 * (weight_num - num) / (num * 2); in ingenic_ipu_set_downscale_coefs()
206 offset = (weight_num - num) / (num * 2); in ingenic_ipu_set_downscale_coefs()
208 ipu->soc_info->set_coefs(ipu, reg, ipu->sharpness, in ingenic_ipu_set_downscale_coefs()
215 unsigned int num) in ingenic_ipu_set_integer_upscale_coefs() argument
218 * Force nearest-neighbor scaling and use simple math when upscaling in ingenic_ipu_set_integer_upscale_coefs()
223 for (i = 0; i < num; i++) in ingenic_ipu_set_integer_upscale_coefs()
224 ipu->soc_info->set_coefs(ipu, reg, 0, false, 512, i == num - 1); in ingenic_ipu_set_integer_upscale_coefs()
229 unsigned int num, in ingenic_ipu_set_upscale_coefs() argument
234 for (i = 0; i < num; i++) { in ingenic_ipu_set_upscale_coefs()
235 weight = 512 - 512 * weight_num / num; in ingenic_ipu_set_upscale_coefs()
237 offset = weight_num >= num; in ingenic_ipu_set_upscale_coefs()
240 weight_num -= num; in ingenic_ipu_set_upscale_coefs()
242 ipu->soc_info->set_coefs(ipu, reg, ipu->sharpness, in ingenic_ipu_set_upscale_coefs()
248 unsigned int num, unsigned int denom) in ingenic_ipu_set_coefs() argument
251 regmap_write(ipu->map, reg, -1); in ingenic_ipu_set_coefs()
253 if (denom > num) in ingenic_ipu_set_coefs()
254 ingenic_ipu_set_downscale_coefs(ipu, reg, num, denom); in ingenic_ipu_set_coefs()
256 ingenic_ipu_set_integer_upscale_coefs(ipu, reg, num); in ingenic_ipu_set_coefs()
258 ingenic_ipu_set_upscale_coefs(ipu, reg, num, denom); in ingenic_ipu_set_coefs()
261 static int reduce_fraction(unsigned int *num, unsigned int *denom) in reduce_fraction() argument
263 unsigned long d = gcd(*num, *denom); in reduce_fraction()
266 if (*num > 31 * d) in reduce_fraction()
267 return -EINVAL; in reduce_fraction()
269 *num /= d; in reduce_fraction()
277 return state->src_x != oldstate->src_x || in osd_changed()
278 state->src_y != oldstate->src_y || in osd_changed()
279 state->src_w != oldstate->src_w || in osd_changed()
280 state->src_h != oldstate->src_h || in osd_changed()
281 state->crtc_x != oldstate->crtc_x || in osd_changed()
282 state->crtc_y != oldstate->crtc_y || in osd_changed()
283 state->crtc_w != oldstate->crtc_w || in osd_changed()
284 state->crtc_h != oldstate->crtc_h; in osd_changed()
298 if (!newstate || !newstate->fb) in ingenic_ipu_plane_atomic_update()
301 finfo = drm_format_info(newstate->fb->format->format); in ingenic_ipu_plane_atomic_update()
303 if (!ipu->clk_enabled) { in ingenic_ipu_plane_atomic_update()
304 err = clk_enable(ipu->clk); in ingenic_ipu_plane_atomic_update()
306 dev_err(ipu->dev, "Unable to enable clock: %d\n", err); in ingenic_ipu_plane_atomic_update()
310 ipu->clk_enabled = true; in ingenic_ipu_plane_atomic_update()
314 needs_modeset = drm_atomic_crtc_needs_modeset(newstate->crtc->state); in ingenic_ipu_plane_atomic_update()
316 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_RST); in ingenic_ipu_plane_atomic_update()
319 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, in ingenic_ipu_plane_atomic_update()
323 if (ingenic_drm_map_noncoherent(ipu->master)) in ingenic_ipu_plane_atomic_update()
324 drm_fb_cma_sync_non_coherent(ipu->drm, oldstate, newstate); in ingenic_ipu_plane_atomic_update()
326 /* New addresses will be committed in vblank handler... */ in ingenic_ipu_plane_atomic_update()
327 ipu->addr_y = drm_fb_cma_get_gem_addr(newstate->fb, newstate, 0); in ingenic_ipu_plane_atomic_update()
328 if (finfo->num_planes > 1) in ingenic_ipu_plane_atomic_update()
329 ipu->addr_u = drm_fb_cma_get_gem_addr(newstate->fb, newstate, in ingenic_ipu_plane_atomic_update()
331 if (finfo->num_planes > 2) in ingenic_ipu_plane_atomic_update()
332 ipu->addr_v = drm_fb_cma_get_gem_addr(newstate->fb, newstate, in ingenic_ipu_plane_atomic_update()
339 regmap_write(ipu->map, JZ_REG_IPU_Y_ADDR, ipu->addr_y); in ingenic_ipu_plane_atomic_update()
340 regmap_write(ipu->map, JZ_REG_IPU_U_ADDR, ipu->addr_u); in ingenic_ipu_plane_atomic_update()
341 regmap_write(ipu->map, JZ_REG_IPU_V_ADDR, ipu->addr_v); in ingenic_ipu_plane_atomic_update()
343 if (finfo->num_planes == 1) in ingenic_ipu_plane_atomic_update()
344 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_SPKG_SEL); in ingenic_ipu_plane_atomic_update()
346 ingenic_drm_plane_config(ipu->master, plane, DRM_FORMAT_XRGB8888); in ingenic_ipu_plane_atomic_update()
349 if (finfo->num_planes > 2) in ingenic_ipu_plane_atomic_update()
350 stride = ((newstate->src_w >> 16) * finfo->cpp[2] / finfo->hsub) in ingenic_ipu_plane_atomic_update()
353 if (finfo->num_planes > 1) in ingenic_ipu_plane_atomic_update()
354 stride |= ((newstate->src_w >> 16) * finfo->cpp[1] / finfo->hsub) in ingenic_ipu_plane_atomic_update()
357 regmap_write(ipu->map, JZ_REG_IPU_UV_STRIDE, stride); in ingenic_ipu_plane_atomic_update()
359 stride = ((newstate->src_w >> 16) * finfo->cpp[0]) << JZ_IPU_Y_STRIDE_Y_LSB; in ingenic_ipu_plane_atomic_update()
360 regmap_write(ipu->map, JZ_REG_IPU_Y_STRIDE, stride); in ingenic_ipu_plane_atomic_update()
362 regmap_write(ipu->map, JZ_REG_IPU_IN_GS, in ingenic_ipu_plane_atomic_update()
364 ((newstate->src_h >> 16) << JZ_IPU_IN_GS_H_LSB)); in ingenic_ipu_plane_atomic_update()
366 switch (finfo->format) { in ingenic_ipu_plane_atomic_update()
429 regmap_write(ipu->map, JZ_REG_IPU_D_FMT, format); in ingenic_ipu_plane_atomic_update()
432 regmap_write(ipu->map, JZ_REG_IPU_OUT_GS, in ingenic_ipu_plane_atomic_update()
433 ((newstate->crtc_w * 4) << JZ_IPU_OUT_GS_W_LSB) in ingenic_ipu_plane_atomic_update()
434 | newstate->crtc_h << JZ_IPU_OUT_GS_H_LSB); in ingenic_ipu_plane_atomic_update()
435 regmap_write(ipu->map, JZ_REG_IPU_OUT_STRIDE, newstate->crtc_w * 4); in ingenic_ipu_plane_atomic_update()
437 if (finfo->is_yuv) { in ingenic_ipu_plane_atomic_update()
438 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_CSC_EN); in ingenic_ipu_plane_atomic_update()
442 * y = source Y - LUMA, in ingenic_ipu_plane_atomic_update()
443 * u = source Cb - CHROMA, in ingenic_ipu_plane_atomic_update()
444 * v = source Cr - CHROMA in ingenic_ipu_plane_atomic_update()
446 regmap_write(ipu->map, JZ_REG_IPU_CSC_OFFSET, in ingenic_ipu_plane_atomic_update()
453 * G = C0 / 0x400 * y - C2 / 0x400 * u - C3 / 0x400 * v in ingenic_ipu_plane_atomic_update()
456 regmap_write(ipu->map, JZ_REG_IPU_CSC_C0_COEF, 0x4a8); in ingenic_ipu_plane_atomic_update()
457 regmap_write(ipu->map, JZ_REG_IPU_CSC_C1_COEF, 0x662); in ingenic_ipu_plane_atomic_update()
458 regmap_write(ipu->map, JZ_REG_IPU_CSC_C2_COEF, 0x191); in ingenic_ipu_plane_atomic_update()
459 regmap_write(ipu->map, JZ_REG_IPU_CSC_C3_COEF, 0x341); in ingenic_ipu_plane_atomic_update()
460 regmap_write(ipu->map, JZ_REG_IPU_CSC_C4_COEF, 0x811); in ingenic_ipu_plane_atomic_update()
470 if (ipu->soc_info->has_bicubic) in ingenic_ipu_plane_atomic_update()
473 upscaling_w = ipu->num_w > ipu->denom_w; in ingenic_ipu_plane_atomic_update()
477 if (ipu->num_w != 1 || ipu->denom_w != 1) { in ingenic_ipu_plane_atomic_update()
478 if (!ipu->soc_info->has_bicubic && !upscaling_w) in ingenic_ipu_plane_atomic_update()
479 coef_index |= (ipu->denom_w - 1) << 16; in ingenic_ipu_plane_atomic_update()
481 coef_index |= (ipu->num_w - 1) << 16; in ingenic_ipu_plane_atomic_update()
485 upscaling_h = ipu->num_h > ipu->denom_h; in ingenic_ipu_plane_atomic_update()
489 if (ipu->num_h != 1 || ipu->denom_h != 1) { in ingenic_ipu_plane_atomic_update()
490 if (!ipu->soc_info->has_bicubic && !upscaling_h) in ingenic_ipu_plane_atomic_update()
491 coef_index |= ipu->denom_h - 1; in ingenic_ipu_plane_atomic_update()
493 coef_index |= ipu->num_h - 1; in ingenic_ipu_plane_atomic_update()
497 regmap_update_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_ZOOM_SEL | in ingenic_ipu_plane_atomic_update()
502 regmap_write(ipu->map, JZ_REG_IPU_RSZ_COEF_INDEX, coef_index); in ingenic_ipu_plane_atomic_update()
504 if (ipu->num_w != 1 || ipu->denom_w != 1) in ingenic_ipu_plane_atomic_update()
506 ipu->num_w, ipu->denom_w); in ingenic_ipu_plane_atomic_update()
508 if (ipu->num_h != 1 || ipu->denom_h != 1) in ingenic_ipu_plane_atomic_update()
510 ipu->num_h, ipu->denom_h); in ingenic_ipu_plane_atomic_update()
513 regmap_write(ipu->map, JZ_REG_IPU_STATUS, 0); in ingenic_ipu_plane_atomic_update()
516 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, in ingenic_ipu_plane_atomic_update()
519 dev_dbg(ipu->dev, "Scaling %ux%u to %ux%u (%u:%u horiz, %u:%u vert)\n", in ingenic_ipu_plane_atomic_update()
520 newstate->src_w >> 16, newstate->src_h >> 16, in ingenic_ipu_plane_atomic_update()
521 newstate->crtc_w, newstate->crtc_h, in ingenic_ipu_plane_atomic_update()
522 ipu->num_w, ipu->denom_w, ipu->num_h, ipu->denom_h); in ingenic_ipu_plane_atomic_update()
534 struct drm_crtc *crtc = new_plane_state->crtc ?: old_plane_state->crtc; in ingenic_ipu_plane_atomic_check()
542 return -EINVAL; in ingenic_ipu_plane_atomic_check()
545 if (!old_plane_state->crtc ^ !new_plane_state->crtc) in ingenic_ipu_plane_atomic_check()
546 crtc_state->mode_changed = true; in ingenic_ipu_plane_atomic_check()
548 if (!new_plane_state->crtc || in ingenic_ipu_plane_atomic_check()
549 !crtc_state->mode.hdisplay || !crtc_state->mode.vdisplay) in ingenic_ipu_plane_atomic_check()
553 if (new_plane_state->crtc_x < 0 || new_plane_state->crtc_y < 0 || in ingenic_ipu_plane_atomic_check()
554 new_plane_state->crtc_x + new_plane_state->crtc_w > crtc_state->mode.hdisplay || in ingenic_ipu_plane_atomic_check()
555 new_plane_state->crtc_y + new_plane_state->crtc_h > crtc_state->mode.vdisplay) in ingenic_ipu_plane_atomic_check()
556 return -EINVAL; in ingenic_ipu_plane_atomic_check()
559 if ((new_plane_state->src_w >> 16) < 4 || (new_plane_state->src_h >> 16) < 4) in ingenic_ipu_plane_atomic_check()
560 return -EINVAL; in ingenic_ipu_plane_atomic_check()
563 if (((new_plane_state->src_w >> 16) & 1) || (new_plane_state->crtc_w & 1)) in ingenic_ipu_plane_atomic_check()
564 return -EINVAL; in ingenic_ipu_plane_atomic_check()
569 crtc_state->mode_changed = true; in ingenic_ipu_plane_atomic_check()
571 xres = new_plane_state->src_w >> 16; in ingenic_ipu_plane_atomic_check()
572 yres = new_plane_state->src_h >> 16; in ingenic_ipu_plane_atomic_check()
581 max_w = crtc_state->mode.hdisplay * 102 / 100; in ingenic_ipu_plane_atomic_check()
582 max_h = crtc_state->mode.vdisplay * 102 / 100; in ingenic_ipu_plane_atomic_check()
584 for (denom_w = xres, num_w = new_plane_state->crtc_w; num_w <= max_w; num_w++) in ingenic_ipu_plane_atomic_check()
588 return -EINVAL; in ingenic_ipu_plane_atomic_check()
590 for (denom_h = yres, num_h = new_plane_state->crtc_h; num_h <= max_h; num_h++) in ingenic_ipu_plane_atomic_check()
594 return -EINVAL; in ingenic_ipu_plane_atomic_check()
596 ipu->num_w = num_w; in ingenic_ipu_plane_atomic_check()
597 ipu->num_h = num_h; in ingenic_ipu_plane_atomic_check()
598 ipu->denom_w = denom_w; in ingenic_ipu_plane_atomic_check()
599 ipu->denom_h = denom_h; in ingenic_ipu_plane_atomic_check()
602 if (ingenic_drm_map_noncoherent(ipu->master)) in ingenic_ipu_plane_atomic_check()
613 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_STOP); in ingenic_ipu_plane_atomic_disable()
614 regmap_clear_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_CHIP_EN); in ingenic_ipu_plane_atomic_disable()
616 ingenic_drm_plane_disable(ipu->master, plane); in ingenic_ipu_plane_atomic_disable()
618 if (ipu->clk_enabled) { in ingenic_ipu_plane_atomic_disable()
619 clk_disable(ipu->clk); in ingenic_ipu_plane_atomic_disable()
620 ipu->clk_enabled = false; in ingenic_ipu_plane_atomic_disable()
637 if (property != ipu->sharpness_prop) in ingenic_ipu_plane_atomic_get_property()
638 return -EINVAL; in ingenic_ipu_plane_atomic_get_property()
640 *val = ipu->sharpness; in ingenic_ipu_plane_atomic_get_property()
653 if (property != ipu->sharpness_prop) in ingenic_ipu_plane_atomic_set_property()
654 return -EINVAL; in ingenic_ipu_plane_atomic_set_property()
656 ipu->sharpness = val; in ingenic_ipu_plane_atomic_set_property()
658 if (state->crtc) { in ingenic_ipu_plane_atomic_set_property()
659 crtc_state = drm_atomic_get_existing_crtc_state(state->state, state->crtc); in ingenic_ipu_plane_atomic_set_property()
661 return -EINVAL; in ingenic_ipu_plane_atomic_set_property()
663 crtc_state->mode_changed = true; in ingenic_ipu_plane_atomic_set_property()
685 struct drm_crtc *crtc = drm_crtc_from_index(ipu->drm, 0); in ingenic_ipu_irq_handler()
689 if (ipu->soc_info->manual_restart) in ingenic_ipu_irq_handler()
690 regmap_read(ipu->map, JZ_REG_IPU_STATUS, &dummy); in ingenic_ipu_irq_handler()
693 regmap_write(ipu->map, JZ_REG_IPU_STATUS, 0); in ingenic_ipu_irq_handler()
695 /* Set previously cached addresses */ in ingenic_ipu_irq_handler()
696 regmap_write(ipu->map, JZ_REG_IPU_Y_ADDR, ipu->addr_y); in ingenic_ipu_irq_handler()
697 regmap_write(ipu->map, JZ_REG_IPU_U_ADDR, ipu->addr_u); in ingenic_ipu_irq_handler()
698 regmap_write(ipu->map, JZ_REG_IPU_V_ADDR, ipu->addr_v); in ingenic_ipu_irq_handler()
701 if (ipu->soc_info->manual_restart) in ingenic_ipu_irq_handler()
702 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_RUN); in ingenic_ipu_irq_handler()
730 return -ENOMEM; in ingenic_ipu_bind()
735 return -EINVAL; in ingenic_ipu_bind()
738 ipu->dev = dev; in ingenic_ipu_bind()
739 ipu->drm = drm; in ingenic_ipu_bind()
740 ipu->master = master; in ingenic_ipu_bind()
741 ipu->soc_info = soc_info; in ingenic_ipu_bind()
749 ipu->map = devm_regmap_init_mmio(dev, base, &ingenic_ipu_regmap_config); in ingenic_ipu_bind()
750 if (IS_ERR(ipu->map)) { in ingenic_ipu_bind()
752 return PTR_ERR(ipu->map); in ingenic_ipu_bind()
759 ipu->clk = devm_clk_get(dev, "ipu"); in ingenic_ipu_bind()
760 if (IS_ERR(ipu->clk)) { in ingenic_ipu_bind()
762 return PTR_ERR(ipu->clk); in ingenic_ipu_bind()
772 plane = &ipu->plane; in ingenic_ipu_bind()
778 soc_info->formats, soc_info->num_formats, in ingenic_ipu_bind()
790 * 0 : nearest-neighbor in ingenic_ipu_bind()
792 * 2 .. 32 : bicubic (translated to sharpness factor -0.25 .. -4.0) in ingenic_ipu_bind()
794 sharpness_max = soc_info->has_bicubic ? 32 : 1; in ingenic_ipu_bind()
795 ipu->sharpness_prop = drm_property_create_range(drm, 0, "sharpness", in ingenic_ipu_bind()
797 if (!ipu->sharpness_prop) { in ingenic_ipu_bind()
799 return -ENOMEM; in ingenic_ipu_bind()
802 /* Default sharpness factor: -0.125 * 8 = -1.0 */ in ingenic_ipu_bind()
803 ipu->sharpness = soc_info->has_bicubic ? 8 : 1; in ingenic_ipu_bind()
804 drm_object_attach_property(&plane->base, ipu->sharpness_prop, in ingenic_ipu_bind()
805 ipu->sharpness); in ingenic_ipu_bind()
807 err = clk_prepare(ipu->clk); in ingenic_ipu_bind()
821 clk_unprepare(ipu->clk); in ingenic_ipu_unbind()
831 return component_add(&pdev->dev, &ingenic_ipu_ops); in ingenic_ipu_probe()
836 component_del(&pdev->dev, &ingenic_ipu_ops); in ingenic_ipu_remove()
892 { .compatible = "ingenic,jz4725b-ipu", .data = &jz4725b_soc_info },
893 { .compatible = "ingenic,jz4760-ipu", .data = &jz4760_soc_info },
900 .name = "ingenic-ipu",