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),