Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <kraxel@redhat.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20190204110131.21467-1-kraxel@redhat.com

+69 -1
+69 -1
drivers/gpu/drm/cirrus/cirrus_mode.c
··· 360 360 }; 361 361 362 362 /* CRTC setup */ 363 + static const uint32_t cirrus_formats_16[] = { 364 + DRM_FORMAT_RGB565, 365 + }; 366 + 367 + static const uint32_t cirrus_formats_24[] = { 368 + DRM_FORMAT_RGB888, 369 + DRM_FORMAT_RGB565, 370 + }; 371 + 372 + static const uint32_t cirrus_formats_32[] = { 373 + DRM_FORMAT_XRGB8888, 374 + DRM_FORMAT_ARGB8888, 375 + DRM_FORMAT_RGB888, 376 + DRM_FORMAT_RGB565, 377 + }; 378 + 379 + static struct drm_plane *cirrus_primary_plane(struct drm_device *dev) 380 + { 381 + const uint32_t *formats; 382 + uint32_t nformats; 383 + struct drm_plane *primary; 384 + int ret; 385 + 386 + switch (cirrus_bpp) { 387 + case 16: 388 + formats = cirrus_formats_16; 389 + nformats = ARRAY_SIZE(cirrus_formats_16); 390 + break; 391 + case 24: 392 + formats = cirrus_formats_24; 393 + nformats = ARRAY_SIZE(cirrus_formats_24); 394 + break; 395 + case 32: 396 + formats = cirrus_formats_32; 397 + nformats = ARRAY_SIZE(cirrus_formats_32); 398 + break; 399 + default: 400 + return NULL; 401 + } 402 + 403 + primary = kzalloc(sizeof(*primary), GFP_KERNEL); 404 + if (primary == NULL) { 405 + DRM_DEBUG_KMS("Failed to allocate primary plane\n"); 406 + return NULL; 407 + } 408 + 409 + ret = drm_universal_plane_init(dev, primary, 0, 410 + &drm_primary_helper_funcs, 411 + formats, nformats, 412 + NULL, 413 + DRM_PLANE_TYPE_PRIMARY, NULL); 414 + if (ret) { 415 + kfree(primary); 416 + primary = NULL; 417 + } 418 + 419 + return primary; 420 + } 421 + 363 422 static void cirrus_crtc_init(struct drm_device *dev) 364 423 { 365 424 struct cirrus_device *cdev = dev->dev_private; 366 425 struct cirrus_crtc *cirrus_crtc; 426 + struct drm_plane *primary; 367 427 368 428 cirrus_crtc = kzalloc(sizeof(struct cirrus_crtc) + 369 429 (CIRRUSFB_CONN_LIMIT * sizeof(struct drm_connector *)), ··· 432 372 if (cirrus_crtc == NULL) 433 373 return; 434 374 435 - drm_crtc_init(dev, &cirrus_crtc->base, &cirrus_crtc_funcs); 375 + primary = cirrus_primary_plane(dev); 376 + if (primary == NULL) { 377 + kfree(cirrus_crtc); 378 + return; 379 + } 380 + 381 + drm_crtc_init_with_planes(dev, &cirrus_crtc->base, 382 + primary, NULL, 383 + &cirrus_crtc_funcs, NULL); 436 384 437 385 drm_mode_crtc_set_gamma_size(&cirrus_crtc->base, CIRRUS_LUT_SIZE); 438 386 cdev->mode_info.crtc = cirrus_crtc;