Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/rockchip: vop2: Only wait for changed layer cfg done when there is pending cfgdone bits

The write of cfgdone bits always done at .atomic_flush.
When userspace makes plane zpos changes of two crtc within one commit,
at the .atomic_begin stage, crtcN will never receive the "layer change
cfg done" event of crtcM because crtcM has not yet written "cfgdone".
So only wait when there is pending cfgdone bits to avoid long timeout.

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: Andy Yan <andy.yan@rock-chips.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patch.msgid.link/20250718064120.8811-2-andyshrk@163.com

authored by

Andy Yan and committed by
Heiko Stuebner
7f6721b7 9fae8245

+11 -2
+11 -2
drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
··· 2144 2144 u8 layer_sel_id; 2145 2145 unsigned int ofs; 2146 2146 u32 ovl_ctrl; 2147 + u32 cfg_done; 2147 2148 int i; 2148 2149 struct vop2_video_port *vp0 = &vop2->vps[0]; 2149 2150 struct vop2_video_port *vp1 = &vop2->vps[1]; ··· 2299 2298 rk3568_vop2_wait_for_port_mux_done(vop2); 2300 2299 } 2301 2300 2302 - if (layer_sel != old_layer_sel && atv_layer_sel != old_layer_sel) 2303 - rk3568_vop2_wait_for_layer_cfg_done(vop2, vop2->old_layer_sel); 2301 + if (layer_sel != old_layer_sel && atv_layer_sel != old_layer_sel) { 2302 + cfg_done = vop2_readl(vop2, RK3568_REG_CFG_DONE); 2303 + cfg_done &= (BIT(vop2->data->nr_vps) - 1); 2304 + cfg_done &= ~BIT(vp->id); 2305 + /* 2306 + * Changes of other VPs' overlays have not taken effect 2307 + */ 2308 + if (cfg_done) 2309 + rk3568_vop2_wait_for_layer_cfg_done(vop2, vop2->old_layer_sel); 2310 + } 2304 2311 2305 2312 vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel); 2306 2313 mutex_unlock(&vop2->ovl_lock);