From: Sean Paul seanpaul@chromium.org
Instead of fully disabling and re-enabling the vop on PSR transitions, only disable the active windows. This will speed up PSR exits substantially and is still a power-savings win.
This patch integrates portions of Zain's patch from here: https://patchwork.kernel.org/patch/9615063/
Cc: Zain Wang wzz@rock-chips.com Cc: Tomasz Figa tfiga@chromium.org Cc: Kristian H. Kristensen hoegsberg@chromium.org Signed-off-by: Sean Paul seanpaul@chromium.org --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 38 +++++++++++++++++++++ 1 file changed, 38 insertions(+)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 66c99d57e62a..025cfb55ffe2 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -131,6 +131,7 @@ struct vop { bool is_enabled;
struct completion dsp_hold_completion; + unsigned int win_enabled;
/* protected by dev->event_lock */ struct drm_pending_vblank_event *event; @@ -591,6 +592,7 @@ static int vop_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) const struct vop_win_data *win = vop_win->data;
VOP_WIN_SET(vop, win, enable, 0); + vop->win_enabled &= ~BIT(i); } } spin_unlock(&vop->reg_lock); @@ -621,6 +623,25 @@ static int vop_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) return ret; }
+static void rockchip_drm_set_win_enabled(struct drm_crtc *crtc, bool enabled) +{ + struct vop *vop = to_vop(crtc); + int i; + + spin_lock(&vop->reg_lock); + + 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_SET(vop, win, enable, + enabled && (vop->win_enabled & BIT(i))); + } + vop_cfg_done(vop); + + spin_unlock(&vop->reg_lock); +} + static void vop_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { @@ -628,9 +649,15 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc,
WARN_ON(vop->event);
+ if (crtc->state->psr_transition) + rockchip_drm_set_win_enabled(crtc, false); + mutex_lock(&vop->vop_lock); drm_crtc_vblank_off(crtc);
+ if (crtc->state->psr_transition) + goto out; + /* * Vop standby will take effect at end of current frame, * if dsp hold valid irq happen, it means standby complete. @@ -661,6 +688,8 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc, clk_disable(vop->dclk); vop_core_clks_disable(vop); pm_runtime_put(vop->dev); + +out: mutex_unlock(&vop->vop_lock);
if (crtc->state->event && !crtc->state->active) { @@ -741,6 +770,7 @@ static void vop_plane_atomic_disable(struct drm_plane *plane, spin_lock(&vop->reg_lock);
VOP_WIN_SET(vop, win, enable, 0); + vop->win_enabled &= ~BIT(VOP_WIN_TO_INDEX(vop_win));
spin_unlock(&vop->reg_lock); } @@ -879,6 +909,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, }
VOP_WIN_SET(vop, win, enable, 1); + vop->win_enabled |= BIT(win_index); spin_unlock(&vop->reg_lock); }
@@ -1034,6 +1065,12 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, uint32_t pin_pol, val; int ret;
+ if (old_state->psr_transition) { + drm_crtc_vblank_on(crtc); + rockchip_drm_set_win_enabled(crtc, true); + return; + } + mutex_lock(&vop->vop_lock);
WARN_ON(vop->event); @@ -1627,6 +1664,7 @@ static int vop_initial(struct vop *vop) VOP_WIN_SET(vop, win, channel, (channel + 1) << 4 | channel); VOP_WIN_SET(vop, win, enable, 0); VOP_WIN_SET(vop, win, gate, 1); + vop->win_enabled &= ~BIT(i); }
vop_cfg_done(vop);