From 363b2d2f7b9938b28974e2992633629aca1180cd Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Thu, 24 Dec 2020 15:55:43 +0800 Subject: [PATCH] drm/rockchip: vop2: Fix HDR2SDR 1. Add hdr2sdr_bypass_en and hdr2sdr_auto_gating_en bits, which unmentationed in TRM. 2. HDR2SDR and SDR2HDR should overlay in RGB color space. 3. Window csc should be disabled when HDR2SDR or SDR2HDR enabled. Change-Id: Ic3e15c3f0ddb5adf23a4962366749228f5117a9f Signed-off-by: Andy Yan --- drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 4 +- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 60 +++++++++++++++----- drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 4 +- 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index c77e36a905fc..e46007521f92 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -557,8 +557,10 @@ struct vop2_video_port_regs { struct vop_reg sdr2hdr_r2r_mode; struct vop_reg sdr2hdr_oetf_en; struct vop_reg sdr2hdr_bypass_en; - struct vop_reg sdr2hdr_gating_en; + struct vop_reg sdr2hdr_auto_gating_en; struct vop_reg hdr2sdr_en; + struct vop_reg hdr2sdr_bypass_en; + struct vop_reg hdr2sdr_auto_gating_en; 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_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index bf7171309b88..44bf6fd03bc7 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -216,6 +216,8 @@ struct vop2_plane_state { dma_addr_t yrgb_mst; dma_addr_t uv_mst; bool afbc_en; + bool hdr_in; + bool hdr2sdr_en; bool r2y_en; bool y2r_en; uint32_t csc_mode; @@ -349,6 +351,11 @@ struct vop2_video_port { * */ bool hdr_out; + /* + * @sdr2hdr_en: All the ui plane need to do sdr2hdr for a hdr_out enabled vp. + * + */ + bool sdr2hdr_en; /** * @bg_ovl_dly: The timing delay from background layer @@ -1286,18 +1293,29 @@ static void vop2_disable_all_planes_for_crtc(struct drm_crtc *crtc) * 11. RGB --> bypass --> RGB_OUTPUT(709) */ -static void vop2_setup_csc_mode(struct rockchip_crtc_state *vcstate, +static void vop2_setup_csc_mode(struct vop2_video_port *vp, struct vop2_plane_state *vpstate) { struct drm_plane_state *pstate = &vpstate->base; + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state); int is_input_yuv = is_yuv_support(pstate->fb->format->format); - int is_output_yuv = is_yuv_output(vcstate->bus_format); + int is_output_yuv = vcstate->yuv_overlay; int input_csc = vpstate->color_space; int output_csc = vcstate->color_space; vpstate->y2r_en = 0; vpstate->r2y_en = 0; vpstate->csc_mode = 0; + + /* hdr2sdr and sdr2hdr will do csc itself */ + if (vpstate->hdr2sdr_en) { + /* This is hdr2sdr enabled plane */ + return; + } else if (!vpstate->hdr_in && vp->sdr2hdr_en) { + /* This is sdr2hdr enabled plane */ + return; + } + if (is_input_yuv && !is_output_yuv) { vpstate->y2r_en = 1; vpstate->csc_mode = vop2_convert_csc_mode(input_csc); @@ -1872,8 +1890,8 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, struct drm_plane_s struct drm_plane_state *pstate = plane->state; struct drm_crtc *crtc = pstate->crtc; struct vop2_win *win = to_vop2_win(plane); + struct vop2_video_port *vp = to_vop2_video_port(crtc); struct vop2_plane_state *vpstate = to_vop2_plane_state(pstate); - struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; struct vop2 *vop2 = win->vop2; struct drm_framebuffer *fb = pstate->fb; @@ -1963,7 +1981,7 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, struct drm_plane_s format = vop2_convert_format(fb->format->format); - vop2_setup_csc_mode(vcstate, vpstate); + vop2_setup_csc_mode(vp, vpstate); spin_lock(&vop2->reg_lock); @@ -3134,7 +3152,6 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state else out_mode = vcstate->output_mode; VOP_MODULE_SET(vop2, vp, out_mode, out_mode); - VOP_MODULE_SET(vop2, vp, overlay_mode, is_yuv_output(vcstate->bus_format)); if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode)) VOP_MODULE_SET(vop2, vp, dsp_data_swap, DSP_RB_SWAP); @@ -3190,11 +3207,6 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state clk_set_rate(vp->dclk, adjusted_mode->crtc_clock * 1000); - if (is_yuv_output(vcstate->bus_format)) - val = 0x20010200; - else - val = 0; - VOP_MODULE_SET(vop2, vp, dsp_background, val); vop2_post_config(crtc); vop2_cfg_done(crtc); @@ -3236,8 +3248,8 @@ static void vop2_setup_hdr10(struct vop2_video_port *vp, uint8_t win_phys_id) bool hdr2sdr_en = 0; bool sdr2hdr_en = 0; bool sdr2hdr_tf = 0; - bool hdr2sdr_tf_update = 1; - bool sdr2hdr_tf_update = 1; + bool hdr2sdr_tf_update = 0; + bool sdr2hdr_tf_update = 0; /* * Check whether this video port support hdr or not @@ -3264,9 +3276,13 @@ static void vop2_setup_hdr10(struct vop2_video_port *vp, uint8_t win_phys_id) if (vp->hdr_in && !vp->hdr_out) hdr2sdr_en = 1; - if (vp->hdr_out) + if (vp->hdr_out && (vp->nr_wins > 1)) sdr2hdr_en = 1; + vp->sdr2hdr_en = sdr2hdr_en; + vpstate->hdr_in = hdr_en; + vpstate->hdr2sdr_en = hdr2sdr_en; + if (sdr2hdr_en) { sdr2hdr_r2r_mode = BT709_TO_BT2020; if (vp->hdr_in) @@ -3277,8 +3293,13 @@ static void vop2_setup_hdr10(struct vop2_video_port *vp, uint8_t win_phys_id) VOP_MODULE_SET(vop2, vp, hdr10_en, hdr_en); - if (hdr2sdr_en || sdr2hdr_en) + if (hdr2sdr_en || sdr2hdr_en) { + /* + * HDR2SDR and SDR2HDR must overlay in yuv color space + */ + vcstate->yuv_overlay = false; VOP_MODULE_SET(vop2, vp, hdr_lut_mode, lut_mode); + } if (hdr2sdr_en) { if (hdr2sdr_tf_update) @@ -3291,6 +3312,7 @@ static void vop2_setup_hdr10(struct vop2_video_port *vp, uint8_t win_phys_id) VOP_MODULE_SET(vop2, vp, hdr2sdr_normfacgamma, hdr_table->hdr2sdr_normfacgamma); } VOP_MODULE_SET(vop2, vp, hdr2sdr_en, hdr2sdr_en); + VOP_MODULE_SET(vop2, vp, hdr2sdr_bypass_en, !hdr2sdr_en); if (sdr2hdr_en) { if (sdr2hdr_tf_update) @@ -3778,10 +3800,20 @@ static void vop2_cfg_update(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { struct vop2_video_port *vp = to_vop2_video_port(crtc); + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); struct vop2 *vop2 = vp->vop2; + uint32_t val; spin_lock(&vop2->reg_lock); + VOP_MODULE_SET(vop2, vp, overlay_mode, vcstate->yuv_overlay); + + if (vcstate->yuv_overlay) + val = 0x20010200; + else + val = 0; + VOP_MODULE_SET(vop2, vp, dsp_background, val); + vop2_tv_config_update(crtc, old_crtc_state); vop2_post_config(crtc); diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index 7c5f02cfec84..749b25feda92 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -391,8 +391,10 @@ static const struct vop2_video_port_regs rk3568_vop_vp0_regs = { .sdr2hdr_r2r_mode = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 2), .sdr2hdr_oetf_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 3), .sdr2hdr_bypass_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 8), - .sdr2hdr_gating_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 9), + .sdr2hdr_auto_gating_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 9), .hdr2sdr_en = VOP_REG(RK3568_HDR2SDR_CTRL, 0x1, 0), + .hdr2sdr_bypass_en = VOP_REG(RK3568_HDR2SDR_CTRL, 0x1, 8), + .hdr2sdr_auto_gating_en = VOP_REG(RK3568_HDR2SDR_CTRL, 0x1, 9), .hdr2sdr_src_min = VOP_REG(RK3568_HDR2SDR_SRC_RANGE, 0x3fff, 0), .hdr2sdr_src_max = VOP_REG(RK3568_HDR2SDR_SRC_RANGE, 0x3fff, 16), .hdr2sdr_normfaceetf = VOP_REG(RK3568_HDR2SDR_NORMFACEETF, 0x7ff, 0),