From db97dd0eef3af860a7e9886e271709590feafee7 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 4 Feb 2019 12:01:31 +0100 Subject: [PATCH] drm/cirrus: add plane setup 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 Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20190204110131.21467-1-kraxel@redhat.com --- drivers/gpu/drm/cirrus/cirrus_mode.c | 70 +++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index a830e70f..7f9bc32 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -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; -- 2.7.4