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
This commit is contained in:
Thomas Zimmermann 2025-07-14 17:13:04 +02:00
parent 31eea29d72
commit 061963cd9e
2 changed files with 20 additions and 11 deletions

View file

@ -132,7 +132,7 @@ int drm_sysfb_plane_helper_get_scanout_buffer(struct drm_plane *plane,
struct drm_sysfb_crtc_state { struct drm_sysfb_crtc_state {
struct drm_crtc_state base; struct drm_crtc_state base;
/* Primary-plane format; required for color mgmt. */ /* CRTC input color format; required for color mgmt. */
const struct drm_format_info *format; const struct drm_format_info *format;
}; };

View file

@ -210,7 +210,12 @@ int drm_sysfb_plane_helper_atomic_check(struct drm_plane *plane,
else if (!new_plane_state->visible) else if (!new_plane_state->visible)
return 0; return 0;
if (new_fb->format != sysfb->fb_format) { new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_plane_state->crtc);
new_sysfb_crtc_state = to_drm_sysfb_crtc_state(new_crtc_state);
new_sysfb_crtc_state->format = sysfb->fb_format;
if (new_fb->format != new_sysfb_crtc_state->format) {
void *buf; void *buf;
/* format conversion necessary; reserve buffer */ /* format conversion necessary; reserve buffer */
@ -220,11 +225,6 @@ int drm_sysfb_plane_helper_atomic_check(struct drm_plane *plane,
return -ENOMEM; return -ENOMEM;
} }
new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_plane_state->crtc);
new_sysfb_crtc_state = to_drm_sysfb_crtc_state(new_crtc_state);
new_sysfb_crtc_state->format = new_fb->format;
return 0; return 0;
} }
EXPORT_SYMBOL(drm_sysfb_plane_helper_atomic_check); EXPORT_SYMBOL(drm_sysfb_plane_helper_atomic_check);
@ -238,7 +238,10 @@ void drm_sysfb_plane_helper_atomic_update(struct drm_plane *plane, struct drm_at
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb; struct drm_framebuffer *fb = plane_state->fb;
unsigned int dst_pitch = sysfb->fb_pitch; unsigned int dst_pitch = sysfb->fb_pitch;
const struct drm_format_info *dst_format = sysfb->fb_format; struct drm_crtc_state *crtc_state = crtc_state =
drm_atomic_get_new_crtc_state(state, plane_state->crtc);
struct drm_sysfb_crtc_state *sysfb_crtc_state = to_drm_sysfb_crtc_state(crtc_state);
const struct drm_format_info *dst_format = sysfb_crtc_state->format;
struct drm_atomic_helper_damage_iter iter; struct drm_atomic_helper_damage_iter iter;
struct drm_rect damage; struct drm_rect damage;
int ret, idx; int ret, idx;
@ -278,7 +281,10 @@ void drm_sysfb_plane_helper_atomic_disable(struct drm_plane *plane,
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
void __iomem *dst_vmap = dst.vaddr_iomem; /* TODO: Use mapping abstraction */ void __iomem *dst_vmap = dst.vaddr_iomem; /* TODO: Use mapping abstraction */
unsigned int dst_pitch = sysfb->fb_pitch; unsigned int dst_pitch = sysfb->fb_pitch;
const struct drm_format_info *dst_format = sysfb->fb_format; struct drm_crtc_state *crtc_state = crtc_state =
drm_atomic_get_new_crtc_state(state, plane_state->crtc);
struct drm_sysfb_crtc_state *sysfb_crtc_state = to_drm_sysfb_crtc_state(crtc_state);
const struct drm_format_info *dst_format = sysfb_crtc_state->format;
struct drm_rect dst_clip; struct drm_rect dst_clip;
unsigned long lines, linepixels, i; unsigned long lines, linepixels, i;
int idx; int idx;
@ -370,16 +376,19 @@ EXPORT_SYMBOL(drm_sysfb_crtc_helper_atomic_check);
void drm_sysfb_crtc_reset(struct drm_crtc *crtc) void drm_sysfb_crtc_reset(struct drm_crtc *crtc)
{ {
struct drm_sysfb_device *sysfb = to_drm_sysfb_device(crtc->dev);
struct drm_sysfb_crtc_state *sysfb_crtc_state; struct drm_sysfb_crtc_state *sysfb_crtc_state;
if (crtc->state) if (crtc->state)
drm_sysfb_crtc_state_destroy(to_drm_sysfb_crtc_state(crtc->state)); drm_sysfb_crtc_state_destroy(to_drm_sysfb_crtc_state(crtc->state));
sysfb_crtc_state = kzalloc(sizeof(*sysfb_crtc_state), GFP_KERNEL); sysfb_crtc_state = kzalloc(sizeof(*sysfb_crtc_state), GFP_KERNEL);
if (sysfb_crtc_state) if (sysfb_crtc_state) {
sysfb_crtc_state->format = sysfb->fb_format;
__drm_atomic_helper_crtc_reset(crtc, &sysfb_crtc_state->base); __drm_atomic_helper_crtc_reset(crtc, &sysfb_crtc_state->base);
else } else {
__drm_atomic_helper_crtc_reset(crtc, NULL); __drm_atomic_helper_crtc_reset(crtc, NULL);
}
} }
EXPORT_SYMBOL(drm_sysfb_crtc_reset); EXPORT_SYMBOL(drm_sysfb_crtc_reset);