mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
drm/rockchip: vop2: Use OVL_LAYER_SEL configuration instead of use win_mask calculate used layers
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: 3e89a8c683 ("drm/rockchip: vop2: Fix the update of LAYER/PORT select registers when there are multi display output on rk3588/rk3568")
Cc: stable@vger.kernel.org
Reported-by: Diederik de Haas <diederik@cknow-tech.com>
Closes: https://bugs.kde.org/show_bug.cgi?id=511274
Signed-off-by: Andy Yan <andy.yan@rock-chips.com>
Tested-by: Dang Huynh <dang.huynh@mainlining.org>
Tested-by: Diederik de Haas <diederik@cknow-tech.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://lore.kernel.org/r/20251112085024.2480111-1-andyshrk@163.com
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user