Lines Matching +full:jz4725b +full:- +full:lcd

1 // SPDX-License-Identifier: GPL-2.0
8 #include "ingenic-drm.h"
9 #include "ingenic-ipu.h"
71 /* Signed 15.16 fixed-point math (for bicubic scaling coefficients) */
75 #define SHARPNESS_INCR (I2F(-1) / 8)
93 priv_state = drm_atomic_get_private_obj_state(state, &priv->private_obj); in ingenic_ipu_get_priv_state()
105 priv_state = drm_atomic_get_new_private_obj_state(state, &priv->private_obj); in ingenic_ipu_get_new_priv_state()
114 * and return value are 15.16 signed fixed-point.
116 * @f_a: Sharpness factor, typically in range [-4.0, -0.25].
118 * -2.0 might cause ringing artifacts to outweigh any improvement.
119 * Nice values on a 320x240 LCD are between -0.75 and -2.0.
124 * returns: Weight of this pixel within 4-pixel sample group. Range is
125 * [-2.0, +2.0]. For moderate (i.e. > -3.0) sharpness factors,
126 * range is within [-1.0, +1.0].
138 return FMUL((f_a + f_2), f_x3) - FMUL((f_a + f_3), f_x2) + f_1; in cubic_conv()
140 return FMUL(f_a, (f_x3 - 5 * f_x2 + 8 * f_x - f_4)); in cubic_conv()
160 s32 w0, w1, w2, w3; /* Pixel weights at X (or Y) offsets -1,0,1,2 */ in jz4760_set_coefs()
166 * When sharpness setting is 0, emulate nearest-neighbor. in jz4760_set_coefs()
174 w2 = 512 - weight; in jz4760_set_coefs()
182 * The resulting coefficients match a round-to-nearest-int in jz4760_set_coefs()
183 * double floating-point implementation. in jz4760_set_coefs()
186 weight = 512 - weight; in jz4760_set_coefs()
189 w2 = F2I(f_h + 512 * cubic_conv(f_a, I2F(512 - weight) / 512)); in jz4760_set_coefs()
190 w3 = F2I(f_h + 512 * cubic_conv(f_a, I2F(1024 - weight) / 512)); in jz4760_set_coefs()
191 w0 = clamp_val(w0, -1024, 1023); in jz4760_set_coefs()
192 w1 = clamp_val(w1, -1024, 1023); in jz4760_set_coefs()
193 w2 = clamp_val(w2, -1024, 1023); in jz4760_set_coefs()
194 w3 = clamp_val(w3, -1024, 1023); in jz4760_set_coefs()
199 regmap_write(ipu->map, reg, val); in jz4760_set_coefs()
204 regmap_write(ipu->map, reg, val); in jz4760_set_coefs()
223 regmap_write(ipu->map, reg, val); in jz4725b_set_coefs()
227 regmap_write(ipu->map, reg, JZ4725B_IPU_RSZ_LUT_IN_EN); in jz4725b_set_coefs()
239 weight_num = num + (weight_num - num) % (num * 2); in ingenic_ipu_set_downscale_coefs()
240 weight = 512 - 512 * (weight_num - num) / (num * 2); in ingenic_ipu_set_downscale_coefs()
242 offset = (weight_num - num) / (num * 2); in ingenic_ipu_set_downscale_coefs()
244 ipu->soc_info->set_coefs(ipu, reg, ipu->sharpness, in ingenic_ipu_set_downscale_coefs()
254 * Force nearest-neighbor scaling and use simple math when upscaling in ingenic_ipu_set_integer_upscale_coefs()
260 ipu->soc_info->set_coefs(ipu, reg, 0, false, 512, i == num - 1); in ingenic_ipu_set_integer_upscale_coefs()
271 weight = 512 - 512 * weight_num / num; in ingenic_ipu_set_upscale_coefs()
276 weight_num -= num; in ingenic_ipu_set_upscale_coefs()
278 ipu->soc_info->set_coefs(ipu, reg, ipu->sharpness, in ingenic_ipu_set_upscale_coefs()
287 regmap_write(ipu->map, reg, -1); in ingenic_ipu_set_coefs()
303 return -EINVAL; in reduce_fraction()
313 return state->src_x != oldstate->src_x || in osd_changed()
314 state->src_y != oldstate->src_y || in osd_changed()
315 state->src_w != oldstate->src_w || in osd_changed()
316 state->src_h != oldstate->src_h || in osd_changed()
317 state->crtc_x != oldstate->crtc_x || in osd_changed()
318 state->crtc_y != oldstate->crtc_y || in osd_changed()
319 state->crtc_w != oldstate->crtc_w || in osd_changed()
320 state->crtc_h != oldstate->crtc_h; in osd_changed()
335 if (!newstate || !newstate->fb) in ingenic_ipu_plane_atomic_update()
342 finfo = drm_format_info(newstate->fb->format->format); in ingenic_ipu_plane_atomic_update()
344 if (!ipu->clk_enabled) { in ingenic_ipu_plane_atomic_update()
345 err = clk_enable(ipu->clk); in ingenic_ipu_plane_atomic_update()
347 dev_err(ipu->dev, "Unable to enable clock: %d\n", err); in ingenic_ipu_plane_atomic_update()
351 ipu->clk_enabled = true; in ingenic_ipu_plane_atomic_update()
355 needs_modeset = drm_atomic_crtc_needs_modeset(newstate->crtc->state); in ingenic_ipu_plane_atomic_update()
357 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_RST); in ingenic_ipu_plane_atomic_update()
360 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, in ingenic_ipu_plane_atomic_update()
364 if (ingenic_drm_map_noncoherent(ipu->master)) in ingenic_ipu_plane_atomic_update()
365 drm_fb_dma_sync_non_coherent(ipu->drm, oldstate, newstate); in ingenic_ipu_plane_atomic_update()
368 ipu->addr_y = drm_fb_dma_get_gem_addr(newstate->fb, newstate, 0); in ingenic_ipu_plane_atomic_update()
369 if (finfo->num_planes > 1) in ingenic_ipu_plane_atomic_update()
370 ipu->addr_u = drm_fb_dma_get_gem_addr(newstate->fb, newstate, in ingenic_ipu_plane_atomic_update()
372 if (finfo->num_planes > 2) in ingenic_ipu_plane_atomic_update()
373 ipu->addr_v = drm_fb_dma_get_gem_addr(newstate->fb, newstate, in ingenic_ipu_plane_atomic_update()
380 regmap_write(ipu->map, JZ_REG_IPU_Y_ADDR, ipu->addr_y); in ingenic_ipu_plane_atomic_update()
381 regmap_write(ipu->map, JZ_REG_IPU_U_ADDR, ipu->addr_u); in ingenic_ipu_plane_atomic_update()
382 regmap_write(ipu->map, JZ_REG_IPU_V_ADDR, ipu->addr_v); in ingenic_ipu_plane_atomic_update()
384 if (finfo->num_planes == 1) in ingenic_ipu_plane_atomic_update()
385 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_SPKG_SEL); in ingenic_ipu_plane_atomic_update()
387 ingenic_drm_plane_config(ipu->master, plane, DRM_FORMAT_XRGB8888); in ingenic_ipu_plane_atomic_update()
390 if (finfo->num_planes > 2) in ingenic_ipu_plane_atomic_update()
391 stride = ((newstate->src_w >> 16) * finfo->cpp[2] / finfo->hsub) in ingenic_ipu_plane_atomic_update()
394 if (finfo->num_planes > 1) in ingenic_ipu_plane_atomic_update()
395 stride |= ((newstate->src_w >> 16) * finfo->cpp[1] / finfo->hsub) in ingenic_ipu_plane_atomic_update()
398 regmap_write(ipu->map, JZ_REG_IPU_UV_STRIDE, stride); in ingenic_ipu_plane_atomic_update()
400 stride = ((newstate->src_w >> 16) * finfo->cpp[0]) << JZ_IPU_Y_STRIDE_Y_LSB; in ingenic_ipu_plane_atomic_update()
401 regmap_write(ipu->map, JZ_REG_IPU_Y_STRIDE, stride); in ingenic_ipu_plane_atomic_update()
403 regmap_write(ipu->map, JZ_REG_IPU_IN_GS, in ingenic_ipu_plane_atomic_update()
405 ((newstate->src_h >> 16) << JZ_IPU_IN_GS_H_LSB)); in ingenic_ipu_plane_atomic_update()
407 switch (finfo->format) { in ingenic_ipu_plane_atomic_update()
470 regmap_write(ipu->map, JZ_REG_IPU_D_FMT, format); in ingenic_ipu_plane_atomic_update()
473 regmap_write(ipu->map, JZ_REG_IPU_OUT_GS, in ingenic_ipu_plane_atomic_update()
474 ((newstate->crtc_w * 4) << JZ_IPU_OUT_GS_W_LSB) in ingenic_ipu_plane_atomic_update()
475 | newstate->crtc_h << JZ_IPU_OUT_GS_H_LSB); in ingenic_ipu_plane_atomic_update()
476 regmap_write(ipu->map, JZ_REG_IPU_OUT_STRIDE, newstate->crtc_w * 4); in ingenic_ipu_plane_atomic_update()
478 if (finfo->is_yuv) { in ingenic_ipu_plane_atomic_update()
479 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_CSC_EN); in ingenic_ipu_plane_atomic_update()
483 * y = source Y - LUMA, in ingenic_ipu_plane_atomic_update()
484 * u = source Cb - CHROMA, in ingenic_ipu_plane_atomic_update()
485 * v = source Cr - CHROMA in ingenic_ipu_plane_atomic_update()
487 regmap_write(ipu->map, JZ_REG_IPU_CSC_OFFSET, in ingenic_ipu_plane_atomic_update()
494 * G = C0 / 0x400 * y - C2 / 0x400 * u - C3 / 0x400 * v in ingenic_ipu_plane_atomic_update()
497 regmap_write(ipu->map, JZ_REG_IPU_CSC_C0_COEF, 0x4a8); in ingenic_ipu_plane_atomic_update()
498 regmap_write(ipu->map, JZ_REG_IPU_CSC_C1_COEF, 0x662); in ingenic_ipu_plane_atomic_update()
499 regmap_write(ipu->map, JZ_REG_IPU_CSC_C2_COEF, 0x191); in ingenic_ipu_plane_atomic_update()
500 regmap_write(ipu->map, JZ_REG_IPU_CSC_C3_COEF, 0x341); in ingenic_ipu_plane_atomic_update()
501 regmap_write(ipu->map, JZ_REG_IPU_CSC_C4_COEF, 0x811); in ingenic_ipu_plane_atomic_update()
511 if (ipu->soc_info->has_bicubic) in ingenic_ipu_plane_atomic_update()
514 upscaling_w = ipu_state->num_w > ipu_state->denom_w; in ingenic_ipu_plane_atomic_update()
518 if (ipu_state->num_w != 1 || ipu_state->denom_w != 1) { in ingenic_ipu_plane_atomic_update()
519 if (!ipu->soc_info->has_bicubic && !upscaling_w) in ingenic_ipu_plane_atomic_update()
520 coef_index |= (ipu_state->denom_w - 1) << 16; in ingenic_ipu_plane_atomic_update()
522 coef_index |= (ipu_state->num_w - 1) << 16; in ingenic_ipu_plane_atomic_update()
526 upscaling_h = ipu_state->num_h > ipu_state->denom_h; in ingenic_ipu_plane_atomic_update()
530 if (ipu_state->num_h != 1 || ipu_state->denom_h != 1) { in ingenic_ipu_plane_atomic_update()
531 if (!ipu->soc_info->has_bicubic && !upscaling_h) in ingenic_ipu_plane_atomic_update()
532 coef_index |= ipu_state->denom_h - 1; in ingenic_ipu_plane_atomic_update()
534 coef_index |= ipu_state->num_h - 1; in ingenic_ipu_plane_atomic_update()
538 regmap_update_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_ZOOM_SEL | in ingenic_ipu_plane_atomic_update()
543 regmap_write(ipu->map, JZ_REG_IPU_RSZ_COEF_INDEX, coef_index); in ingenic_ipu_plane_atomic_update()
545 if (ipu_state->num_w != 1 || ipu_state->denom_w != 1) in ingenic_ipu_plane_atomic_update()
547 ipu_state->num_w, ipu_state->denom_w); in ingenic_ipu_plane_atomic_update()
549 if (ipu_state->num_h != 1 || ipu_state->denom_h != 1) in ingenic_ipu_plane_atomic_update()
551 ipu_state->num_h, ipu_state->denom_h); in ingenic_ipu_plane_atomic_update()
554 regmap_write(ipu->map, JZ_REG_IPU_STATUS, 0); in ingenic_ipu_plane_atomic_update()
557 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, in ingenic_ipu_plane_atomic_update()
560 dev_dbg(ipu->dev, "Scaling %ux%u to %ux%u (%u:%u horiz, %u:%u vert)\n", in ingenic_ipu_plane_atomic_update()
561 newstate->src_w >> 16, newstate->src_h >> 16, in ingenic_ipu_plane_atomic_update()
562 newstate->crtc_w, newstate->crtc_h, in ingenic_ipu_plane_atomic_update()
563 ipu_state->num_w, ipu_state->denom_w, in ingenic_ipu_plane_atomic_update()
564 ipu_state->num_h, ipu_state->denom_h); in ingenic_ipu_plane_atomic_update()
576 struct drm_crtc *crtc = new_plane_state->crtc ?: old_plane_state->crtc; in ingenic_ipu_plane_atomic_check()
585 return -EINVAL; in ingenic_ipu_plane_atomic_check()
592 if (!old_plane_state->crtc ^ !new_plane_state->crtc) in ingenic_ipu_plane_atomic_check()
593 crtc_state->mode_changed = true; in ingenic_ipu_plane_atomic_check()
595 if (!new_plane_state->crtc || in ingenic_ipu_plane_atomic_check()
596 !crtc_state->mode.hdisplay || !crtc_state->mode.vdisplay) in ingenic_ipu_plane_atomic_check()
600 if (new_plane_state->crtc_x < 0 || new_plane_state->crtc_y < 0 || in ingenic_ipu_plane_atomic_check()
601 new_plane_state->crtc_x + new_plane_state->crtc_w > crtc_state->mode.hdisplay || in ingenic_ipu_plane_atomic_check()
602 new_plane_state->crtc_y + new_plane_state->crtc_h > crtc_state->mode.vdisplay) in ingenic_ipu_plane_atomic_check()
603 return -EINVAL; in ingenic_ipu_plane_atomic_check()
606 if ((new_plane_state->src_w >> 16) < 4 || (new_plane_state->src_h >> 16) < 4) in ingenic_ipu_plane_atomic_check()
607 return -EINVAL; in ingenic_ipu_plane_atomic_check()
610 if (((new_plane_state->src_w >> 16) & 1) || (new_plane_state->crtc_w & 1)) in ingenic_ipu_plane_atomic_check()
611 return -EINVAL; in ingenic_ipu_plane_atomic_check()
616 crtc_state->mode_changed = true; in ingenic_ipu_plane_atomic_check()
618 xres = new_plane_state->src_w >> 16; in ingenic_ipu_plane_atomic_check()
619 yres = new_plane_state->src_h >> 16; in ingenic_ipu_plane_atomic_check()
628 max_w = crtc_state->mode.hdisplay * 102 / 100; in ingenic_ipu_plane_atomic_check()
629 max_h = crtc_state->mode.vdisplay * 102 / 100; in ingenic_ipu_plane_atomic_check()
631 for (denom_w = xres, num_w = new_plane_state->crtc_w; num_w <= max_w; num_w++) in ingenic_ipu_plane_atomic_check()
635 return -EINVAL; in ingenic_ipu_plane_atomic_check()
637 for (denom_h = yres, num_h = new_plane_state->crtc_h; num_h <= max_h; num_h++) in ingenic_ipu_plane_atomic_check()
641 return -EINVAL; in ingenic_ipu_plane_atomic_check()
643 ipu_state->num_w = num_w; in ingenic_ipu_plane_atomic_check()
644 ipu_state->num_h = num_h; in ingenic_ipu_plane_atomic_check()
645 ipu_state->denom_w = denom_w; in ingenic_ipu_plane_atomic_check()
646 ipu_state->denom_h = denom_h; in ingenic_ipu_plane_atomic_check()
649 if (ingenic_drm_map_noncoherent(ipu->master)) in ingenic_ipu_plane_atomic_check()
660 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_STOP); in ingenic_ipu_plane_atomic_disable()
661 regmap_clear_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_CHIP_EN); in ingenic_ipu_plane_atomic_disable()
663 ingenic_drm_plane_disable(ipu->master, plane); in ingenic_ipu_plane_atomic_disable()
665 if (ipu->clk_enabled) { in ingenic_ipu_plane_atomic_disable()
666 clk_disable(ipu->clk); in ingenic_ipu_plane_atomic_disable()
667 ipu->clk_enabled = false; in ingenic_ipu_plane_atomic_disable()
684 if (property != ipu->sharpness_prop) in ingenic_ipu_plane_atomic_get_property()
685 return -EINVAL; in ingenic_ipu_plane_atomic_get_property()
687 *val = ipu->sharpness; in ingenic_ipu_plane_atomic_get_property()
701 if (property != ipu->sharpness_prop) in ingenic_ipu_plane_atomic_set_property()
702 return -EINVAL; in ingenic_ipu_plane_atomic_set_property()
704 mode_changed = val != ipu->sharpness; in ingenic_ipu_plane_atomic_set_property()
705 ipu->sharpness = val; in ingenic_ipu_plane_atomic_set_property()
707 if (state->crtc) { in ingenic_ipu_plane_atomic_set_property()
708 crtc_state = drm_atomic_get_existing_crtc_state(state->state, state->crtc); in ingenic_ipu_plane_atomic_set_property()
710 return -EINVAL; in ingenic_ipu_plane_atomic_set_property()
712 crtc_state->mode_changed |= mode_changed; in ingenic_ipu_plane_atomic_set_property()
734 struct ingenic_ipu_private_state *state = to_ingenic_ipu_priv_state(obj->state); in ingenic_ipu_duplicate_state()
740 __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base); in ingenic_ipu_duplicate_state()
742 return &state->base; in ingenic_ipu_duplicate_state()
761 struct drm_crtc *crtc = drm_crtc_from_index(ipu->drm, 0); in ingenic_ipu_irq_handler()
765 if (ipu->soc_info->manual_restart) in ingenic_ipu_irq_handler()
766 regmap_read(ipu->map, JZ_REG_IPU_STATUS, &dummy); in ingenic_ipu_irq_handler()
769 regmap_write(ipu->map, JZ_REG_IPU_STATUS, 0); in ingenic_ipu_irq_handler()
772 regmap_write(ipu->map, JZ_REG_IPU_Y_ADDR, ipu->addr_y); in ingenic_ipu_irq_handler()
773 regmap_write(ipu->map, JZ_REG_IPU_U_ADDR, ipu->addr_u); in ingenic_ipu_irq_handler()
774 regmap_write(ipu->map, JZ_REG_IPU_V_ADDR, ipu->addr_v); in ingenic_ipu_irq_handler()
777 if (ipu->soc_info->manual_restart) in ingenic_ipu_irq_handler()
778 regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_RUN); in ingenic_ipu_irq_handler()
807 return -ENOMEM; in ingenic_ipu_bind()
812 return -EINVAL; in ingenic_ipu_bind()
815 ipu->dev = dev; in ingenic_ipu_bind()
816 ipu->drm = drm; in ingenic_ipu_bind()
817 ipu->master = master; in ingenic_ipu_bind()
818 ipu->soc_info = soc_info; in ingenic_ipu_bind()
826 ipu->map = devm_regmap_init_mmio(dev, base, &ingenic_ipu_regmap_config); in ingenic_ipu_bind()
827 if (IS_ERR(ipu->map)) { in ingenic_ipu_bind()
829 return PTR_ERR(ipu->map); in ingenic_ipu_bind()
836 ipu->clk = devm_clk_get(dev, "ipu"); in ingenic_ipu_bind()
837 if (IS_ERR(ipu->clk)) { in ingenic_ipu_bind()
839 return PTR_ERR(ipu->clk); in ingenic_ipu_bind()
849 plane = &ipu->plane; in ingenic_ipu_bind()
855 soc_info->formats, soc_info->num_formats, in ingenic_ipu_bind()
867 * 0 : nearest-neighbor in ingenic_ipu_bind()
869 * 2 .. 32 : bicubic (translated to sharpness factor -0.25 .. -4.0) in ingenic_ipu_bind()
871 sharpness_max = soc_info->has_bicubic ? 32 : 1; in ingenic_ipu_bind()
872 ipu->sharpness_prop = drm_property_create_range(drm, 0, "sharpness", in ingenic_ipu_bind()
874 if (!ipu->sharpness_prop) { in ingenic_ipu_bind()
876 return -ENOMEM; in ingenic_ipu_bind()
879 /* Default sharpness factor: -0.125 * 8 = -1.0 */ in ingenic_ipu_bind()
880 ipu->sharpness = soc_info->has_bicubic ? 8 : 1; in ingenic_ipu_bind()
881 drm_object_attach_property(&plane->base, ipu->sharpness_prop, in ingenic_ipu_bind()
882 ipu->sharpness); in ingenic_ipu_bind()
884 err = clk_prepare(ipu->clk); in ingenic_ipu_bind()
892 err = -ENOMEM; in ingenic_ipu_bind()
896 drm_atomic_private_obj_init(drm, &ipu->private_obj, &private_state->base, in ingenic_ipu_bind()
902 clk_unprepare(ipu->clk); in ingenic_ipu_bind()
911 drm_atomic_private_obj_fini(&ipu->private_obj); in ingenic_ipu_unbind()
912 clk_unprepare(ipu->clk); in ingenic_ipu_unbind()
922 return component_add(&pdev->dev, &ingenic_ipu_ops); in ingenic_ipu_probe()
927 component_del(&pdev->dev, &ingenic_ipu_ops); in ingenic_ipu_remove()
933 * random hardware crashes on JZ4725B under certain circumstances.
982 { .compatible = "ingenic,jz4725b-ipu", .data = &jz4725b_soc_info },
983 { .compatible = "ingenic,jz4760-ipu", .data = &jz4760_soc_info },
990 .name = "ingenic-ipu",