From 78d4e14a0485466daff6e5365ed47a81434ddd03 Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Mon, 9 Jun 2025 12:04:32 +0800 Subject: [PATCH] drm/rockchip: vop: Add support mipi TE mode For software TE mode, we register a gpio IRQ to respond to the TE signal from the panel. If the falling edge is detected via gpio, a new frame will be sent to the panel for display by software driver. For hardware TE mode, we set the specific pin to TE function iomux. If the TE signal is detected, a new frame will be sent to the RX device by hardware automatically. Change-Id: Ic594e5eb4b267a52441fb2720c788aba4d8ffb72 Signed-off-by: Damon Ding --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 27 ++++++++++++++++++++- drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 4 +++ drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 18 ++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 9eac6c767165..e30ea74eda67 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -2212,6 +2212,7 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc, { struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, crtc); struct vop *vop = to_vop(crtc); + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); int sys_status = drm_crtc_index(crtc) ? SYS_STATUS_LCDC1 : SYS_STATUS_LCDC0; unsigned long status; @@ -2224,6 +2225,10 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc, } vop_lock(vop); + if (s->hold_mode) { + VOP_CTRL_SET(vop, edpi_te_en, 0); + VOP_CTRL_SET(vop, edpi_ctrl_mode, 0); + } VOP_CTRL_SET(vop, reg_done_frm, 1); VOP_CTRL_SET(vop, dsp_interlace, 0); drm_crtc_vblank_off(crtc); @@ -3828,8 +3833,24 @@ static void vop_crtc_te_handler(struct drm_crtc *crtc) vop = to_vop(crtc); - if (vop->mcu_timing.mcu_pix_total) + if (vop->mcu_timing.mcu_pix_total) { VOP_CTRL_SET(vop, mcu_frame_st, 1); + } else { + /* + * For software TE mode, we register a gpio IRQ to respond to + * the TE signal from the panel. If the TE signal is detected + * via gpio, a new frame will be sent to the panel for display + * only by controlling the edpi_wms_fs bit. + * + * As the IC design, the VOP will only refresh one new frame + * of image when the ​​edpi_wms_fs​​ bit, which can take effect + * immediately, is first written with ​​1​ and then cleared to 0​​. + * If only written to ​​1​​, it will result in ​​two frames being + * refreshed​​ instead. + */ + VOP_CTRL_SET(vop, edpi_wms_fs, 1); + VOP_CTRL_SET(vop, edpi_wms_fs, 0); + } } #if defined(CONFIG_ROCKCHIP_DRM_DEBUG) @@ -4279,6 +4300,10 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, VOP_GRF_SET(vop, vo0_grf, grf_mipi_mode, 0); VOP_GRF_SET(vop, vo0_grf, grf_mipi_pin_pol, val); VOP_GRF_SET(vop, vo0_grf, grf_mipi_1to4_en, 1); + if (s->hold_mode) { + VOP_CTRL_SET(vop, edpi_te_en, !s->soft_te); + VOP_CTRL_SET(vop, edpi_ctrl_mode, 1); + } break; case DRM_MODE_CONNECTOR_DisplayPort: VOP_CTRL_SET(vop, dp_dclk_pol, 0); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 7aba354f82cc..f39b9748ca3d 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -466,6 +466,10 @@ struct vop_ctrl { struct vop_reg reg_done_frm; struct vop_reg cfg_done; + struct vop_reg edpi_wms_fs; + struct vop_reg edpi_ctrl_mode; + struct vop_reg edpi_te_en; + /* ebc vop */ struct vop_reg enable; struct vop_reg inf_out_en; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index cbd3431d2586..787cf7c789dd 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -323,6 +323,10 @@ static const struct vop_ctrl rk3288_ctrl_data = { .mipi_dclk_pol = VOP_REG_VER(RK3368_DSP_CTRL1, 0x1, 31, 3, 2, -1), .mipi_pin_pol = VOP_REG_VER(RK3368_DSP_CTRL1, 0x7, 28, 3, 2, -1), + .edpi_wms_fs = VOP_REG(RK3288_SYS_CTRL, 0x1, 10), + .edpi_ctrl_mode = VOP_REG(RK3288_SYS_CTRL, 0x1, 9), + .edpi_te_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 8), + .dither_down_sel = VOP_REG(RK3288_DSP_CTRL1, 0x1, 4), .dither_down_mode = VOP_REG(RK3288_DSP_CTRL1, 0x1, 3), .dither_down_en = VOP_REG(RK3288_DSP_CTRL1, 0x1, 2), @@ -1629,6 +1633,10 @@ static const struct vop_ctrl px30_ctrl_data = { .mcu_type = VOP_REG(RK3366_LIT_MCU_CTRL, 0x1, 31), .mcu_rw_bypass_port = VOP_REG(RK3366_LIT_MCU_RW_BYPASS_PORT, 0xffffffff, 0), + + .edpi_wms_fs = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 11), + .edpi_ctrl_mode = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 10), + .edpi_te_en = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 9), }; static const struct vop_win_phy px30_win23_data = { @@ -1878,6 +1886,10 @@ static const struct vop_ctrl rv1126_ctrl_data = { 0xffffffff, 0), .bt1120_yc_swap = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x1, 30), .bt1120_en = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x1, 31), + + .edpi_wms_fs = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 11), + .edpi_ctrl_mode = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 10), + .edpi_te_en = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 9), }; static const struct vop_win_data rv1126_vop_win_data[] = { @@ -1932,6 +1944,9 @@ static const struct vop_ctrl rv1126b_ctrl_data = { .standby = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 1), .dsp_outzero = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 3), .yuv_clip = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 4), + .edpi_te_en = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 9), + .edpi_ctrl_mode = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 10), + .edpi_wms_fs = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 11), .global_regdone_en = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 13), .rgb_en = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x1, 0), @@ -2159,6 +2174,9 @@ static const struct vop_ctrl rk3506_ctrl_data = { .standby = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 1), .dsp_outzero = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 3), .yuv_clip = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 4), + .edpi_te_en = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 9), + .edpi_ctrl_mode = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 10), + .edpi_wms_fs = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 11), .rgb_en = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x1, 0), .rgb_pin_pol = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x7, 2),