diff options
Diffstat (limited to 'drivers/gpu/drm/rockchip/rockchip_drm_vop.c')
-rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index b0179849de96..90eb9a3bcf03 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -26,6 +26,7 @@ #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_self_refresh_helper.h> #include <drm/drm_vblank.h> #ifdef CONFIG_DRM_ANALOGIX_DP @@ -35,10 +36,11 @@ #include "rockchip_drm_drv.h" #include "rockchip_drm_gem.h" #include "rockchip_drm_fb.h" -#include "rockchip_drm_psr.h" #include "rockchip_drm_vop.h" #include "rockchip_rgb.h" +#define VOP_SELF_REFRESH_ENTRY_DELAY_MS 100 + #define VOP_WIN_SET(vop, win, name, v) \ vop_reg_set(vop, &win->phy->name, win->base, ~0, v, #name) #define VOP_SCL_SET(vop, win, name, v) \ @@ -541,7 +543,7 @@ static void vop_win_disable(struct vop *vop, const struct vop_win_data *win) VOP_WIN_SET(vop, win, enable, 0); } -static int vop_enable(struct drm_crtc *crtc) +static int vop_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { struct vop *vop = to_vop(crtc); int ret, i; @@ -581,12 +583,18 @@ static int vop_enable(struct drm_crtc *crtc) * We need to make sure that all windows are disabled before we * enable the crtc. Otherwise we might try to scan from a destroyed * buffer later. + * + * In the case of enable-after-PSR, we don't need to worry about this + * case since the buffer is guaranteed to be valid and disabling the + * window will result in screen glitches on PSR exit. */ - for (i = 0; i < vop->data->win_size; i++) { - struct vop_win *vop_win = &vop->win[i]; - const struct vop_win_data *win = vop_win->data; + if (!old_state || !old_state->self_refresh_active) { + for (i = 0; i < vop->data->win_size; i++) { + struct vop_win *vop_win = &vop->win[i]; + const struct vop_win_data *win = vop_win->data; - vop_win_disable(vop, win); + vop_win_disable(vop, win); + } } spin_unlock(&vop->reg_lock); @@ -624,6 +632,12 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc, WARN_ON(vop->event); mutex_lock(&vop->vop_lock); + + if (!vop->is_enabled) { + mutex_unlock(&vop->vop_lock); + return; + } + drm_crtc_vblank_off(crtc); /* @@ -925,12 +939,10 @@ static void vop_plane_atomic_async_update(struct drm_plane *plane, swap(plane->state->fb, new_state->fb); if (vop->is_enabled) { - rockchip_drm_psr_inhibit_get_state(new_state->state); vop_plane_atomic_update(plane, plane->state); spin_lock(&vop->reg_lock); vop_cfg_done(vop); spin_unlock(&vop->reg_lock); - rockchip_drm_psr_inhibit_put_state(new_state->state); /* * A scanout can still be occurring, so we can't drop the @@ -1038,7 +1050,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, WARN_ON(vop->event); - ret = vop_enable(crtc); + ret = vop_enable(crtc, old_state); if (ret) { mutex_unlock(&vop->vop_lock); DRM_DEV_ERROR(vop->dev, "Failed to enable vop (%d)\n", ret); @@ -1520,6 +1532,13 @@ static int vop_create_crtc(struct vop *vop) init_completion(&vop->line_flag_completion); crtc->port = port; + ret = drm_self_refresh_helper_init(crtc, + VOP_SELF_REFRESH_ENTRY_DELAY_MS); + if (ret) + DRM_DEV_DEBUG_KMS(vop->dev, + "Failed to init %s with SR helpers %d, ignoring\n", + crtc->name, ret); + return 0; err_cleanup_crtc: @@ -1537,6 +1556,8 @@ static void vop_destroy_crtc(struct vop *vop) struct drm_device *drm_dev = vop->drm_dev; struct drm_plane *plane, *tmp; + drm_self_refresh_helper_cleanup(crtc); + of_node_put(crtc->port); /* |