From 70f2a67d360a1f74c1a6cfb9fc08e4223ad14554 Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Thu, 21 Dec 2017 20:30:37 +0800 Subject: [PATCH] drm/rockchip: vop: fix hdr2sdr csc error Change-Id: I9792f14675527ff192e77ea7f9fe0f58b09e54b3 Signed-off-by: Sandy Huang --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 68 ++++++++++++--------- drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 1 + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 7 ++- 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 5541c002b137..09f9b74493ee 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -732,7 +732,6 @@ static int vop_hdr_atomic_check(struct drm_crtc *crtc, if (!vop->data->hdr_table) return 0; /* hdr cover */ - s->yuv_overlay = is_yuv_output(s->bus_format); drm_atomic_crtc_state_for_each_plane(plane, crtc_state) { struct vop_plane_state *vop_plane_state; struct vop_win *win = to_vop_win(plane); @@ -2278,11 +2277,8 @@ static void vop_update_csc(struct drm_crtc *crtc) s->output_mode == ROCKCHIP_OUT_MODE_YUV420 ? 1 : 0); VOP_CTRL_SET(vop, hdmi_dclk_out_en, s->output_mode == ROCKCHIP_OUT_MODE_YUV420 ? 1 : 0); - s->yuv_overlay = 0; - if (VOP_CTRL_SUPPORT(vop, overlay_mode)) { - s->yuv_overlay = is_yuv_output(s->bus_format); - VOP_CTRL_SET(vop, overlay_mode, s->yuv_overlay); - } + + VOP_CTRL_SET(vop, overlay_mode, s->yuv_overlay); VOP_CTRL_SET(vop, dsp_out_yuv, is_yuv_output(s->bus_format)); /* @@ -2583,6 +2579,10 @@ static int vop_crtc_atomic_check(struct drm_crtc *crtc, if (ret) return ret; + s->yuv_overlay = 0; + if (VOP_CTRL_SUPPORT(vop, overlay_mode)) + s->yuv_overlay = is_yuv_output(s->bus_format); + ret = vop_hdr_atomic_check(crtc, crtc_state); if (ret) return ret; @@ -2750,8 +2750,14 @@ static void vop_update_hdr(struct drm_crtc *crtc, if (!vop->data->hdr_table) return; - if (s->hdr.hdr2sdr_en) + if (s->hdr.hdr2sdr_en) { vop_load_hdr2sdr_table(vop); + /* This is ic design bug, when in hdr2sdr mode, the overlay mode + * is rgb deomain, so the win0 is do yuv2rgb, but in this case, + * we must close win0 y2r. + */ + VOP_CTRL_SET(vop, hdr2sdr_en_win0_csc, 0); + } VOP_CTRL_SET(vop, hdr2sdr_en, s->hdr.hdr2sdr_en); VOP_CTRL_SET(vop, bt1886eotf_pre_conv_en, @@ -2759,33 +2765,23 @@ static void vop_update_hdr(struct drm_crtc *crtc, VOP_CTRL_SET(vop, bt1886eotf_post_conv_en, sdr2hdr_state->bt1886eotf_post_conv_en); - if (sdr2hdr_state->bt1886eotf_pre_conv_en) { - VOP_CTRL_SET(vop, rgb2rgb_pre_conv_en, - sdr2hdr_state->rgb2rgb_pre_conv_en); - VOP_CTRL_SET(vop, rgb2rgb_pre_conv_mode, - sdr2hdr_state->rgb2rgb_pre_conv_mode); - VOP_CTRL_SET(vop, st2084oetf_pre_conv_en, - sdr2hdr_state->st2084oetf_pre_conv_en); - } + VOP_CTRL_SET(vop, rgb2rgb_pre_conv_en, + sdr2hdr_state->rgb2rgb_pre_conv_en); + VOP_CTRL_SET(vop, rgb2rgb_pre_conv_mode, + sdr2hdr_state->rgb2rgb_pre_conv_mode); + VOP_CTRL_SET(vop, st2084oetf_pre_conv_en, + sdr2hdr_state->st2084oetf_pre_conv_en); - if (sdr2hdr_state->bt1886eotf_post_conv_en) { - VOP_CTRL_SET(vop, rgb2rgb_post_conv_en, - sdr2hdr_state->rgb2rgb_post_conv_en); - VOP_CTRL_SET(vop, rgb2rgb_post_conv_mode, - sdr2hdr_state->rgb2rgb_post_conv_mode); - VOP_CTRL_SET(vop, st2084oetf_post_conv_en, - sdr2hdr_state->st2084oetf_post_conv_en); - } + VOP_CTRL_SET(vop, rgb2rgb_post_conv_en, + sdr2hdr_state->rgb2rgb_post_conv_en); + VOP_CTRL_SET(vop, rgb2rgb_post_conv_mode, + sdr2hdr_state->rgb2rgb_post_conv_mode); + VOP_CTRL_SET(vop, st2084oetf_post_conv_en, + sdr2hdr_state->st2084oetf_post_conv_en); if (sdr2hdr_state->bt1886eotf_pre_conv_en || sdr2hdr_state->bt1886eotf_post_conv_en) vop_load_sdr2hdr_table(vop, sdr2hdr_state->sdr2hdr_func); - - /* TODO: maybe need move to irq func */ - VOP_CTRL_SET(vop, level2_overlay_en, s->hdr.pre_overlay); - VOP_CTRL_SET(vop, alpha_hard_calc, s->hdr.pre_overlay); - - VOP_CTRL_SET(vop, overlay_mode, s->yuv_overlay); } static void vop_update_cabc(struct drm_crtc *crtc, @@ -2830,6 +2826,8 @@ static void vop_tv_config_update(struct drm_crtc *crtc, { struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); + struct rockchip_crtc_state *old_s = + to_rockchip_crtc_state(old_crtc_state); int brightness, contrast, saturation, hue, sin_hue, cos_hue; struct vop *vop = to_vop(crtc); const struct vop_data *vop_data = vop->data; @@ -2837,7 +2835,10 @@ static void vop_tv_config_update(struct drm_crtc *crtc, if (!s->tv_state) return; - if (!memcmp(s->tv_state, &vop->active_tv_state, sizeof(*s->tv_state))) + if (!memcmp(s->tv_state, + &vop->active_tv_state, sizeof(*s->tv_state)) && + s->yuv_overlay == old_s->yuv_overlay && + s->bcsh_en == old_s->bcsh_en) return; memcpy(&vop->active_tv_state, s->tv_state, sizeof(*s->tv_state)); @@ -3322,6 +3323,7 @@ static irqreturn_t vop_isr(int irq, void *data) { struct vop *vop = data; struct drm_crtc *crtc = &vop->crtc; + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); uint32_t active_irqs; unsigned long flags; int ret = IRQ_NONE; @@ -3360,6 +3362,12 @@ static irqreturn_t vop_isr(int irq, void *data) vop_handle_vblank(vop); active_irqs &= ~FS_INTR; ret = IRQ_HANDLED; + /* This is IC design bug, this two register bit need frame + * effective, but actually it's effective immediately, so we + * config this register at frame start. + */ + VOP_CTRL_SET(vop, level2_overlay_en, s->hdr.pre_overlay); + VOP_CTRL_SET(vop, alpha_hard_calc, s->hdr.pre_overlay); } #define ERROR_HANDLER(x) \ diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 04710aba57e9..fd944d6a8615 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -207,6 +207,7 @@ struct vop_ctrl { struct vop_reg level2_overlay_en; struct vop_reg alpha_hard_calc; struct vop_reg hdr2sdr_en; + struct vop_reg hdr2sdr_en_win0_csc; struct vop_reg hdr2sdr_src_min; struct vop_reg hdr2sdr_src_max; struct vop_reg hdr2sdr_normfaceetf; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 9d92b9a55e67..8e0619317a6a 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -911,6 +911,7 @@ static const struct vop_ctrl rk3328_ctrl_data = { .level2_overlay_en = VOP_REG(RK3328_SYS_CTRL1, 0x1, 28), .hdr2sdr_en = VOP_REG(RK3328_HDR2DR_CTRL, 0x1, 0), + .hdr2sdr_en_win0_csc = VOP_REG(RK3328_SDR2HDR_CTRL, 0x1, 9), .hdr2sdr_src_min = VOP_REG(RK3328_HDR2DR_SRC_RANGE, 0x3fff, 0), .hdr2sdr_src_max = VOP_REG(RK3328_HDR2DR_SRC_RANGE, 0x3fff, 16), .hdr2sdr_normfaceetf = VOP_REG(RK3328_HDR2DR_NORMFACEETF, 0x7ff, 0), @@ -935,9 +936,9 @@ static const struct vop_ctrl rk3328_ctrl_data = { .bcsh_sin_hue = VOP_REG(RK3328_BCSH_H, 0x1ff, 0), .bcsh_cos_hue = VOP_REG(RK3328_BCSH_H, 0x1ff, 16), .bcsh_r2y_csc_mode = VOP_REG(RK3328_BCSH_CTRL, 0x3, 6), - .bcsh_r2y_en = VOP_REG(RK3368_BCSH_CTRL, 0x1, 4), - .bcsh_y2r_csc_mode = VOP_REG(RK3368_BCSH_CTRL, 0x3, 2), - .bcsh_y2r_en = VOP_REG(RK3368_BCSH_CTRL, 0x1, 0), + .bcsh_r2y_en = VOP_REG(RK3328_BCSH_CTRL, 0x1, 4), + .bcsh_y2r_csc_mode = VOP_REG(RK3328_BCSH_CTRL, 0x3, 2), + .bcsh_y2r_en = VOP_REG(RK3328_BCSH_CTRL, 0x1, 0), .bcsh_color_bar = VOP_REG(RK3328_BCSH_COLOR_BAR, 0xffffff, 8), .bcsh_en = VOP_REG(RK3328_BCSH_COLOR_BAR, 0x1, 0),