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

drm/pl111: Fix FB depth on IMPD-1 framebuffer

The last argument to the function drm_fbdev_dma_setup() was
changed from desired BPP to desired depth.

In our case the desired depth was 15 but BPP was 16, so we
specified 16 as BPP and we relied on the FB emulation core to
select a format with a suitable depth for the limited bandwidth
and end up with e.g. XRGB1555 like in the past:

[drm] Initialized pl111 1.0.0 20170317 for c1000000.display on minor 0
drm-clcd-pl111 c1000000.display: [drm] requested bpp 16, scaled depth down to 15
drm-clcd-pl111 c1000000.display: enable IM-PD1 CLCD connectors
Console: switching to colour frame buffer device 80x30
drm-clcd-pl111 c1000000.display: [drm] fb0: pl111drmfb frame buffer device

However the current code will fail at that:

[drm] Initialized pl111 1.0.0 20170317 for c1000000.display on minor 0
drm-clcd-pl111 c1000000.display: [drm] bpp/depth value of 16/16 not supported
drm-clcd-pl111 c1000000.display: [drm] No compatible format found
drm-clcd-pl111 c1000000.display: [drm] *ERROR* fbdev: Failed to setup generic emulation (ret=-12)

Fix this by passing the desired depth of 15 for the IM/PD-1 display
instead of 16 to drm_fbdev_dma_setup().

The desired depth is however in turn used for bandwidth limiting
calculations and that was done with a simple / integer division,
whereas we now have to modify that to use DIV_ROUND_UP() so that
we get DIV_ROUND_UP(15, 2) = 2 not 15/2 = 1.

After this the display works again on the Integrator/AP IM/PD-1.

Cc: Emma Anholt <emma@anholt.net>
Cc: stable@vger.kernel.org
Suggested-by: Thomas Zimmermann <tzimmermann@suse.de>
Fixes: 37c90d589dc0 ("drm/fb-helper: Fix single-probe color-format selection")
Link: https://lore.kernel.org/dri-devel/20230102112927.26565-1-tzimmermann@suse.de/
Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20230515092943.1401558-1-linus.walleij@linaro.org

+12 -12
+1 -1
drivers/gpu/drm/pl111/pl111_display.c
··· 53 53 { 54 54 struct drm_device *drm = pipe->crtc.dev; 55 55 struct pl111_drm_dev_private *priv = drm->dev_private; 56 - u32 cpp = priv->variant->fb_bpp / 8; 56 + u32 cpp = DIV_ROUND_UP(priv->variant->fb_depth, 8); 57 57 u64 bw; 58 58 59 59 /*
+2 -2
drivers/gpu/drm/pl111/pl111_drm.h
··· 114 114 * extensions to the control register 115 115 * @formats: array of supported pixel formats on this variant 116 116 * @nformats: the length of the array of supported pixel formats 117 - * @fb_bpp: desired bits per pixel on the default framebuffer 117 + * @fb_depth: desired depth per pixel on the default framebuffer 118 118 */ 119 119 struct pl111_variant_data { 120 120 const char *name; ··· 126 126 bool st_bitmux_control; 127 127 const u32 *formats; 128 128 unsigned int nformats; 129 - unsigned int fb_bpp; 129 + unsigned int fb_depth; 130 130 }; 131 131 132 132 struct pl111_drm_dev_private {
+4 -4
drivers/gpu/drm/pl111/pl111_drv.c
··· 308 308 if (ret < 0) 309 309 goto dev_put; 310 310 311 - drm_fbdev_dma_setup(drm, priv->variant->fb_bpp); 311 + drm_fbdev_dma_setup(drm, priv->variant->fb_depth); 312 312 313 313 return 0; 314 314 ··· 351 351 .is_pl110 = true, 352 352 .formats = pl110_pixel_formats, 353 353 .nformats = ARRAY_SIZE(pl110_pixel_formats), 354 - .fb_bpp = 16, 354 + .fb_depth = 16, 355 355 }; 356 356 357 357 /* RealView, Versatile Express etc use this modern variant */ ··· 376 376 .name = "PL111", 377 377 .formats = pl111_pixel_formats, 378 378 .nformats = ARRAY_SIZE(pl111_pixel_formats), 379 - .fb_bpp = 32, 379 + .fb_depth = 32, 380 380 }; 381 381 382 382 static const u32 pl110_nomadik_pixel_formats[] = { ··· 405 405 .is_lcdc = true, 406 406 .st_bitmux_control = true, 407 407 .broken_vblank = true, 408 - .fb_bpp = 16, 408 + .fb_depth = 16, 409 409 }; 410 410 411 411 static const struct amba_id pl111_id_table[] = {
+5 -5
drivers/gpu/drm/pl111/pl111_versatile.c
··· 316 316 .broken_vblank = true, 317 317 .formats = pl110_integrator_pixel_formats, 318 318 .nformats = ARRAY_SIZE(pl110_integrator_pixel_formats), 319 - .fb_bpp = 16, 319 + .fb_depth = 16, 320 320 }; 321 321 322 322 /* ··· 330 330 .broken_vblank = true, 331 331 .formats = pl110_integrator_pixel_formats, 332 332 .nformats = ARRAY_SIZE(pl110_integrator_pixel_formats), 333 - .fb_bpp = 16, 333 + .fb_depth = 15, 334 334 }; 335 335 336 336 /* ··· 343 343 .external_bgr = true, 344 344 .formats = pl110_versatile_pixel_formats, 345 345 .nformats = ARRAY_SIZE(pl110_versatile_pixel_formats), 346 - .fb_bpp = 16, 346 + .fb_depth = 16, 347 347 }; 348 348 349 349 /* ··· 355 355 .name = "PL111 RealView", 356 356 .formats = pl111_realview_pixel_formats, 357 357 .nformats = ARRAY_SIZE(pl111_realview_pixel_formats), 358 - .fb_bpp = 16, 358 + .fb_depth = 16, 359 359 }; 360 360 361 361 /* ··· 367 367 .name = "PL111 Versatile Express", 368 368 .formats = pl111_realview_pixel_formats, 369 369 .nformats = ARRAY_SIZE(pl111_realview_pixel_formats), 370 - .fb_bpp = 16, 370 + .fb_depth = 16, 371 371 .broken_clockdivider = true, 372 372 }; 373 373