mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 02:50:49 +09:00
drm/rockchip: vop2: recover win state when exit psr
Change-Id: I0d30042473ae84f49b4d326b31732180995b8b52 Signed-off-by: Sandy Huang <hjc@rock-chips.com>
This commit is contained in:
@@ -642,6 +642,11 @@ struct vop2_video_port {
|
||||
* @win_mask: Bitmask of wins attached to the video port;
|
||||
*/
|
||||
uint32_t win_mask;
|
||||
/**
|
||||
* @enabled_win_mask: Bitmask of enabled wins attached to the video port;
|
||||
*/
|
||||
uint32_t enabled_win_mask;
|
||||
|
||||
/**
|
||||
* @nr_layers: active layers attached to the video port;
|
||||
*/
|
||||
@@ -4269,13 +4274,24 @@ static int vop2_clk_set_parent_extend(struct vop2_video_port *vp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vop2_crtc_atomic_disable_for_psr(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old_state)
|
||||
static void vop2_crtc_atomic_enter_psr(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
|
||||
{
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
struct vop2_win *win;
|
||||
unsigned long win_mask = vp->enabled_win_mask;
|
||||
int phys_id;
|
||||
|
||||
vop2_disable_all_planes_for_crtc(crtc);
|
||||
for_each_set_bit(phys_id, &win_mask, ROCKCHIP_MAX_LAYER) {
|
||||
win = vop2_find_win_by_phys_id(vop2, phys_id);
|
||||
VOP_WIN_SET(vop2, win, enable, 0);
|
||||
|
||||
if (win->feature & WIN_FEATURE_CLUSTER_MAIN)
|
||||
VOP_CLUSTER_SET(vop2, win, enable, 0);
|
||||
}
|
||||
|
||||
vop2_cfg_done(crtc);
|
||||
vop2_wait_for_fs_by_done_bit_status(vp);
|
||||
drm_crtc_vblank_off(crtc);
|
||||
if (hweight8(vop2->active_vp_mask) == 1) {
|
||||
u32 adjust_aclk_rate = 0;
|
||||
@@ -4298,6 +4314,30 @@ static void vop2_crtc_atomic_disable_for_psr(struct drm_crtc *crtc,
|
||||
}
|
||||
}
|
||||
|
||||
static void vop2_crtc_atomic_exit_psr(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
|
||||
{
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
u32 phys_id;
|
||||
struct vop2_win *win;
|
||||
unsigned long enabled_win_mask = vp->enabled_win_mask;
|
||||
|
||||
drm_crtc_vblank_on(crtc);
|
||||
if (vop2->aclk_rate_reset)
|
||||
clk_set_rate(vop2->aclk, vop2->aclk_rate);
|
||||
vop2->aclk_rate_reset = false;
|
||||
|
||||
for_each_set_bit(phys_id, &enabled_win_mask, ROCKCHIP_MAX_LAYER) {
|
||||
win = vop2_find_win_by_phys_id(vop2, phys_id);
|
||||
VOP_WIN_SET(vop2, win, enable, 1);
|
||||
if (win->feature & WIN_FEATURE_CLUSTER_MAIN)
|
||||
VOP_CLUSTER_SET(vop2, win, enable, 1);
|
||||
}
|
||||
|
||||
vop2_cfg_done(crtc);
|
||||
vop2_wait_for_fs_by_done_bit_status(vp);
|
||||
}
|
||||
|
||||
static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old_state)
|
||||
{
|
||||
@@ -4312,7 +4352,7 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
WARN_ON(vp->event);
|
||||
|
||||
if (crtc->state->self_refresh_active) {
|
||||
vop2_crtc_atomic_disable_for_psr(crtc, old_state);
|
||||
vop2_crtc_atomic_enter_psr(crtc, old_state);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -4777,6 +4817,9 @@ static void vop2_plane_atomic_disable(struct drm_plane *plane, struct drm_plane_
|
||||
{
|
||||
struct vop2_win *win = to_vop2_win(plane);
|
||||
struct vop2 *vop2 = win->vop2;
|
||||
struct drm_crtc *crtc;
|
||||
struct vop2_video_port *vp;
|
||||
|
||||
#if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
|
||||
struct vop2_plane_state *vpstate = to_vop2_plane_state(plane->state);
|
||||
#endif
|
||||
@@ -4789,9 +4832,15 @@ static void vop2_plane_atomic_disable(struct drm_plane *plane, struct drm_plane_
|
||||
|
||||
spin_lock(&vop2->reg_lock);
|
||||
|
||||
crtc = old_state->crtc;
|
||||
vp = to_vop2_video_port(crtc);
|
||||
|
||||
vop2_win_disable(win, false);
|
||||
if (win->splice_win)
|
||||
vp->enabled_win_mask &= ~BIT(win->phys_id);
|
||||
if (win->splice_win) {
|
||||
vop2_win_disable(win->splice_win, false);
|
||||
vp->enabled_win_mask &= ~BIT(win->splice_win->phys_id);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
|
||||
kfree(vpstate->planlist);
|
||||
@@ -5203,6 +5252,7 @@ static void vop2_win_atomic_update(struct vop2_win *win, struct drm_rect *src, s
|
||||
VOP_WIN_SET(vop2, win, dither_up, dither_up);
|
||||
|
||||
VOP_WIN_SET(vop2, win, enable, 1);
|
||||
vp->enabled_win_mask |= BIT(win->phys_id);
|
||||
if (vop2_cluster_window(win)) {
|
||||
lb_mode = vop2_get_cluster_lb_mode(win, vpstate);
|
||||
VOP_CLUSTER_SET(vop2, win, lb_mode, lb_mode);
|
||||
@@ -5972,6 +6022,7 @@ static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on, void *data)
|
||||
win->pd->vp_mask |= BIT(vp->id);
|
||||
}
|
||||
|
||||
vp->enabled_win_mask |= BIT(win->phys_id);
|
||||
crtc_state = drm_atomic_get_crtc_state(crtc->state->state, crtc);
|
||||
mode = &crtc_state->adjusted_mode;
|
||||
if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
|
||||
@@ -5984,6 +6035,7 @@ static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on, void *data)
|
||||
splice_vp->win_mask |= BIT(splice_win->phys_id);
|
||||
splice_win->vp_mask = BIT(splice_vp->id);
|
||||
vop2->active_vp_mask |= BIT(splice_vp->id);
|
||||
vp->enabled_win_mask |= BIT(splice_win->phys_id);
|
||||
|
||||
if (splice_win->pd &&
|
||||
VOP_WIN_GET(vop2, splice_win, enable)) {
|
||||
@@ -7559,10 +7611,7 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state
|
||||
int ret;
|
||||
|
||||
if (old_state && old_state->self_refresh_active) {
|
||||
drm_crtc_vblank_on(crtc);
|
||||
if (vop2->aclk_rate_reset)
|
||||
clk_set_rate(vop2->aclk, vop2->aclk_rate);
|
||||
vop2->aclk_rate_reset = false;
|
||||
vop2_crtc_atomic_exit_psr(crtc, old_state);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user