Lines Matching +full:num +full:- +full:addresses
1 // SPDX-License-Identifier: GPL-2.0
8 #include "ingenic-drm.h"
9 #include "ingenic-ipu.h"
62 /* Signed 15.16 fixed-point math (for bicubic scaling coefficients) */
66 #define SHARPNESS_INCR (I2F(-1) / 8)
75 * and return value are 15.16 signed fixed-point.
77 * @f_a: Sharpness factor, typically in range [-4.0, -0.25].
79 * -2.0 might cause ringing artifacts to outweigh any improvement.
80 * Nice values on a 320x240 LCD are between -0.75 and -2.0.
85 * returns: Weight of this pixel within 4-pixel sample group. Range is
86 * [-2.0, +2.0]. For moderate (i.e. > -3.0) sharpness factors,
87 * range is within [-1.0, +1.0].
99 return FMUL((f_a + f_2), f_x3) - FMUL((f_a + f_3), f_x2) + f_1; in cubic_conv()
101 return FMUL(f_a, (f_x3 - 5 * f_x2 + 8 * f_x - f_4)); in cubic_conv()
121 s32 w0, w1, w2, w3; /* Pixel weights at X (or Y) offsets -1,0,1,2 */ in jz4760_set_coefs()
127 * When sharpness setting is 0, emulate nearest-neighbor. in jz4760_set_coefs()
135 w2 = 512 - weight; in jz4760_set_coefs()
143 * The resulting coefficients match a round-to-nearest-int in jz4760_set_coefs()
144 * double floating-point implementation. in jz4760_set_coefs()
147 weight = 512 - weight; in jz4760_set_coefs()
150 w2 = F2I(f_h + 512 * cubic_conv(f_a, I2F(512 - weight) / 512)); in jz4760_set_coefs()
151 w3 = F2I(f_h + 512 * cubic_conv(f_a, I2F(1024 - weight) / 512)); in jz4760_set_coefs()
152 w0 = clamp_val(w0, -1024, 1023); in jz4760_set_coefs()
153 w1 = clamp_val(w1, -1024, 1023); in jz4760_set_coefs()
154 w2 = clamp_val(w2, -1024, 1023); in jz4760_set_coefs()
155 w3 = clamp_val(w3, -1024, 1023); in jz4760_set_coefs()
160 regmap_write(ipu->map, reg, val); in jz4760_set_coefs()
165 regmap_write(ipu->map, reg, val); in jz4760_set_coefs()
184 regmap_write(ipu->map, reg, val); in jz4725b_set_coefs()
188 regmap_write(ipu->map, reg, JZ4725B_IPU_RSZ_LUT_IN_EN); in jz4725b_set_coefs()
194 unsigned int num, in ingenic_ipu_set_downscale_coefs() argument
199 for (i = 0; i < num; i++) { in ingenic_ipu_set_downscale_coefs()
200 weight_num = num + (weight_num - num) % (num * 2); in ingenic_ipu_set_downscale_coefs()
201 weight = 512 - 512 * (weight_num - num) / (num * 2); in ingenic_ipu_set_downscale_coefs()
203 offset = (weight_num - num) / (num * 2); in ingenic_ipu_set_downscale_coefs()
205 ipu->soc_info->set_coefs(ipu, reg, ipu->sharpness, in ingenic_ipu_set_downscale_coefs()
212 unsigned int num) in ingenic_ipu_set_integer_upscale_coefs() argument
215 * Force nearest-neighbor scaling and use simple math when upscaling in ingenic_ipu_set_integer_upscale_coefs()
220 for (i = 0; i < num; i++) in ingenic_ipu_set_integer_upscale_coefs()
221 ipu->soc_info->set_coefs(ipu, reg, 0, false, 512, i == num - 1); in ingenic_ipu_set_integer_upscale_coefs()
226 unsigned int num, in ingenic_ipu_set_upscale_coefs() argument
231 for (i = 0; i < num; i++) { in ingenic_ipu_set_upscale_coefs()
232 weight = 512 - 512 * weight_num / num; in ingenic_ipu_set_upscale_coefs()
234 offset = weight_num >= num; in ingenic_ipu_set_upscale_coefs()
237 weight_num -= num; in ingenic_ipu_set_upscale_coefs()
239 ipu->soc_info->set_coefs(ipu, reg, ipu->sharpness, in ingenic_ipu_set_upscale_coefs()
245 unsigned int num, unsigned int denom) in ingenic_ipu_set_coefs() argument
248 regmap_write(ipu->map, reg, -1); in ingenic_ipu_set_coefs()
250 if (denom > num) in ingenic_ipu_set_coefs()
251 ingenic_ipu_set_downscale_coefs(ipu, reg, num, denom); in ingenic_ipu_set_coefs()
253 ingenic_ipu_set_integer_upscale_coefs(ipu, reg, num); in ingenic_ipu_set_coefs()
255 ingenic_ipu_set_upscale_coefs(ipu, reg, num, denom); in ingenic_ipu_set_coefs()
258 static int reduce_fraction(unsigned int *num, unsigned int *denom) in reduce_fraction() argument
260 unsigned long d = gcd(*num, *denom); in reduce_fraction()
263 if (*num > 31 * d) in reduce_fraction()
264 return -EINVAL; in reduce_fraction()
266 *num /= d; in reduce_fraction()
274 return state->src_x != oldstate->src_x || in osd_changed()
275 state->src_y != oldstate->src_y || in osd_changed()
276 state->src_w != oldstate->src_w || in osd_changed()
277 state->src_h != oldstate->src_h || in osd_changed()
278 state->crtc_x != oldstate->crtc_x || in osd_changed()
279 state->crtc_y != oldstate->crtc_y || in osd_changed()
280 state->crtc_w != oldstate->crtc_w || in osd_changed()
281 state->crtc_h != oldstate->crtc_h; in osd_changed()
288 struct drm_plane_state *state = plane->state; in ingenic_ipu_plane_atomic_update()
294 if (!state || !state->fb) in ingenic_ipu_plane_atomic_update()
297 finfo = drm_format_info(state->fb->format->format); in ingenic_ipu_plane_atomic_update()
299 if (!ipu->clk_enabled) { in ingenic_ipu_plane_atomic_update()
300 err = clk_enable(ipu->clk); in ingenic_ipu_plane_atomic_update()
302 dev_err(ipu->dev, "Unable to enable clock: %d\n", err); in ingenic_ipu_plane_atomic_update()
306 ipu->clk_enabled = true; in ingenic_ipu_plane_atomic_update()
310 needs_modeset = drm_atomic_crtc_needs_modeset(state->crtc->state); in ingenic_ipu_plane_atomic_update()
312 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_RST); in ingenic_ipu_plane_atomic_update()
315 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, in ingenic_ipu_plane_atomic_update()
319 /* New addresses will be committed in vblank handler... */ in ingenic_ipu_plane_atomic_update()
320 ipu->addr_y = drm_fb_cma_get_gem_addr(state->fb, state, 0); in ingenic_ipu_plane_atomic_update()
321 if (finfo->num_planes > 1) in ingenic_ipu_plane_atomic_update()
322 ipu->addr_u = drm_fb_cma_get_gem_addr(state->fb, state, 1); in ingenic_ipu_plane_atomic_update()
323 if (finfo->num_planes > 2) in ingenic_ipu_plane_atomic_update()
324 ipu->addr_v = drm_fb_cma_get_gem_addr(state->fb, state, 2); in ingenic_ipu_plane_atomic_update()
330 regmap_write(ipu->map, JZ_REG_IPU_Y_ADDR, ipu->addr_y); in ingenic_ipu_plane_atomic_update()
331 regmap_write(ipu->map, JZ_REG_IPU_U_ADDR, ipu->addr_u); in ingenic_ipu_plane_atomic_update()
332 regmap_write(ipu->map, JZ_REG_IPU_V_ADDR, ipu->addr_v); in ingenic_ipu_plane_atomic_update()
334 if (finfo->num_planes == 1) in ingenic_ipu_plane_atomic_update()
335 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_SPKG_SEL); in ingenic_ipu_plane_atomic_update()
337 ingenic_drm_plane_config(ipu->master, plane, DRM_FORMAT_XRGB8888); in ingenic_ipu_plane_atomic_update()
340 if (finfo->num_planes > 2) in ingenic_ipu_plane_atomic_update()
341 stride = ((state->src_w >> 16) * finfo->cpp[2] / finfo->hsub) in ingenic_ipu_plane_atomic_update()
344 if (finfo->num_planes > 1) in ingenic_ipu_plane_atomic_update()
345 stride |= ((state->src_w >> 16) * finfo->cpp[1] / finfo->hsub) in ingenic_ipu_plane_atomic_update()
348 regmap_write(ipu->map, JZ_REG_IPU_UV_STRIDE, stride); in ingenic_ipu_plane_atomic_update()
350 stride = ((state->src_w >> 16) * finfo->cpp[0]) << JZ_IPU_Y_STRIDE_Y_LSB; in ingenic_ipu_plane_atomic_update()
351 regmap_write(ipu->map, JZ_REG_IPU_Y_STRIDE, stride); in ingenic_ipu_plane_atomic_update()
353 regmap_write(ipu->map, JZ_REG_IPU_IN_GS, in ingenic_ipu_plane_atomic_update()
355 ((state->src_h >> 16) << JZ_IPU_IN_GS_H_LSB)); in ingenic_ipu_plane_atomic_update()
357 switch (finfo->format) { in ingenic_ipu_plane_atomic_update()
420 regmap_write(ipu->map, JZ_REG_IPU_D_FMT, format); in ingenic_ipu_plane_atomic_update()
423 regmap_write(ipu->map, JZ_REG_IPU_OUT_GS, in ingenic_ipu_plane_atomic_update()
424 ((state->crtc_w * 4) << JZ_IPU_OUT_GS_W_LSB) in ingenic_ipu_plane_atomic_update()
425 | state->crtc_h << JZ_IPU_OUT_GS_H_LSB); in ingenic_ipu_plane_atomic_update()
426 regmap_write(ipu->map, JZ_REG_IPU_OUT_STRIDE, state->crtc_w * 4); in ingenic_ipu_plane_atomic_update()
428 if (finfo->is_yuv) { in ingenic_ipu_plane_atomic_update()
429 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_CSC_EN); in ingenic_ipu_plane_atomic_update()
433 * y = source Y - LUMA, in ingenic_ipu_plane_atomic_update()
434 * u = source Cb - CHROMA, in ingenic_ipu_plane_atomic_update()
435 * v = source Cr - CHROMA in ingenic_ipu_plane_atomic_update()
437 regmap_write(ipu->map, JZ_REG_IPU_CSC_OFFSET, in ingenic_ipu_plane_atomic_update()
444 * G = C0 / 0x400 * y - C2 / 0x400 * u - C3 / 0x400 * v in ingenic_ipu_plane_atomic_update()
447 regmap_write(ipu->map, JZ_REG_IPU_CSC_C0_COEF, 0x4a8); in ingenic_ipu_plane_atomic_update()
448 regmap_write(ipu->map, JZ_REG_IPU_CSC_C1_COEF, 0x662); in ingenic_ipu_plane_atomic_update()
449 regmap_write(ipu->map, JZ_REG_IPU_CSC_C2_COEF, 0x191); in ingenic_ipu_plane_atomic_update()
450 regmap_write(ipu->map, JZ_REG_IPU_CSC_C3_COEF, 0x341); in ingenic_ipu_plane_atomic_update()
451 regmap_write(ipu->map, JZ_REG_IPU_CSC_C4_COEF, 0x811); in ingenic_ipu_plane_atomic_update()
461 if (ipu->soc_info->has_bicubic) in ingenic_ipu_plane_atomic_update()
464 upscaling_w = ipu->num_w > ipu->denom_w; in ingenic_ipu_plane_atomic_update()
468 if (ipu->num_w != 1 || ipu->denom_w != 1) { in ingenic_ipu_plane_atomic_update()
469 if (!ipu->soc_info->has_bicubic && !upscaling_w) in ingenic_ipu_plane_atomic_update()
470 coef_index |= (ipu->denom_w - 1) << 16; in ingenic_ipu_plane_atomic_update()
472 coef_index |= (ipu->num_w - 1) << 16; in ingenic_ipu_plane_atomic_update()
476 upscaling_h = ipu->num_h > ipu->denom_h; in ingenic_ipu_plane_atomic_update()
480 if (ipu->num_h != 1 || ipu->denom_h != 1) { in ingenic_ipu_plane_atomic_update()
481 if (!ipu->soc_info->has_bicubic && !upscaling_h) in ingenic_ipu_plane_atomic_update()
482 coef_index |= ipu->denom_h - 1; in ingenic_ipu_plane_atomic_update()
484 coef_index |= ipu->num_h - 1; in ingenic_ipu_plane_atomic_update()
488 regmap_update_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_ZOOM_SEL | in ingenic_ipu_plane_atomic_update()
493 regmap_write(ipu->map, JZ_REG_IPU_RSZ_COEF_INDEX, coef_index); in ingenic_ipu_plane_atomic_update()
495 if (ipu->num_w != 1 || ipu->denom_w != 1) in ingenic_ipu_plane_atomic_update()
497 ipu->num_w, ipu->denom_w); in ingenic_ipu_plane_atomic_update()
499 if (ipu->num_h != 1 || ipu->denom_h != 1) in ingenic_ipu_plane_atomic_update()
501 ipu->num_h, ipu->denom_h); in ingenic_ipu_plane_atomic_update()
504 regmap_write(ipu->map, JZ_REG_IPU_STATUS, 0); in ingenic_ipu_plane_atomic_update()
507 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, in ingenic_ipu_plane_atomic_update()
510 dev_dbg(ipu->dev, "Scaling %ux%u to %ux%u (%u:%u horiz, %u:%u vert)\n", in ingenic_ipu_plane_atomic_update()
511 state->src_w >> 16, state->src_h >> 16, in ingenic_ipu_plane_atomic_update()
512 state->crtc_w, state->crtc_h, in ingenic_ipu_plane_atomic_update()
513 ipu->num_w, ipu->denom_w, ipu->num_h, ipu->denom_h); in ingenic_ipu_plane_atomic_update()
521 struct drm_crtc *crtc = state->crtc ?: plane->state->crtc; in ingenic_ipu_plane_atomic_check()
527 crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc); in ingenic_ipu_plane_atomic_check()
529 return -EINVAL; in ingenic_ipu_plane_atomic_check()
532 if (!plane->state->crtc ^ !state->crtc) in ingenic_ipu_plane_atomic_check()
533 crtc_state->mode_changed = true; in ingenic_ipu_plane_atomic_check()
535 if (!state->crtc || in ingenic_ipu_plane_atomic_check()
536 !crtc_state->mode.hdisplay || !crtc_state->mode.vdisplay) in ingenic_ipu_plane_atomic_check()
540 if (state->crtc_x < 0 || state->crtc_y < 0 || in ingenic_ipu_plane_atomic_check()
541 state->crtc_x + state->crtc_w > crtc_state->mode.hdisplay || in ingenic_ipu_plane_atomic_check()
542 state->crtc_y + state->crtc_h > crtc_state->mode.vdisplay) in ingenic_ipu_plane_atomic_check()
543 return -EINVAL; in ingenic_ipu_plane_atomic_check()
546 if ((state->src_w >> 16) < 4 || (state->src_h >> 16) < 4) in ingenic_ipu_plane_atomic_check()
547 return -EINVAL; in ingenic_ipu_plane_atomic_check()
550 if (((state->src_w >> 16) & 1) || (state->crtc_w & 1)) in ingenic_ipu_plane_atomic_check()
551 return -EINVAL; in ingenic_ipu_plane_atomic_check()
553 if (!osd_changed(state, plane->state)) in ingenic_ipu_plane_atomic_check()
556 crtc_state->mode_changed = true; in ingenic_ipu_plane_atomic_check()
558 xres = state->src_w >> 16; in ingenic_ipu_plane_atomic_check()
559 yres = state->src_h >> 16; in ingenic_ipu_plane_atomic_check()
562 for (denom_w = xres, num_w = state->crtc_w; in ingenic_ipu_plane_atomic_check()
563 num_w <= crtc_state->mode.hdisplay; num_w++) in ingenic_ipu_plane_atomic_check()
566 if (num_w > crtc_state->mode.hdisplay) in ingenic_ipu_plane_atomic_check()
567 return -EINVAL; in ingenic_ipu_plane_atomic_check()
569 for (denom_h = yres, num_h = state->crtc_h; in ingenic_ipu_plane_atomic_check()
570 num_h <= crtc_state->mode.vdisplay; num_h++) in ingenic_ipu_plane_atomic_check()
573 if (num_h > crtc_state->mode.vdisplay) in ingenic_ipu_plane_atomic_check()
574 return -EINVAL; in ingenic_ipu_plane_atomic_check()
576 ipu->num_w = num_w; in ingenic_ipu_plane_atomic_check()
577 ipu->num_h = num_h; in ingenic_ipu_plane_atomic_check()
578 ipu->denom_w = denom_w; in ingenic_ipu_plane_atomic_check()
579 ipu->denom_h = denom_h; in ingenic_ipu_plane_atomic_check()
589 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_STOP); in ingenic_ipu_plane_atomic_disable()
590 regmap_clear_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_CHIP_EN); in ingenic_ipu_plane_atomic_disable()
592 ingenic_drm_plane_disable(ipu->master, plane); in ingenic_ipu_plane_atomic_disable()
594 if (ipu->clk_enabled) { in ingenic_ipu_plane_atomic_disable()
595 clk_disable(ipu->clk); in ingenic_ipu_plane_atomic_disable()
596 ipu->clk_enabled = false; in ingenic_ipu_plane_atomic_disable()
614 if (property != ipu->sharpness_prop) in ingenic_ipu_plane_atomic_get_property()
615 return -EINVAL; in ingenic_ipu_plane_atomic_get_property()
617 *val = ipu->sharpness; in ingenic_ipu_plane_atomic_get_property()
630 if (property != ipu->sharpness_prop) in ingenic_ipu_plane_atomic_set_property()
631 return -EINVAL; in ingenic_ipu_plane_atomic_set_property()
633 ipu->sharpness = val; in ingenic_ipu_plane_atomic_set_property()
635 if (state->crtc) { in ingenic_ipu_plane_atomic_set_property()
636 crtc_state = drm_atomic_get_existing_crtc_state(state->state, state->crtc); in ingenic_ipu_plane_atomic_set_property()
638 return -EINVAL; in ingenic_ipu_plane_atomic_set_property()
640 crtc_state->mode_changed = true; in ingenic_ipu_plane_atomic_set_property()
662 struct drm_crtc *crtc = drm_crtc_from_index(ipu->drm, 0); in ingenic_ipu_irq_handler()
666 if (ipu->soc_info->manual_restart) in ingenic_ipu_irq_handler()
667 regmap_read(ipu->map, JZ_REG_IPU_STATUS, &dummy); in ingenic_ipu_irq_handler()
670 regmap_write(ipu->map, JZ_REG_IPU_STATUS, 0); in ingenic_ipu_irq_handler()
672 /* Set previously cached addresses */ in ingenic_ipu_irq_handler()
673 regmap_write(ipu->map, JZ_REG_IPU_Y_ADDR, ipu->addr_y); in ingenic_ipu_irq_handler()
674 regmap_write(ipu->map, JZ_REG_IPU_U_ADDR, ipu->addr_u); in ingenic_ipu_irq_handler()
675 regmap_write(ipu->map, JZ_REG_IPU_V_ADDR, ipu->addr_v); in ingenic_ipu_irq_handler()
678 if (ipu->soc_info->manual_restart) in ingenic_ipu_irq_handler()
679 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_RUN); in ingenic_ipu_irq_handler()
707 return -ENOMEM; in ingenic_ipu_bind()
712 return -EINVAL; in ingenic_ipu_bind()
715 ipu->dev = dev; in ingenic_ipu_bind()
716 ipu->drm = drm; in ingenic_ipu_bind()
717 ipu->master = master; in ingenic_ipu_bind()
718 ipu->soc_info = soc_info; in ingenic_ipu_bind()
726 ipu->map = devm_regmap_init_mmio(dev, base, &ingenic_ipu_regmap_config); in ingenic_ipu_bind()
727 if (IS_ERR(ipu->map)) { in ingenic_ipu_bind()
729 return PTR_ERR(ipu->map); in ingenic_ipu_bind()
736 ipu->clk = devm_clk_get(dev, "ipu"); in ingenic_ipu_bind()
737 if (IS_ERR(ipu->clk)) { in ingenic_ipu_bind()
739 return PTR_ERR(ipu->clk); in ingenic_ipu_bind()
749 plane = &ipu->plane; in ingenic_ipu_bind()
755 soc_info->formats, soc_info->num_formats, in ingenic_ipu_bind()
764 * 0 : nearest-neighbor in ingenic_ipu_bind()
766 * 2 .. 32 : bicubic (translated to sharpness factor -0.25 .. -4.0) in ingenic_ipu_bind()
768 sharpness_max = soc_info->has_bicubic ? 32 : 1; in ingenic_ipu_bind()
769 ipu->sharpness_prop = drm_property_create_range(drm, 0, "sharpness", in ingenic_ipu_bind()
771 if (!ipu->sharpness_prop) { in ingenic_ipu_bind()
773 return -ENOMEM; in ingenic_ipu_bind()
776 /* Default sharpness factor: -0.125 * 8 = -1.0 */ in ingenic_ipu_bind()
777 ipu->sharpness = soc_info->has_bicubic ? 8 : 1; in ingenic_ipu_bind()
778 drm_object_attach_property(&plane->base, ipu->sharpness_prop, in ingenic_ipu_bind()
779 ipu->sharpness); in ingenic_ipu_bind()
781 err = clk_prepare(ipu->clk); in ingenic_ipu_bind()
795 clk_unprepare(ipu->clk); in ingenic_ipu_unbind()
805 return component_add(&pdev->dev, &ingenic_ipu_ops); in ingenic_ipu_probe()
810 component_del(&pdev->dev, &ingenic_ipu_ops); in ingenic_ipu_remove()
866 { .compatible = "ingenic,jz4725b-ipu", .data = &jz4725b_soc_info },
867 { .compatible = "ingenic,jz4760-ipu", .data = &jz4760_soc_info },
874 .name = "ingenic-ipu",