@@ -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);