From a103f1595b5eced3ef63d5bf3d2dcb4124c7fc8e Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Thu, 1 Apr 2021 16:32:13 +0800 Subject: [PATCH] drm/rockchip: vop2: add parse plane mask policy from uboot or dts file Change-Id: I8608dfeb44ab02717d64da151aefe1f9548c936b Signed-off-by: Sandy Huang --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 164 ++++++++++++++++--- drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 28 ++-- 2 files changed, 154 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 66998a814790..0ee9b37f1b7c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -183,6 +183,20 @@ enum vop2_pending { VOP_PENDING_FB_UNREF, }; +enum vop2_layer_phy_id { + ROCKCHIP_VOP2_CLUSTER0 = 0, + ROCKCHIP_VOP2_CLUSTER1, + ROCKCHIP_VOP2_ESMART0, + ROCKCHIP_VOP2_ESMART1, + ROCKCHIP_VOP2_SMART0, + ROCKCHIP_VOP2_SMART1, + ROCKCHIP_VOP2_CLUSTER2, + ROCKCHIP_VOP2_CLUSTER3, + ROCKCHIP_VOP2_ESMART2, + ROCKCHIP_VOP2_ESMART3, + ROCKCHIP_VOP2_PHY_ID_INVALID = -1, +}; + struct vop2_zpos { int win_phys_id; int zpos; @@ -492,6 +506,23 @@ struct vop2_video_port { * @loader_protect: loader logo protect state */ bool loader_protect; + + /** + * @plane_mask: show the plane attach to this vp, + * it maybe init at dts file or uboot driver + */ + uint32_t plane_mask; + + /** + * @plane_mask_prop: plane mask interaction with userspace + */ + struct drm_property *plane_mask_prop; + + /** + * @primary_plane_phy_id: vp primary plane phy id, the primary plane + * will be used to show uboot logo and kernel logo + */ + enum vop2_layer_phy_id primary_plane_phy_id; }; struct vop2 { @@ -2338,21 +2369,8 @@ static void vop2_layer_map_initial(struct vop2 *vop2, uint32_t current_vp_id) shift = vop2->data->ctrl->win_vp_id[j].shift; vp_id = (win_map >> shift) & 0x3; if (vp_id == i) { - /* - * If the Video Port is not activated, - * move the attached win to the last Video Port - * we want enabled. - */ - if (active_vp_mask & BIT(vp_id)) { - vp->win_mask |= BIT(j); - win->vp_mask = BIT(vp_id); - - } else { - last_active_vp->win_mask |= BIT(j); - win->vp_mask = BIT(last_active_vp->id); - VOP_CTRL_SET(vop2, win_vp_id[win->phys_id], last_active_vp->id); - - } + vp->win_mask |= BIT(j); + win->vp_mask = BIT(vp_id); win->old_vp_mask = win->vp_mask; } } @@ -5642,6 +5660,40 @@ static void vop2_cubic_lut_init(struct vop2 *vop2) } } +static int vop2_crtc_create_plane_mask_property(struct vop2 *vop2, + struct drm_crtc *crtc) +{ + struct drm_property *prop; + struct vop2_video_port *vp = to_vop2_video_port(crtc); + + static const struct drm_prop_enum_list props[] = { + { ROCKCHIP_VOP2_CLUSTER0, "Cluster0" }, + { ROCKCHIP_VOP2_CLUSTER1, "Cluster1" }, + { ROCKCHIP_VOP2_ESMART0, "Esmart0" }, + { ROCKCHIP_VOP2_ESMART1, "Esmart1" }, + { ROCKCHIP_VOP2_SMART0, "Smart0" }, + { ROCKCHIP_VOP2_SMART1, "Smart1" }, + { ROCKCHIP_VOP2_CLUSTER2, "Cluster2" }, + { ROCKCHIP_VOP2_CLUSTER3, "Cluster3" }, + { ROCKCHIP_VOP2_ESMART2, "Esmart2" }, + { ROCKCHIP_VOP2_ESMART3, "Esmart3" }, + }; + + prop = drm_property_create_bitmask(vop2->drm_dev, + DRM_MODE_PROP_IMMUTABLE, "PLANE_MASK", + props, ARRAY_SIZE(props), + 0xffffffff); + if (!prop) { + DRM_DEV_ERROR(vop2->dev, "create plane_mask prop for vp%d failed\n", vp->id); + return -ENOMEM; + } + + vp->plane_mask_prop = prop; + drm_object_attach_property(&crtc->base, vp->plane_mask_prop, vp->plane_mask); + + return 0; +} + static int vop2_create_crtc(struct vop2 *vop2) { const struct vop2_data *vop2_data = vop2->data; @@ -5656,8 +5708,10 @@ static int vop2_create_crtc(struct vop2 *vop2) uint32_t possible_crtcs; uint64_t soc_id; char dclk_name[9]; - int i = 0, j = 0; + int i = 0, j = 0, k = 0; int ret = 0; + bool be_used_for_primary_plane = false; + bool find_primary_plane = false; /* all planes can attach to any crtc */ possible_crtcs = (1 << vop2_data->nr_vps) - 1; @@ -5687,16 +5741,41 @@ static int vop2_create_crtc(struct vop2 *vop2) crtc = &vp->crtc; - while (j < vop2->registered_num_wins) { - win = &vop2->win[j]; - j++; + if (vp->primary_plane_phy_id >= 0) { + win = vop2_find_win_by_phys_id(vop2, vp->primary_plane_phy_id); + if (win) + find_primary_plane = true; + } else { + while (j < vop2->registered_num_wins) { + be_used_for_primary_plane = false; + win = &vop2->win[j]; + j++; - if (win->type == DRM_PLANE_TYPE_PRIMARY) + if (win->parent || (win->feature & WIN_FEATURE_CLUSTER_SUB)) + continue; + + if (win->type != DRM_PLANE_TYPE_PRIMARY) + continue; + + for (k = 0; k < vop2_data->nr_vps; k++) { + if (win->phys_id == vop2->vps[k].primary_plane_phy_id) { + be_used_for_primary_plane = true; + break; + } + } + + if (be_used_for_primary_plane) + continue; + + find_primary_plane = true; break; - win = NULL; + } + + if (find_primary_plane) + vp->primary_plane_phy_id = win->phys_id; } - if (!win) { + if (!find_primary_plane) { DRM_DEV_ERROR(vop2->dev, "No primary plane find for video_port%d\n", i); break; } @@ -5740,14 +5819,25 @@ static int vop2_create_crtc(struct vop2 *vop2) drm_dev->mode_config.tv_top_margin_property, 100); drm_object_attach_property(&crtc->base, drm_dev->mode_config.tv_bottom_margin_property, 100); + vop2_crtc_create_plane_mask_property(vop2, crtc); } /* * change the unused primary window to overlay window */ - for (; j < vop2->registered_num_wins; j++) { + for (j = 0; j < vop2->registered_num_wins; j++) { win = &vop2->win[j]; - if (win->type == DRM_PLANE_TYPE_PRIMARY) + be_used_for_primary_plane = false; + + for (k = 0; k < vop2_data->nr_vps; k++) { + if (vop2->vps[k].primary_plane_phy_id == win->phys_id) { + be_used_for_primary_plane = true; + break; + } + } + + if (win->type == DRM_PLANE_TYPE_PRIMARY && + !be_used_for_primary_plane) win->type = DRM_PLANE_TYPE_OVERLAY; } @@ -5918,6 +6008,7 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) size_t alloc_size; int ret, i; int num_wins = 0; + struct device_node *vop_out_node; vop2_data = of_device_get_match_data(dev); if (!vop2_data) @@ -5988,6 +6079,31 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) return vop2->irq; } + vop_out_node = of_get_child_by_name(dev->of_node, "ports"); + if (vop_out_node) { + struct device_node *child; + + for_each_child_of_node(vop_out_node, child) { + u32 plane_mask = 0; + u32 primary_plane_phy_id = 0; + u32 vp_id = 0; + + of_property_read_u32(child, "rockchip,plane-mask", &plane_mask); + of_property_read_u32(child, "rockchip,primary-plane", &primary_plane_phy_id); + of_property_read_u32(child, "reg", &vp_id); + + vop2->vps[vp_id].plane_mask = plane_mask; + if (plane_mask) + vop2->vps[vp_id].primary_plane_phy_id = primary_plane_phy_id; + else + vop2->vps[vp_id].primary_plane_phy_id = ROCKCHIP_VOP2_PHY_ID_INVALID; + + 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); + } + } + spin_lock_init(&vop2->reg_lock); spin_lock_init(&vop2->irq_lock); mutex_init(&vop2->vop2_lock); diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index 34251562e1e8..e7787297d8b2 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -1101,20 +1101,20 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { .regs = &rk3568_esmart_win_data, .area = rk3568_area_data, .area_size = ARRAY_SIZE(rk3568_area_data), - .type = DRM_PLANE_TYPE_PRIMARY, + .type = DRM_PLANE_TYPE_OVERLAY, .max_upscale_factor = 8, .max_downscale_factor = 8, .dly = { 20, 47, 41 }, }, { - .name = "Smart0-win0", - .phys_id = 4, - .base = 0x400, - .formats = formats_win_lite, - .nformats = ARRAY_SIZE(formats_win_lite), + .name = "Esmart1-win0", + .phys_id = 3, + .formats = formats_win_full_10bit_yuyv, + .nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv), .format_modifiers = format_modifiers, - .layer_sel_id = 3, + .base = 0x200, + .layer_sel_id = 6, .supported_rotations = DRM_MODE_REFLECT_Y, .hsu_filter_mode = VOP2_SCALE_UP_BIC, .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, @@ -1130,13 +1130,13 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { }, { - .name = "Esmart1-win0", - .phys_id = 3, - .formats = formats_win_full_10bit_yuyv, - .nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv), + .name = "Smart0-win0", + .phys_id = 4, + .base = 0x400, + .formats = formats_win_lite, + .nformats = ARRAY_SIZE(formats_win_lite), .format_modifiers = format_modifiers, - .base = 0x200, - .layer_sel_id = 6, + .layer_sel_id = 3, .supported_rotations = DRM_MODE_REFLECT_Y, .hsu_filter_mode = VOP2_SCALE_UP_BIC, .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, @@ -1167,7 +1167,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { .regs = &rk3568_esmart_win_data, .area = rk3568_area_data, .area_size = ARRAY_SIZE(rk3568_area_data), - .type = DRM_PLANE_TYPE_OVERLAY, + .type = DRM_PLANE_TYPE_PRIMARY, .max_upscale_factor = 8, .max_downscale_factor = 8, .dly = { 20, 47, 41 },