drm/rockchip: vop2: Register the primary plane and overlay plane separately
authorAndy Yan <andy.yan@rock-chips.com>
Mon, 3 Mar 2025 03:44:15 +0000 (11:44 +0800)
committerHeiko Stuebner <heiko@sntech.de>
Mon, 3 Mar 2025 21:35:18 +0000 (22:35 +0100)
In the upcoming VOP of rk3576, a Window cannot attach to all Video Ports,
so make sure all VP find it's suitable primary plane, then register the
remain windows as overlay plane will make code easier.

Signed-off-by: Andy Yan <andy.yan@rock-chips.com>
Tested-by: Michael Riesch <michael.riesch@wolfvision.net> # on RK3568
Tested-by: Detlev Casanova <detlev.casanova@collabora.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20250303034436.192400-2-andyshrk@163.com
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c

index bebe5bd70b90532f3adb3f54b9371b5ad59d3985..0af5059ff7d8b2a74d4632b276a18e477caa9675 100644 (file)
@@ -2264,22 +2264,29 @@ static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win,
        return 0;
 }
 
-static struct vop2_video_port *find_vp_without_primary(struct vop2 *vop2)
+/*
+ * On RK3566 these windows don't have an independent
+ * framebuffer. They can only share/mirror the framebuffer
+ * with smart0, esmart0 and cluster0 respectively.
+ * And RK3566 share the same vop version with Rk3568, so we
+ * need to use soc_id for identification here.
+ */
+static bool vop2_is_mirror_win(struct vop2_win *win)
 {
-       int i;
-
-       for (i = 0; i < vop2->data->nr_vps; i++) {
-               struct vop2_video_port *vp = &vop2->vps[i];
-
-               if (!vp->crtc.port)
-                       continue;
-               if (vp->primary_plane)
-                       continue;
+       struct vop2 *vop2 = win->vop2;
 
-               return vp;
+       if (vop2->data->soc_id == 3566) {
+               switch (win->data->phys_id) {
+               case ROCKCHIP_VOP2_SMART1:
+               case ROCKCHIP_VOP2_ESMART1:
+               case ROCKCHIP_VOP2_CLUSTER1:
+                       return true;
+               default:
+                       return false;
+               }
+       } else {
+               return false;
        }
-
-       return NULL;
 }
 
 static int vop2_create_crtcs(struct vop2 *vop2)
@@ -2290,7 +2297,9 @@ static int vop2_create_crtcs(struct vop2 *vop2)
        struct drm_plane *plane;
        struct device_node *port;
        struct vop2_video_port *vp;
-       int i, nvp, nvps = 0;
+       struct vop2_win *win;
+       u32 possible_crtcs;
+       int i, j, nvp, nvps = 0;
        int ret;
 
        for (i = 0; i < vop2_data->nr_vps; i++) {
@@ -2326,42 +2335,54 @@ static int vop2_create_crtcs(struct vop2 *vop2)
        }
 
        nvp = 0;
-       for (i = 0; i < vop2->registered_num_wins; i++) {
-               struct vop2_win *win = &vop2->win[i];
-               u32 possible_crtcs = 0;
-
-               if (vop2->data->soc_id == 3566) {
-                       /*
-                        * On RK3566 these windows don't have an independent
-                        * framebuffer. They share the framebuffer with smart0,
-                        * esmart0 and cluster0 respectively.
-                        */
-                       switch (win->data->phys_id) {
-                       case ROCKCHIP_VOP2_SMART1:
-                       case ROCKCHIP_VOP2_ESMART1:
-                       case ROCKCHIP_VOP2_CLUSTER1:
+       /* Register a primary plane for every crtc */
+       for (i = 0; i < vop2_data->nr_vps; i++) {
+               vp = &vop2->vps[i];
+
+               if (!vp->crtc.port)
+                       continue;
+
+               for (j = 0; j < vop2->registered_num_wins; j++) {
+                       win = &vop2->win[j];
+
+                       /* Aready registered as primary plane */
+                       if (win->base.type == DRM_PLANE_TYPE_PRIMARY)
+                               continue;
+
+                       if (vop2_is_mirror_win(win))
                                continue;
-                       }
-               }
 
-               if (win->type == DRM_PLANE_TYPE_PRIMARY) {
-                       vp = find_vp_without_primary(vop2);
-                       if (vp) {
+                       if (win->type == DRM_PLANE_TYPE_PRIMARY) {
                                possible_crtcs = BIT(nvp);
                                vp->primary_plane = win;
+                               ret = vop2_plane_init(vop2, win, possible_crtcs);
+                               if (ret)
+                                       return dev_err_probe(drm->dev, ret,
+                                                            "failed to init primary plane %s\n",
+                                                            win->data->name);
                                nvp++;
-                       } else {
-                               /* change the unused primary window to overlay window */
-                               win->type = DRM_PLANE_TYPE_OVERLAY;
+                               break;
                        }
                }
+       }
+
+       /* Register all unused window as overlay plane */
+       for (i = 0; i < vop2->registered_num_wins; i++) {
+               win = &vop2->win[i];
+
+               /* Aready registered as primary plane */
+               if (win->base.type == DRM_PLANE_TYPE_PRIMARY)
+                       continue;
+
+               if (vop2_is_mirror_win(win))
+                       continue;
 
-               if (win->type == DRM_PLANE_TYPE_OVERLAY)
-                       possible_crtcs = (1 << nvps) - 1;
+               win->type = DRM_PLANE_TYPE_OVERLAY;
 
+               possible_crtcs = (1 << nvps) - 1;
                ret = vop2_plane_init(vop2, win, possible_crtcs);
                if (ret)
-                       return dev_err_probe(drm->dev, ret, "failed to init plane %s\n",
+                       return dev_err_probe(drm->dev, ret, "failed to init overlay plane %s\n",
                                             win->data->name);
        }