From bc3c93ff07c0f92dec32660b23c609d2dd00783b Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Mon, 17 May 2021 16:42:40 +0800 Subject: [PATCH] drm/rockchip: vop2: wait port_mux cfg done before configure new plane We need two vsync cycle when move a window from on vp to another: the port_mux take effect in first vsync, than enable the window at second vsync. Signed-off-by: Andy Yan Change-Id: I87c1ac0803081ecb201d9218d40fdea89424fbd8 --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 45 ++++++++++++++------ 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 5e671bdb1004..ac4d96a7b370 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -441,6 +441,13 @@ struct vop2_video_port { * */ bool sdr2hdr_en; + /** + * @skip_vsync: skip on vsync when port_mux changed on this vp. + * a win move from one VP to another need wait one vsync until + * port_mut take effect before this win can be enabled. + * + */ + bool skip_vsync; /** * @bg_ovl_dly: The timing delay from background layer @@ -930,6 +937,7 @@ static void vop2_wait_for_port_mux_done(struct vop2 *vop2) port_mux_cfg, vop2->port_mux_cfg); } + static int32_t vop2_pending_done_bits(struct vop2_video_port *vp) { struct vop2 *vop2 = vp->vop2; @@ -2977,14 +2985,14 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, struct drm_plane_s /* * This means this window is moved from another vp - * so the VOP2_PORT_SEL register is changed - * in this commit, we should not change this - * win register before the VOP2_PORT_SEL take effect - * on this VP, so skip this frame for safe. + * so the VOP2_PORT_SEL register is changed and + * take effect by vop2_wait_for_port_mux_done + * in this commit. so we can continue configure + * the window and report vsync */ if (win->old_vp_mask != win->vp_mask) { win->old_vp_mask = win->vp_mask; - return; + vp->skip_vsync = false; } actual_w = drm_rect_width(src) >> 16; @@ -4826,6 +4834,21 @@ static void vop2_setup_alpha(struct vop2_video_port *vp, } } +static void vop2_setup_port_mux(struct vop2_video_port *vp, uint16_t port_mux_cfg) +{ + struct vop2 *vop2 = vp->vop2; + + spin_lock(&vop2->reg_lock); + if (vop2->port_mux_cfg != port_mux_cfg) { + VOP_CTRL_SET(vop2, ovl_port_mux_cfg, port_mux_cfg); + vp->skip_vsync = true; + vop2_cfg_done(&vp->crtc); + vop2->port_mux_cfg = port_mux_cfg; + vop2_wait_for_port_mux_done(vop2); + } + spin_unlock(&vop2->reg_lock); +} + static void vop2_setup_layer_mixer_for_vp(struct vop2_video_port *vp, const struct vop2_zpos *vop2_zpos) { @@ -4873,12 +4896,6 @@ static void vop2_setup_layer_mixer_for_vp(struct vop2_video_port *vp, port_mux_cfg |= 7 << (4 * (vop2->data->nr_vps - 1)); - vop2_wait_for_port_mux_done(vop2); - vop2->port_mux_cfg = port_mux_cfg; - VOP_CTRL_SET(vop2, ovl_port_mux_cfg, port_mux_cfg); - VOP_CTRL_SET(vop2, ovl_cfg_done_port, port_id); - VOP_CTRL_SET(vop2, ovl_port_mux_cfg_done_imd, 0); - /* * Win and layer must map one by one, if a win is selected * by two layers, unexpected error may happen. @@ -4908,6 +4925,10 @@ static void vop2_setup_layer_mixer_for_vp(struct vop2_video_port *vp, win->layer_id = layer_id; layer->win_phys_id = win_phys_id; } + + VOP_CTRL_SET(vop2, ovl_cfg_done_port, vp->id); + VOP_CTRL_SET(vop2, ovl_port_mux_cfg_done_imd, 0); + vop2_setup_port_mux(vp, port_mux_cfg); } static void vop2_setup_dly_for_vp(struct vop2_video_port *vp) @@ -5720,7 +5741,7 @@ static irqreturn_t vop2_isr(int irq, void *data) if (active_irqs & FS_FIELD_INTR) { vop2_wb_handler(vp); - if (vp->layer_sel_update == false) { + if (likely(!vp->skip_vsync) || (vp->layer_sel_update == false)) { drm_crtc_handle_vblank(crtc); vop2_handle_vblank(vop2, crtc); }