From 19bc7529b9afe5e25ddff6f53d77ebfb1bf5f404 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Fri, 22 Mar 2024 09:30:05 +0800 Subject: [PATCH] drm/rockchip: vop2: Fix no signal when switch YUV420 to RGB/YUV444 in hdmi frl mode The timing of YUV420 at the same resolution is different from other color formats. Therefore, if timing switch of vop is later than the switching process of hdmi, hdmi timing will be abnormal. In hdmi frl mode, input ipi clk is different from output link clk frequency, which makes it difficult to restore after the timing error. Therefore, it is necessary to ensure that the output mode of vop is switched before hdmi switch to ensure the correct timing Change-Id: I4633670f13a28975eb37a68ad597956d87a159c3 Signed-off-by: Algea Cao --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 69 +++++++++++++------- 1 file changed, 45 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index fc1ee3194214..a908265803ff 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -8553,6 +8553,41 @@ static void vop3_setup_pipe_dly(struct vop2_video_port *vp, const struct vop2_zp } } +static void vop2_crtc_setup_output_mode(struct drm_crtc *crtc) +{ + uint8_t out_mode; + struct vop2_video_port *vp = to_vop2_video_port(crtc); + struct vop2 *vop2 = vp->vop2; + const struct vop2_data *vop2_data = vop2->data; + const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id]; + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); + + if ((vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA && + !(vp_data->feature & VOP_FEATURE_OUTPUT_10BIT)) || + vcstate->output_if & VOP_OUTPUT_IF_BT656) + out_mode = ROCKCHIP_OUT_MODE_P888; + else + out_mode = vcstate->output_mode; + + if (out_mode == ROCKCHIP_OUT_MODE_YUV420) { + if (vop2->version == VOP_VERSION_RK3588 && output_if_is_dp(vcstate->output_if)) + out_mode = RK3588_DP_OUT_MODE_YUV420; + } else if (out_mode == ROCKCHIP_OUT_MODE_YUV422) { + if (vop2->version == VOP_VERSION_RK3576 && output_if_is_edp(vcstate->output_if)) + out_mode = RK3576_EDP_OUT_MODE_YUV422; + else if (vop2->version == VOP_VERSION_RK3588 && + output_if_is_edp(vcstate->output_if)) + out_mode = RK3588_EDP_OUTPUT_MODE_YUV422; + else if (vop2->version == VOP_VERSION_RK3576 && + output_if_is_hdmi(vcstate->output_if)) + out_mode = RK3576_HDMI_OUT_MODE_YUV422; + else if (output_if_is_dp(vcstate->output_if)) + out_mode = RK3588_DP_OUT_MODE_YUV422; + } + + VOP_MODULE_SET(vop2, vp, out_mode, out_mode); +} + static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) { struct vop2_video_port *vp = to_vop2_video_port(crtc); @@ -8988,6 +9023,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta vop3_setup_pipe_dly(vp, NULL); vop2_crtc_csu_set_rate(crtc); + vop2_crtc_setup_output_mode(crtc); + vop2_cfg_done(crtc); /* @@ -11019,33 +11056,9 @@ static void vop2_cfg_update(struct drm_crtc *crtc, struct vop2_video_port *splice_vp = &vop2->vps[vp_data->splice_vp_id]; uint32_t val; uint32_t r, g, b; - uint8_t out_mode; spin_lock(&vop2->reg_lock); - if ((vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA && - !(vp_data->feature & VOP_FEATURE_OUTPUT_10BIT)) || - vcstate->output_if & VOP_OUTPUT_IF_BT656) - out_mode = ROCKCHIP_OUT_MODE_P888; - else - out_mode = vcstate->output_mode; - - if (out_mode == ROCKCHIP_OUT_MODE_YUV420) { - if (vop2->version == VOP_VERSION_RK3588 && output_if_is_dp(vcstate->output_if)) - out_mode = RK3588_DP_OUT_MODE_YUV420; - } else if (out_mode == ROCKCHIP_OUT_MODE_YUV422) { - if (vop2->version == VOP_VERSION_RK3576 && output_if_is_edp(vcstate->output_if)) - out_mode = RK3576_EDP_OUT_MODE_YUV422; - else if (vop2->version == VOP_VERSION_RK3588 && output_if_is_edp(vcstate->output_if)) - out_mode = RK3588_EDP_OUTPUT_MODE_YUV422; - else if (vop2->version == VOP_VERSION_RK3576 && output_if_is_hdmi(vcstate->output_if)) - out_mode = RK3576_HDMI_OUT_MODE_YUV422; - else if (output_if_is_dp(vcstate->output_if)) - out_mode = RK3588_DP_OUT_MODE_YUV422; - } - - VOP_MODULE_SET(vop2, vp, out_mode, out_mode); - vop2_post_color_swap(crtc); vop2_dither_setup(vcstate, crtc); @@ -11183,6 +11196,14 @@ static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_stat vop2_wait_for_scan_timing_from_the_assigned_line(vp, current_line, vtotal >> 3); } + /* + * In some cases(such as seamless hdr switching) the crtc + * atomic enable will not be run, but vop output mode may + * also be modified. So vop2_crtc_setup_output_mode must + * be call in crtc atomic flush + */ + vop2_crtc_setup_output_mode(crtc); + vop2_cfg_update(crtc, old_cstate); if (!vop2->is_iommu_enabled && vop2->is_iommu_needed) {