Hi Andy, This fix works on my device. No more black box around the cursor.
Tested-by: Dang Huynh <[email protected]> On Wed, Nov 12, 2025 at 04:50:23PM +0800, Andy Yan wrote: > From: Andy Yan <[email protected]> > > When there are multiple Video Ports, and only one of them is working > (for example, VP1 is working while VP0 is not), in this case, the > win_mask of VP0 is 0. However, we have already set the port mux for VP0 > according to vp0->nlayers, and at the same time, in the OVL_LAYER_SEL > register, there are windows will also be assigned to layers which will > map to the inactive VPs. In this situation, vp0->win_mask is zero as it > now working, it is more reliable to calculate the used layers based on > the configuration of the OVL_LAYER_SEL register. > > Note: as the configuration of OVL_LAYER_SEL is take effect when the > vsync is come, so we use the value backup in vop2->old_layer_sel instead > of read OVL_LAYER_SEL directly. > > Fixes: 3e89a8c68354 ("drm/rockchip: vop2: Fix the update of LAYER/PORT select > registers when there are multi display output on rk3588/rk3568") > Reported-by: Diederik de Haas <[email protected]> > Closes: https://bugs.kde.org/show_bug.cgi?id=511274 > Signed-off-by: Andy Yan <[email protected]> > --- > > drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 49 +++++++++++++++++--- > 1 file changed, 42 insertions(+), 7 deletions(-) > > diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c > b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c > index d22ce11a4235..f3950e8476a7 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c > +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c > @@ -1369,6 +1369,25 @@ static const struct vop2_regs_dump rk3588_regs_dump[] > = { > }, > }; > > +/* > + * phys_id is used to identify a main window(Cluster Win/Smart Win, not > + * include the sub win of a cluster or the multi area) that can do overlay > + * in main overlay stage. > + */ > +static struct vop2_win *vop2_find_win_by_phys_id(struct vop2 *vop2, uint8_t > phys_id) > +{ > + struct vop2_win *win; > + int i; > + > + for (i = 0; i < vop2->data->win_size; i++) { > + win = &vop2->win[i]; > + if (win->data->phys_id == phys_id) > + return win; > + } > + > + return NULL; > +} > + > static unsigned long rk3568_set_intf_mux(struct vop2_video_port *vp, int id, > u32 polflags) > { > struct vop2 *vop2 = vp->vop2; > @@ -1842,15 +1861,31 @@ static void vop2_parse_alpha(struct vop2_alpha_config > *alpha_config, > alpha->dst_alpha_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; > } > > -static int vop2_find_start_mixer_id_for_vp(struct vop2 *vop2, u8 port_id) > +static int vop2_find_start_mixer_id_for_vp(struct vop2_video_port *vp) > { > - struct vop2_video_port *vp; > - int used_layer = 0; > + struct vop2 *vop2 = vp->vop2; > + struct vop2_win *win; > + u32 layer_sel = vop2->old_layer_sel; > + u32 used_layer = 0; > + unsigned long win_mask = vp->win_mask; > + unsigned long phys_id; > + bool match; > int i; > > - for (i = 0; i < port_id; i++) { > - vp = &vop2->vps[i]; > - used_layer += hweight32(vp->win_mask); > + for (i = 0; i < 31; i += 4) { > + match = false; > + for_each_set_bit(phys_id, &win_mask, ROCKCHIP_VOP2_ESMART3) { > + win = vop2_find_win_by_phys_id(vop2, phys_id); > + if (win->data->layer_sel_id[vp->id] == ((layer_sel >> > i) & 0xf)) { > + match = true; > + break; > + } > + } > + > + if (!match) > + used_layer += 1; > + else > + break; > } > > return used_layer; > @@ -1935,7 +1970,7 @@ static void vop2_setup_alpha(struct vop2_video_port *vp) > u32 dst_global_alpha = DRM_BLEND_ALPHA_OPAQUE; > > if (vop2->version <= VOP_VERSION_RK3588) > - mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id); > + mixer_id = vop2_find_start_mixer_id_for_vp(vp); > else > mixer_id = 0; > > -- > 2.43.0 > > base-commit: ded94ec6167e84195507237100f6278941e36fdd > branch: drm-misc-next-2025-1016 > > > _______________________________________________ > Linux-rockchip mailing list > [email protected] > http://lists.infradead.org/mailman/listinfo/linux-rockchip
