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[] = {