drm/rockchip: vop2: add support to assign plane_mask for RK3528/RK3562/RK3576

RK3528/RK3562/RK3576 use the VOP3 architecture, which supports
flexible switching of planes between different VP. User can switch
planes between different CRTCs based on the &drm_plane.possible_crtcs
in userspace, and the plane-mask does not need to be assigned by
default in DTS.

However, for some Linux systems, there may still be scenarios where
it is necessary to specify the primary and cursor planes specifically
used on a VP.

Therefore, the valid plane-mask assignment will change the
&drm_plane.possible_crtcs and establish a fixed binding relationship
between planes and CRTCs, which means that the flexible switching of
planes is not available in the case.

Change-Id: I156f71ceb238c5945a92f48c0024f398711ea811
Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
This commit is contained in:
Damon Ding
2025-01-22 09:57:36 +08:00
committed by Tao Huang
parent 5043d1a786
commit 708010d987
2 changed files with 122 additions and 10 deletions

View File

@@ -15282,29 +15282,103 @@ static void post_buf_empty_work_event(struct work_struct *work)
}
}
static void vop2_plane_mask_to_possible_vp_mask(struct vop2 *vop2)
{
const struct vop2_data *vop2_data = vop2->data;
struct vop2_video_port *vp;
struct vop2_win *win;
uint32_t plane_mask;
uint32_t nr_planes;
uint32_t phys_id;
int i, j, k;
for (i = 0; i < vop2->registered_num_wins; i++) {
win = &vop2->win[i];
win->possible_vp_mask = 0;
}
for (i = 0; i < vop2_data->nr_vps; i++) {
vp = &vop2->vps[i];
plane_mask = vp->plane_mask;
nr_planes = hweight32(plane_mask);
for (j = 0; j < nr_planes; j++) {
phys_id = ffs(plane_mask) - 1;
for (k = 0; k < vop2->registered_num_wins; k++) {
win = &vop2->win[k];
if (win->phys_id == phys_id)
win->possible_vp_mask |= BIT(i);
}
plane_mask &= ~BIT(phys_id);
}
}
}
/*
* The function checks whether the 'rockchip,plane-mask' property assigned
* in DTS is valid.
*/
static bool vop2_plane_mask_check(struct vop2 *vop2)
{
const struct vop2_data *vop2_data = vop2->data;
struct vop2_video_port *vp;
struct vop2_win *win;
char *full_plane, *current_plane;
u32 plane_mask = 0;
int i;
u32 full_plane_mask = 0, plane_mask = 0;
u32 phys_id;
u32 nr_planes;
int i, j;
/*
* For RK3568 and RK3588, all windows need to be assigned to
* one of all vps, and two of vps can not share the same window.
* If plane_mask is assigned in DTS, then every plane need to be assigned to
* one of all the VPs, and no single plane can be assigned to more than one
* VP.
*/
if (vop2->version != VOP_VERSION_RK3568 && vop2->version != VOP_VERSION_RK3588)
return true;
for (i = 0; i < vop2_data->nr_vps; i++) {
if (plane_mask & vop2->vps[i].plane_mask) {
vp = &vop2->vps[i];
plane_mask = vp->plane_mask;
nr_planes = hweight32(plane_mask);
/*
* Every plane assigned to the specific VP should follow the constraints
* of default &vop2_win.possible_vp_mask.
*/
for (j = 0; j < nr_planes; j++) {
phys_id = ffs(plane_mask) - 1;
win = vop2_find_win_by_phys_id(vop2, phys_id);
if (!win) {
DRM_WARN("Invalid plane id %d in VP%d assigned plane mask\n",
phys_id, i);
return false;
}
if (!(win->possible_vp_mask & BIT(i))) {
DRM_WARN("%s can not attach to VP%d\n",
vop2_plane_phys_id_to_string(phys_id), i);
return false;
}
plane_mask &= ~BIT(phys_id);
}
if (full_plane_mask & vop2->vps[i].plane_mask) {
DRM_WARN("the same window can't be assigned to two vp\n");
return false;
}
plane_mask |= vop2->vps[i].plane_mask;
full_plane_mask |= vop2->vps[i].plane_mask;
}
if (plane_mask != vop2_data->plane_mask_base) {
/*
* For VOP3, the DTS assignment of plane_mask is not mandatory. If no plane_mask
* assignment, the planes can be switched between different CRTCs according to
* the &drm_plane.possible_crtcs.
*/
if (is_vop3(vop2) && !full_plane_mask)
return true;
if (full_plane_mask != vop2_data->plane_mask_base) {
full_plane = vop2_plane_mask_to_string(vop2_data->plane_mask_base);
current_plane = vop2_plane_mask_to_string(plane_mask);
DRM_WARN("all windows should be assigned, full plane mask: %s[0x%x], current plane mask: %s[0x%x]\n",
@@ -15314,6 +15388,12 @@ static bool vop2_plane_mask_check(struct vop2 *vop2)
return false;
}
/*
* If plane_mask assigned in DTS is valid, then convert it to &vop2_win.possible_vp_mask
* and replace the default one with it.
*/
vop2_plane_mask_to_possible_vp_mask(vop2);
return true;
}
@@ -15354,6 +15434,21 @@ static void vop2_plane_mask_assign(struct vop2 *vop2, struct device_node *vop_ou
int vp_id;
int i = 0;
/*
* For VOP3, users can switch planes between different CRTCs base on the
* &drm_plane.possible_crtcs that exported to the userspace. Therefore,
* there is no need to set the &vop2_video_port.plane_mask and
* &vop2_video_port.primary_plane_phy_id by default, which are used to
* fix the binding relationship between the plane and the CRTC for VOP2.
*/
if (is_vop3(vop2)) {
for (i = 0; i < vop2->data->nr_vps; i++) {
vop2->vps[i].plane_mask = 0;
vop2->vps[i].primary_plane_phy_id = ROCKCHIP_VOP2_PHY_ID_INVALID;
}
return;
}
for_each_child_of_node(vop_out_node, child) {
if (vop2_get_vp_of_status(child))
active_vp_num++;

View File

@@ -5046,11 +5046,25 @@ static const struct vop_dump_regs rk3588_dump_regs[] = {
{ RK3568_HDR_LUT_CTRL, "HDR", {0}, 0 },
};
#define RK3528_PLANE_MASK_BASE \
(BIT(ROCKCHIP_VOP2_CLUSTER0) | \
BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \
BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3))
#define RK3562_PLANE_MASK_BASE \
(BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \
BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3))
#define RK3568_PLANE_MASK_BASE \
(BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1) | \
BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \
BIT(ROCKCHIP_VOP2_SMART0) | BIT(ROCKCHIP_VOP2_SMART1))
#define RK3576_PLANE_MASK_BASE \
(BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1) | \
BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \
BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3))
#define RK3588_PLANE_MASK_BASE \
(BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1) | \
BIT(ROCKCHIP_VOP2_CLUSTER2) | BIT(ROCKCHIP_VOP2_CLUSTER3) | \
@@ -5244,6 +5258,7 @@ static const struct vop2_data rk3528_vop = {
.win_size = ARRAY_SIZE(rk3528_vop_win_data),
.dump_regs = rk3528_dump_regs,
.dump_regs_size = ARRAY_SIZE(rk3528_dump_regs),
.plane_mask_base = RK3528_PLANE_MASK_BASE,
};
static const struct vop2_data rk3562_vop = {
@@ -5265,6 +5280,7 @@ static const struct vop2_data rk3562_vop = {
.win_size = ARRAY_SIZE(rk3562_vop_win_data),
.dump_regs = rk3562_dump_regs,
.dump_regs_size = ARRAY_SIZE(rk3562_dump_regs),
.plane_mask_base = RK3562_PLANE_MASK_BASE,
};
static const struct vop2_data rk3568_vop = {
@@ -5313,6 +5329,7 @@ static const struct vop2_data rk3576_vop = {
.nr_pds = ARRAY_SIZE(rk3576_vop_pd_data),
.dump_regs = rk3576_dump_regs,
.dump_regs_size = ARRAY_SIZE(rk3576_dump_regs),
.plane_mask_base = RK3576_PLANE_MASK_BASE,
.crc_sources = rk3576_crc_sources,
.crc_sources_num = ARRAY_SIZE(rk3576_crc_sources),
};