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

drm/sysfb: Blit to CRTC destination format

Use the color format stored in struct drm_sysfb_crtc_state for
color-format conversion instead of the scanout-buffer format
announced by firmware. Currently, both values are identical.

This will allow drivers to modify the CRTC's input format to a
certain extend. Specifically, vesadrm will be able to display RGB
framebuffers when the scanout buffer is of C8 format. With color-
format conversion to RGB332 and correct setup of the C8 palette,
displaying XRGB8888-based buffers under C8 can be achieved.

v2:
- refer to RGB332 as CRTC input format

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Link: https://lore.kernel.org/r/20250714151513.309475-5-tzimmermann@suse.de

+20 -11
+1 -1
drivers/gpu/drm/sysfb/drm_sysfb_helper.h
··· 132 132 struct drm_sysfb_crtc_state { 133 133 struct drm_crtc_state base; 134 134 135 - /* Primary-plane format; required for color mgmt. */ 135 + /* CRTC input color format; required for color mgmt. */ 136 136 const struct drm_format_info *format; 137 137 }; 138 138
+19 -10
drivers/gpu/drm/sysfb/drm_sysfb_modeset.c
··· 210 210 else if (!new_plane_state->visible) 211 211 return 0; 212 212 213 - if (new_fb->format != sysfb->fb_format) { 213 + new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_plane_state->crtc); 214 + 215 + new_sysfb_crtc_state = to_drm_sysfb_crtc_state(new_crtc_state); 216 + new_sysfb_crtc_state->format = sysfb->fb_format; 217 + 218 + if (new_fb->format != new_sysfb_crtc_state->format) { 214 219 void *buf; 215 220 216 221 /* format conversion necessary; reserve buffer */ ··· 224 219 if (!buf) 225 220 return -ENOMEM; 226 221 } 227 - 228 - new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_plane_state->crtc); 229 - 230 - new_sysfb_crtc_state = to_drm_sysfb_crtc_state(new_crtc_state); 231 - new_sysfb_crtc_state->format = new_fb->format; 232 222 233 223 return 0; 234 224 } ··· 238 238 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); 239 239 struct drm_framebuffer *fb = plane_state->fb; 240 240 unsigned int dst_pitch = sysfb->fb_pitch; 241 - const struct drm_format_info *dst_format = sysfb->fb_format; 241 + struct drm_crtc_state *crtc_state = crtc_state = 242 + drm_atomic_get_new_crtc_state(state, plane_state->crtc); 243 + struct drm_sysfb_crtc_state *sysfb_crtc_state = to_drm_sysfb_crtc_state(crtc_state); 244 + const struct drm_format_info *dst_format = sysfb_crtc_state->format; 242 245 struct drm_atomic_helper_damage_iter iter; 243 246 struct drm_rect damage; 244 247 int ret, idx; ··· 281 278 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); 282 279 void __iomem *dst_vmap = dst.vaddr_iomem; /* TODO: Use mapping abstraction */ 283 280 unsigned int dst_pitch = sysfb->fb_pitch; 284 - const struct drm_format_info *dst_format = sysfb->fb_format; 281 + struct drm_crtc_state *crtc_state = crtc_state = 282 + drm_atomic_get_new_crtc_state(state, plane_state->crtc); 283 + struct drm_sysfb_crtc_state *sysfb_crtc_state = to_drm_sysfb_crtc_state(crtc_state); 284 + const struct drm_format_info *dst_format = sysfb_crtc_state->format; 285 285 struct drm_rect dst_clip; 286 286 unsigned long lines, linepixels, i; 287 287 int idx; ··· 376 370 377 371 void drm_sysfb_crtc_reset(struct drm_crtc *crtc) 378 372 { 373 + struct drm_sysfb_device *sysfb = to_drm_sysfb_device(crtc->dev); 379 374 struct drm_sysfb_crtc_state *sysfb_crtc_state; 380 375 381 376 if (crtc->state) 382 377 drm_sysfb_crtc_state_destroy(to_drm_sysfb_crtc_state(crtc->state)); 383 378 384 379 sysfb_crtc_state = kzalloc(sizeof(*sysfb_crtc_state), GFP_KERNEL); 385 - if (sysfb_crtc_state) 380 + if (sysfb_crtc_state) { 381 + sysfb_crtc_state->format = sysfb->fb_format; 386 382 __drm_atomic_helper_crtc_reset(crtc, &sysfb_crtc_state->base); 387 - else 383 + } else { 388 384 __drm_atomic_helper_crtc_reset(crtc, NULL); 385 + } 389 386 } 390 387 EXPORT_SYMBOL(drm_sysfb_crtc_reset); 391 388