From 00424a589d3d3a242748e915f42b3ea7b01e611d Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Tue, 11 Apr 2023 18:13:12 +0800 Subject: [PATCH] drm/rockchip: vop2: add support to assign plane mask by default If not to enable uboot logo, neither to set plane mask in dts. For RK3568 and RK3588, it is needed to assign plane mask by default. Signed-off-by: Damon Ding Change-Id: I9ebbc32b89b503784a225cc482e7cbde15508843 --- drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 8 + drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 102 ++++++++++- drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 171 +++++++++++++++++++ 3 files changed, 279 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 896ebfa760a4..aeab8b3d8997 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -1329,6 +1329,12 @@ struct vop_dump_regs { bool enable_state; }; +struct vop2_vp_plane_mask { + u8 primary_plane_id; + u8 attached_layers_nr; + u8 attached_layers[ROCKCHIP_MAX_LAYER]; +}; + /** * VOP2 data structe * @@ -1373,6 +1379,8 @@ struct vop2_data { uint32_t dump_regs_size; struct vop_rect max_input; struct vop_rect max_output; + const struct vop2_vp_plane_mask *plane_mask; + uint32_t plane_mask_base; unsigned int win_size; }; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index c2d210141793..6c56dfd5cf41 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -11360,6 +11360,97 @@ static void post_buf_empty_work_event(struct work_struct *work) } } +static bool vop2_plane_mask_check(struct vop2 *vop2) +{ + const struct vop2_data *vop2_data = vop2->data; + u32 plane_mask = 0; + int i; + + /* + * 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 (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) { + DRM_WARN("the same window can't be assigned to two vp\n"); + return false; + } + plane_mask |= vop2->vps[i].plane_mask; + } + + if (hweight32(plane_mask) != vop2_data->nr_layers || + plane_mask != vop2_data->plane_mask_base) { + DRM_WARN("all windows should be assigned, full plane mask: 0x%x, current plane mask: 0x%x\n", + vop2_data->plane_mask_base, plane_mask); + return false; + } + + return true; +} + +static uint32_t vop2_vp_plane_mask_to_bitmap(const struct vop2_vp_plane_mask *vp_plane_mask) +{ + int layer_phy_id = 0; + int plane_mask = 0; + int i; + + for (i = 0; i < vp_plane_mask->attached_layers_nr; i++) { + layer_phy_id = vp_plane_mask->attached_layers[i]; + plane_mask |= BIT(layer_phy_id); + } + + return plane_mask; +} + +static bool vop2_get_vp_of_status(struct device_node *vp_node) +{ + struct device_node *vp_sub_node; + struct device_node *remote_node; + bool vp_enable = false; + + for_each_child_of_node(vp_node, vp_sub_node) { + remote_node = of_graph_get_remote_endpoint(vp_sub_node); + vp_enable |= of_device_is_available(remote_node); + } + + return vp_enable; +} + +static void vop2_plane_mask_assign(struct vop2 *vop2, struct device_node *vop_out_node) +{ + const struct vop2_data *vop2_data = vop2->data; + const struct vop2_vp_plane_mask *plane_mask; + struct device_node *child; + int active_vp_num = 0; + int vp_id; + int i = 0; + + for_each_child_of_node(vop_out_node, child) { + if (vop2_get_vp_of_status(child)) + active_vp_num++; + } + + if (vop2_soc_is_rk3566() && active_vp_num > 2) + DRM_WARN("RK3566 only support 2 vps\n"); + plane_mask = vop2_data->plane_mask; + plane_mask += (active_vp_num - 1) * ROCKCHIP_MAX_CRTC; + + for_each_child_of_node(vop_out_node, child) { + of_property_read_u32(child, "reg", &vp_id); + if (vop2_get_vp_of_status(child)) { + vop2->vps[vp_id].plane_mask = vop2_vp_plane_mask_to_bitmap(&plane_mask[i]); + vop2->vps[vp_id].primary_plane_phy_id = plane_mask[i].primary_plane_id; + i++; + } else { + vop2->vps[vp_id].plane_mask = 0; + vop2->vps[vp_id].primary_plane_phy_id = ROCKCHIP_VOP2_PHY_ID_INVALID; + } + } +} + static int vop2_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); @@ -11538,10 +11629,17 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) if (!of_property_read_u32(mcu_timing_node, "mcu-hold-mode", &val)) vop2->vps[vp_id].mcu_timing.mcu_hold_mode = val; } + } + if (!vop2_plane_mask_check(vop2)) { + DRM_WARN("use default plane mask\n"); + vop2_plane_mask_assign(vop2, vop_out_node); + } + + for (i = 0; i < vop2->data->nr_vps; i++) { DRM_DEV_INFO(dev, "vp%d assign plane mask: 0x%x, primary plane phy id: %d\n", - vp_id, vop2->vps[vp_id].plane_mask, - vop2->vps[vp_id].primary_plane_phy_id); + i, vop2->vps[i].plane_mask, + vop2->vps[i].primary_plane_phy_id); } } diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index 8e835112b389..dd240faafc5c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -3665,6 +3665,173 @@ static const struct vop_dump_regs rk3588_dump_regs[] = { { RK3568_HDR_LUT_CTRL, "HDR", {0}, 0 }, }; +#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 RK3588_PLANE_MASK_BASE \ + (BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1) | \ + BIT(ROCKCHIP_VOP2_CLUSTER2) | BIT(ROCKCHIP_VOP2_CLUSTER3) | \ + BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \ + BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3)) + +static struct vop2_vp_plane_mask rk3568_vp_plane_mask[ROCKCHIP_MAX_CRTC][ROCKCHIP_MAX_CRTC] = { + { /* one display policy */ + {/* main display */ + .primary_plane_id = ROCKCHIP_VOP2_SMART0, + .attached_layers_nr = 6, + .attached_layers = { + ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0, + ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 + }, + }, + {/* second display */}, + {/* third display */}, + {/* fourth display */}, + }, + + { /* two display policy */ + {/* main display */ + .primary_plane_id = ROCKCHIP_VOP2_SMART0, + .attached_layers_nr = 3, + .attached_layers = { + ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 + }, + }, + + {/* second display */ + .primary_plane_id = ROCKCHIP_VOP2_SMART1, + .attached_layers_nr = 3, + .attached_layers = { + ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 + }, + }, + {/* third display */}, + {/* fourth display */}, + }, + + { /* three display policy */ + {/* main display */ + .primary_plane_id = ROCKCHIP_VOP2_SMART0, + .attached_layers_nr = 3, + .attached_layers = { + ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 + }, + }, + + {/* second display */ + .primary_plane_id = ROCKCHIP_VOP2_SMART1, + .attached_layers_nr = 2, + .attached_layers = { + ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1 + }, + }, + + {/* third display */ + .primary_plane_id = ROCKCHIP_VOP2_ESMART1, + .attached_layers_nr = 1, + .attached_layers = { ROCKCHIP_VOP2_ESMART1 }, + }, + + {/* fourth display */}, + }, + + {/* reserved for four display policy */}, +}; + +static struct vop2_vp_plane_mask rk3588_vp_plane_mask[ROCKCHIP_MAX_CRTC][ROCKCHIP_MAX_CRTC] = { + { /* one display policy */ + {/* main display */ + .primary_plane_id = ROCKCHIP_VOP2_ESMART0, + .attached_layers_nr = 8, + .attached_layers = { + ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART2, + ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART3, + ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3 + }, + }, + {/* second display */}, + {/* third display */}, + {/* fourth display */}, + }, + + { /* two display policy */ + {/* main display */ + .primary_plane_id = ROCKCHIP_VOP2_ESMART0, + .attached_layers_nr = 4, + .attached_layers = { + ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, + ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 + }, + }, + + {/* second display */ + .primary_plane_id = ROCKCHIP_VOP2_ESMART2, + .attached_layers_nr = 4, + .attached_layers = { + ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2, + ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 + }, + }, + {/* third display */}, + {/* fourth display */}, + }, + + { /* three display policy */ + {/* main display */ + .primary_plane_id = ROCKCHIP_VOP2_ESMART0, + .attached_layers_nr = 3, + .attached_layers = { + ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART0 + }, + }, + + {/* second display */ + .primary_plane_id = ROCKCHIP_VOP2_ESMART1, + .attached_layers_nr = 3, + .attached_layers = { + ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART1 + }, + }, + + {/* third display */ + .primary_plane_id = ROCKCHIP_VOP2_ESMART2, + .attached_layers_nr = 2, + .attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 }, + }, + + {/* fourth display */}, + }, + + { /* four display policy */ + {/* main display */ + .primary_plane_id = ROCKCHIP_VOP2_ESMART0, + .attached_layers_nr = 2, + .attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 }, + }, + + {/* second display */ + .primary_plane_id = ROCKCHIP_VOP2_ESMART1, + .attached_layers_nr = 2, + .attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 }, + }, + + {/* third display */ + .primary_plane_id = ROCKCHIP_VOP2_ESMART2, + .attached_layers_nr = 2, + .attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 }, + }, + + {/* fourth display */ + .primary_plane_id = ROCKCHIP_VOP2_ESMART3, + .attached_layers_nr = 2, + .attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 }, + }, + }, + +}; + static const struct vop2_data rk3528_vop = { .version = VOP_VERSION_RK3528, .nr_vps = 2, @@ -3725,6 +3892,8 @@ static const struct vop2_data rk3568_vop = { .win_size = ARRAY_SIZE(rk3568_vop_win_data), .dump_regs = rk3568_dump_regs, .dump_regs_size = ARRAY_SIZE(rk3568_dump_regs), + .plane_mask = rk3568_vp_plane_mask[0], + .plane_mask_base = RK3568_PLANE_MASK_BASE, }; static const struct vop2_data rk3588_vop = { @@ -3761,6 +3930,8 @@ static const struct vop2_data rk3588_vop = { .nr_mem_pgs = ARRAY_SIZE(rk3588_vop_mem_pg_data), .dump_regs = rk3588_dump_regs, .dump_regs_size = ARRAY_SIZE(rk3588_dump_regs), + .plane_mask = rk3588_vp_plane_mask[0], + .plane_mask_base = RK3588_PLANE_MASK_BASE, }; static const struct of_device_id vop2_dt_match[] = {