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

Configure Feed

Select the types of activity you want to include in your feed.

drm/rockchip: vop2: Fix the update of LAYER/PORT select registers when there are multi display output on rk3588/rk3568

The all video ports of rk3568/rk3588 share the same OVL_LAYER_SEL
and OVL_PORT_SEL registers, and the configuration of these two registers
can be set to take effect when the vsync signal arrives at a certain Video
Port.

If two threads for two display output choose to update these two registers
simultaneously to meet their own plane adjustment requirements(change plane
zpos or switch plane from one crtc to another), then no matter which Video
Port'svsync signal we choose to follow for these two registers, the display
output of the other Video Port will be abnormal.
This is because the configuration of this Video Port does not take
effect at the right time (its configuration should take effect when its
VSYNC signal arrives).

In order to solve this problem, when performing plane migration or
change the zpos of planes, there are two things to be observed and
followed:

1. When a plane is migrated from one VP to another, the configuration of
the layer can only take effect after the Port mux configuration is
enabled.

2. When change the zpos of planes, we must ensure that the change for
the previous VP takes effect before we proceed to change the next VP.
Otherwise, the new configuration might overwrite the previous one for
the previous VP, or it could lead to the configuration of the previous
VP being take effect along with the VSYNC of the new VP.

This issue only occurs in scenarios where multi-display output is enabled.

Fixes: c5996e4ab109 ("drm/rockchip: vop2: Make overlay layer select register configuration take effect by vsync")
Signed-off-by: Andy Yan <andy.yan@rock-chips.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://lore.kernel.org/r/20250421102156.424480-1-andyshrk@163.com

authored by

Andy Yan and committed by
Heiko Stuebner
3e89a8c6 6a1b9229

+122 -25
+6 -19
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
··· 146 146 mutex_unlock(&vop2->vop2_lock); 147 147 } 148 148 149 - /* 150 - * Note: 151 - * The write mask function is documented but missing on rk3566/8, writes 152 - * to these bits have no effect. For newer soc(rk3588 and following) the 153 - * write mask is needed for register writes. 154 - * 155 - * GLB_CFG_DONE_EN has no write mask bit. 156 - * 157 - */ 158 - static void vop2_cfg_done(struct vop2_video_port *vp) 159 - { 160 - struct vop2 *vop2 = vp->vop2; 161 - u32 val = RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN; 162 - 163 - val |= BIT(vp->id) | (BIT(vp->id) << 16); 164 - 165 - regmap_set_bits(vop2->map, RK3568_REG_CFG_DONE, val); 166 - } 167 - 168 149 static void vop2_win_disable(struct vop2_win *win) 169 150 { 170 151 vop2_win_write(win, VOP2_WIN_ENABLE, 0); ··· 834 853 835 854 if (vop2->version == VOP_VERSION_RK3588) 836 855 rk3588_vop2_power_domain_enable_all(vop2); 856 + 857 + if (vop2->version <= VOP_VERSION_RK3588) { 858 + vop2->old_layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); 859 + vop2->old_port_sel = vop2_readl(vop2, RK3568_OVL_PORT_SEL); 860 + } 837 861 838 862 vop2_writel(vop2, RK3568_REG_CFG_DONE, RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN); 839 863 ··· 2714 2728 return dev_err_probe(drm->dev, vop2->irq, "cannot find irq for vop2\n"); 2715 2729 2716 2730 mutex_init(&vop2->vop2_lock); 2731 + mutex_init(&vop2->ovl_lock); 2717 2732 2718 2733 ret = devm_request_irq(dev, vop2->irq, vop2_isr, IRQF_SHARED, dev_name(dev), vop2); 2719 2734 if (ret)
+33
drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
··· 334 334 /* optional internal rgb encoder */ 335 335 struct rockchip_rgb *rgb; 336 336 337 + /* 338 + * Used to record layer selection configuration on rk356x/rk3588 339 + * as register RK3568_OVL_LAYER_SEL and RK3568_OVL_PORT_SEL are 340 + * shared for all the Video Ports. 341 + */ 342 + u32 old_layer_sel; 343 + u32 old_port_sel; 344 + /* 345 + * Ensure that the updates to these two registers(RKK3568_OVL_LAYER_SEL/RK3568_OVL_PORT_SEL) 346 + * take effect in sequence. 347 + */ 348 + struct mutex ovl_lock; 349 + 337 350 /* must be put at the end of the struct */ 338 351 struct vop2_win win[]; 339 352 }; ··· 740 727 #define RK3588_OVL_PORT_SEL__CLUSTER2 GENMASK(21, 20) 741 728 #define RK3568_OVL_PORT_SEL__CLUSTER1 GENMASK(19, 18) 742 729 #define RK3568_OVL_PORT_SEL__CLUSTER0 GENMASK(17, 16) 730 + #define RK3588_OVL_PORT_SET__PORT3_MUX GENMASK(15, 12) 743 731 #define RK3568_OVL_PORT_SET__PORT2_MUX GENMASK(11, 8) 744 732 #define RK3568_OVL_PORT_SET__PORT1_MUX GENMASK(7, 4) 745 733 #define RK3568_OVL_PORT_SET__PORT0_MUX GENMASK(3, 0) ··· 843 829 static inline struct vop2_win *to_vop2_win(struct drm_plane *p) 844 830 { 845 831 return container_of(p, struct vop2_win, base); 832 + } 833 + 834 + /* 835 + * Note: 836 + * The write mask function is documented but missing on rk3566/8, writes 837 + * to these bits have no effect. For newer soc(rk3588 and following) the 838 + * write mask is needed for register writes. 839 + * 840 + * GLB_CFG_DONE_EN has no write mask bit. 841 + * 842 + */ 843 + static inline void vop2_cfg_done(struct vop2_video_port *vp) 844 + { 845 + struct vop2 *vop2 = vp->vop2; 846 + u32 val = RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN; 847 + 848 + val |= BIT(vp->id) | (BIT(vp->id) << 16); 849 + 850 + regmap_set_bits(vop2->map, RK3568_REG_CFG_DONE, val); 846 851 } 847 852 848 853 #endif /* _ROCKCHIP_DRM_VOP2_H */
+83 -6
drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
··· 2052 2052 } 2053 2053 } 2054 2054 2055 + static u32 rk3568_vop2_read_port_mux(struct vop2 *vop2) 2056 + { 2057 + return vop2_readl(vop2, RK3568_OVL_PORT_SEL); 2058 + } 2059 + 2060 + static void rk3568_vop2_wait_for_port_mux_done(struct vop2 *vop2) 2061 + { 2062 + u32 port_mux_sel; 2063 + int ret; 2064 + 2065 + /* 2066 + * Spin until the previous port_mux figuration is done. 2067 + */ 2068 + ret = readx_poll_timeout_atomic(rk3568_vop2_read_port_mux, vop2, port_mux_sel, 2069 + port_mux_sel == vop2->old_port_sel, 0, 50 * 1000); 2070 + if (ret) 2071 + DRM_DEV_ERROR(vop2->dev, "wait port_mux done timeout: 0x%x--0x%x\n", 2072 + port_mux_sel, vop2->old_port_sel); 2073 + } 2074 + 2075 + static u32 rk3568_vop2_read_layer_cfg(struct vop2 *vop2) 2076 + { 2077 + return vop2_readl(vop2, RK3568_OVL_LAYER_SEL); 2078 + } 2079 + 2080 + static void rk3568_vop2_wait_for_layer_cfg_done(struct vop2 *vop2, u32 cfg) 2081 + { 2082 + u32 atv_layer_cfg; 2083 + int ret; 2084 + 2085 + /* 2086 + * Spin until the previous layer configuration is done. 2087 + */ 2088 + ret = readx_poll_timeout_atomic(rk3568_vop2_read_layer_cfg, vop2, atv_layer_cfg, 2089 + atv_layer_cfg == cfg, 0, 50 * 1000); 2090 + if (ret) 2091 + DRM_DEV_ERROR(vop2->dev, "wait layer cfg done timeout: 0x%x--0x%x\n", 2092 + atv_layer_cfg, cfg); 2093 + } 2094 + 2055 2095 static void rk3568_vop2_setup_layer_mixer(struct vop2_video_port *vp) 2056 2096 { 2057 2097 struct vop2 *vop2 = vp->vop2; 2058 2098 struct drm_plane *plane; 2059 2099 u32 layer_sel = 0; 2060 2100 u32 port_sel; 2101 + u32 old_layer_sel = 0; 2102 + u32 atv_layer_sel = 0; 2103 + u32 old_port_sel = 0; 2061 2104 u8 layer_id; 2062 2105 u8 old_layer_id; 2063 2106 u8 layer_sel_id; ··· 2112 2069 struct vop2_video_port *vp2 = &vop2->vps[2]; 2113 2070 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state); 2114 2071 2072 + mutex_lock(&vop2->ovl_lock); 2115 2073 ovl_ctrl = vop2_readl(vop2, RK3568_OVL_CTRL); 2116 2074 ovl_ctrl &= ~RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD; 2117 2075 ovl_ctrl &= ~RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL; 2118 - ovl_ctrl |= FIELD_PREP(RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL, vp->id); 2119 2076 2120 2077 if (vcstate->yuv_overlay) 2121 2078 ovl_ctrl |= RK3568_OVL_CTRL__YUV_MODE(vp->id); 2122 2079 else 2123 2080 ovl_ctrl &= ~RK3568_OVL_CTRL__YUV_MODE(vp->id); 2124 2081 2125 - vop2_writel(vop2, RK3568_OVL_CTRL, ovl_ctrl); 2126 - 2127 - port_sel = vop2_readl(vop2, RK3568_OVL_PORT_SEL); 2082 + old_port_sel = vop2->old_port_sel; 2083 + port_sel = old_port_sel; 2128 2084 port_sel &= RK3568_OVL_PORT_SEL__SEL_PORT; 2129 2085 2130 2086 if (vp0->nlayers) ··· 2144 2102 else 2145 2103 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, 8); 2146 2104 2147 - layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); 2105 + /* Fixed value for rk3588 */ 2106 + if (vop2->version == VOP_VERSION_RK3588) 2107 + port_sel |= FIELD_PREP(RK3588_OVL_PORT_SET__PORT3_MUX, 7); 2108 + 2109 + atv_layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); 2110 + old_layer_sel = vop2->old_layer_sel; 2111 + layer_sel = old_layer_sel; 2148 2112 2149 2113 ofs = 0; 2150 2114 for (i = 0; i < vp->id; i++) ··· 2234 2186 old_win->data->layer_sel_id[vp->id]); 2235 2187 } 2236 2188 2189 + vop2->old_layer_sel = layer_sel; 2190 + vop2->old_port_sel = port_sel; 2191 + /* 2192 + * As the RK3568_OVL_LAYER_SEL and RK3568_OVL_PORT_SEL are shared by all Video Ports, 2193 + * and the configuration take effect by one Video Port's vsync. 2194 + * When performing layer migration or change the zpos of layers, there are two things 2195 + * to be observed and followed: 2196 + * 1. When a layer is migrated from one VP to another, the configuration of the layer 2197 + * can only take effect after the Port mux configuration is enabled. 2198 + * 2199 + * 2. When we change the zpos of layers, we must ensure that the change for the previous 2200 + * VP takes effect before we proceed to change the next VP. Otherwise, the new 2201 + * configuration might overwrite the previous one for the previous VP, or it could 2202 + * lead to the configuration of the previous VP being take effect along with the VSYNC 2203 + * of the new VP. 2204 + */ 2205 + if (layer_sel != old_layer_sel || port_sel != old_port_sel) 2206 + ovl_ctrl |= FIELD_PREP(RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL, vp->id); 2207 + vop2_writel(vop2, RK3568_OVL_CTRL, ovl_ctrl); 2208 + 2209 + if (port_sel != old_port_sel) { 2210 + vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel); 2211 + vop2_cfg_done(vp); 2212 + rk3568_vop2_wait_for_port_mux_done(vop2); 2213 + } 2214 + 2215 + if (layer_sel != old_layer_sel && atv_layer_sel != old_layer_sel) 2216 + rk3568_vop2_wait_for_layer_cfg_done(vop2, vop2->old_layer_sel); 2217 + 2237 2218 vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel); 2238 - vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel); 2219 + mutex_unlock(&vop2->ovl_lock); 2239 2220 } 2240 2221 2241 2222 static void rk3568_vop2_setup_dly_for_windows(struct vop2_video_port *vp)