LAYERSEL_REGDONE_SEL mask of RK3568_OVL_CTRL register controls which
Video Port (VP) vsync latches the shared RK3568_OVL_{LAYER|PORT}_SEL
shadow registers into the active configuration.

rk3568_vop2_setup_layer_mixer() overwrites LAYERSEL_REGDONE_SEL to the
current VP ID before waiting for the previous VP layer configuration to
take effect.  As a consequence, the previous VP vsync can no longer
trigger the latch, so the wait polls a value that might never appear.

Move the layer cfg done wait before the RK3568_OVL_CTRL write so the
previous VP vsync can still commit the pending configuration.

Fixes: 3e89a8c68354 ("drm/rockchip: vop2: Fix the update of LAYER/PORT select 
registers when there are multi display output on rk3588/rk3568")
Signed-off-by: Cristian Ciocaltea <[email protected]>
---
 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c 
b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
index edca0fb16e08..5206f01ec787 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
@@ -2289,15 +2289,6 @@ static void rk3568_vop2_setup_layer_mixer(struct 
vop2_video_port *vp)
         *    lead to the configuration of the previous VP being take effect 
along with the VSYNC
         *    of the new VP.
         */
-       if (layer_sel != old_layer_sel || port_sel != old_port_sel)
-               ovl_ctrl |= FIELD_PREP(RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL, 
vp->id);
-       vop2_writel(vop2, RK3568_OVL_CTRL, ovl_ctrl);
-
-       if (port_sel != old_port_sel) {
-               vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel);
-               vop2_cfg_done(vp);
-               rk3568_vop2_wait_for_port_mux_done(vop2);
-       }
 
        if (layer_sel != old_layer_sel && atv_layer_sel != old_layer_sel) {
                cfg_done = vop2_readl(vop2, RK3568_REG_CFG_DONE);
@@ -2310,6 +2301,16 @@ static void rk3568_vop2_setup_layer_mixer(struct 
vop2_video_port *vp)
                        rk3568_vop2_wait_for_layer_cfg_done(vop2, 
old_layer_sel);
        }
 
+       if (layer_sel != old_layer_sel || port_sel != old_port_sel)
+               ovl_ctrl |= FIELD_PREP(RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL, 
vp->id);
+       vop2_writel(vop2, RK3568_OVL_CTRL, ovl_ctrl);
+
+       if (port_sel != old_port_sel) {
+               vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel);
+               vop2_cfg_done(vp);
+               rk3568_vop2_wait_for_port_mux_done(vop2);
+       }
+
        vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel);
        mutex_unlock(&vop2->ovl_lock);
 }

-- 
2.53.0

Reply via email to