drm/cirrus: add plane setup
authorGerd Hoffmann <kraxel@redhat.com>
Mon, 4 Feb 2019 11:01:31 +0000 (12:01 +0100)
committerGerd Hoffmann <kraxel@redhat.com>
Tue, 5 Feb 2019 09:28:13 +0000 (10:28 +0100)
Commit "f4bd542bca drm/fb-helper: Scale back depth to supported maximum"
uncovered a bug in the cirrus driver.  It must create its own primary
plane, using the correct format list, depending on the bpp module
parameter, so it is consistent with mode_config->preferred_depth.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20190204110131.21467-1-kraxel@redhat.com
drivers/gpu/drm/cirrus/cirrus_mode.c

index a830e70..7f9bc32 100644 (file)
@@ -360,10 +360,70 @@ static const struct drm_crtc_helper_funcs cirrus_helper_funcs = {
 };
 
 /* CRTC setup */
+static const uint32_t cirrus_formats_16[] = {
+       DRM_FORMAT_RGB565,
+};
+
+static const uint32_t cirrus_formats_24[] = {
+       DRM_FORMAT_RGB888,
+       DRM_FORMAT_RGB565,
+};
+
+static const uint32_t cirrus_formats_32[] = {
+       DRM_FORMAT_XRGB8888,
+       DRM_FORMAT_ARGB8888,
+       DRM_FORMAT_RGB888,
+       DRM_FORMAT_RGB565,
+};
+
+static struct drm_plane *cirrus_primary_plane(struct drm_device *dev)
+{
+       const uint32_t *formats;
+       uint32_t nformats;
+       struct drm_plane *primary;
+       int ret;
+
+       switch (cirrus_bpp) {
+       case 16:
+               formats = cirrus_formats_16;
+               nformats = ARRAY_SIZE(cirrus_formats_16);
+               break;
+       case 24:
+               formats = cirrus_formats_24;
+               nformats = ARRAY_SIZE(cirrus_formats_24);
+               break;
+       case 32:
+               formats = cirrus_formats_32;
+               nformats = ARRAY_SIZE(cirrus_formats_32);
+               break;
+       default:
+               return NULL;
+       }
+
+       primary = kzalloc(sizeof(*primary), GFP_KERNEL);
+       if (primary == NULL) {
+               DRM_DEBUG_KMS("Failed to allocate primary plane\n");
+               return NULL;
+       }
+
+       ret = drm_universal_plane_init(dev, primary, 0,
+                                      &drm_primary_helper_funcs,
+                                      formats, nformats,
+                                      NULL,
+                                      DRM_PLANE_TYPE_PRIMARY, NULL);
+       if (ret) {
+               kfree(primary);
+               primary = NULL;
+       }
+
+       return primary;
+}
+
 static void cirrus_crtc_init(struct drm_device *dev)
 {
        struct cirrus_device *cdev = dev->dev_private;
        struct cirrus_crtc *cirrus_crtc;
+       struct drm_plane *primary;
 
        cirrus_crtc = kzalloc(sizeof(struct cirrus_crtc) +
                              (CIRRUSFB_CONN_LIMIT * sizeof(struct drm_connector *)),
@@ -372,7 +432,15 @@ static void cirrus_crtc_init(struct drm_device *dev)
        if (cirrus_crtc == NULL)
                return;
 
-       drm_crtc_init(dev, &cirrus_crtc->base, &cirrus_crtc_funcs);
+       primary = cirrus_primary_plane(dev);
+       if (primary == NULL) {
+               kfree(cirrus_crtc);
+               return;
+       }
+
+       drm_crtc_init_with_planes(dev, &cirrus_crtc->base,
+                                 primary, NULL,
+                                 &cirrus_crtc_funcs, NULL);
 
        drm_mode_crtc_set_gamma_size(&cirrus_crtc->base, CIRRUS_LUT_SIZE);
        cdev->mode_info.crtc = cirrus_crtc;