Skip to content

Commit 7399c13

Browse files
committed
drm/vesadrm: Support DRM_FORMAT_C8
Add support for DRM_FORMAT_C8 to vesadrm. The new pixel-format description PIXEL_FORMAT_C8 describes the layout. Vesadrm's helpers vesadrm_fill_palette_lut() and vesadrm_load_palette_lut() set the hardware palette according to the CRTC's output format. The driver emulates XRGB8888 by converting the source buffer to RGB332 and using the resulting 256 colors as index into the hardware palette. The hardware palette converts back to RGB during scanout. This has no overhead compared to other format conversion, but allows common userspace, such as Wayland compositors, to operate on the display. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://lore.kernel.org/r/20250714151513.309475-10-tzimmermann@suse.de
1 parent 1adb35c commit 7399c13

2 files changed

Lines changed: 116 additions & 1 deletion

File tree

drivers/gpu/drm/sysfb/vesadrm.c

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ static const struct drm_format_info *vesadrm_get_format_si(struct drm_device *de
4646
{ PIXEL_FORMAT_RGB888, DRM_FORMAT_RGB888, },
4747
{ PIXEL_FORMAT_XRGB8888, DRM_FORMAT_XRGB8888, },
4848
{ PIXEL_FORMAT_XBGR8888, DRM_FORMAT_XBGR8888, },
49+
{ PIXEL_FORMAT_C8, DRM_FORMAT_C8, },
4950
};
5051

5152
return drm_sysfb_get_format_si(dev, formats, ARRAY_SIZE(formats), si);
@@ -192,6 +193,44 @@ static void vesadrm_load_gamma_lut(struct vesadrm_device *vesa,
192193
}
193194
}
194195

196+
static void vesadrm_fill_palette_lut(struct vesadrm_device *vesa,
197+
const struct drm_format_info *format)
198+
{
199+
struct drm_device *dev = &vesa->sysfb.dev;
200+
struct drm_crtc *crtc = &vesa->crtc;
201+
202+
switch (format->format) {
203+
case DRM_FORMAT_C8:
204+
drm_crtc_fill_palette_8(crtc, vesadrm_set_color_lut);
205+
break;
206+
case DRM_FORMAT_RGB332:
207+
drm_crtc_fill_palette_332(crtc, vesadrm_set_color_lut);
208+
break;
209+
default:
210+
drm_warn_once(dev, "Unsupported format %p4cc for palette\n",
211+
&format->format);
212+
break;
213+
}
214+
}
215+
216+
static void vesadrm_load_palette_lut(struct vesadrm_device *vesa,
217+
const struct drm_format_info *format,
218+
struct drm_color_lut *lut)
219+
{
220+
struct drm_device *dev = &vesa->sysfb.dev;
221+
struct drm_crtc *crtc = &vesa->crtc;
222+
223+
switch (format->format) {
224+
case DRM_FORMAT_C8:
225+
drm_crtc_load_palette_8(crtc, lut, vesadrm_set_color_lut);
226+
break;
227+
default:
228+
drm_warn_once(dev, "Unsupported format %p4cc for gamma correction\n",
229+
&format->format);
230+
break;
231+
}
232+
}
233+
195234
/*
196235
* Modesetting
197236
*/
@@ -200,8 +239,67 @@ static const u64 vesadrm_primary_plane_format_modifiers[] = {
200239
DRM_SYSFB_PLANE_FORMAT_MODIFIERS,
201240
};
202241

242+
static int vesadrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
243+
struct drm_atomic_state *new_state)
244+
{
245+
struct drm_sysfb_device *sysfb = to_drm_sysfb_device(plane->dev);
246+
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(new_state, plane);
247+
struct drm_framebuffer *new_fb = new_plane_state->fb;
248+
struct drm_crtc_state *new_crtc_state;
249+
struct drm_sysfb_crtc_state *new_sysfb_crtc_state;
250+
int ret;
251+
252+
ret = drm_sysfb_plane_helper_atomic_check(plane, new_state);
253+
if (ret)
254+
return ret;
255+
else if (!new_plane_state->visible)
256+
return 0;
257+
258+
/*
259+
* Fix up format conversion for specific cases
260+
*/
261+
262+
switch (sysfb->fb_format->format) {
263+
case DRM_FORMAT_C8:
264+
new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_plane_state->crtc);
265+
new_sysfb_crtc_state = to_drm_sysfb_crtc_state(new_crtc_state);
266+
267+
switch (new_fb->format->format) {
268+
case DRM_FORMAT_XRGB8888:
269+
/*
270+
* Reduce XRGB8888 to RGB332. Each resulting pixel is an index
271+
* into the C8 hardware palette, which stores RGB332 colors.
272+
*/
273+
if (new_sysfb_crtc_state->format->format != DRM_FORMAT_RGB332) {
274+
new_sysfb_crtc_state->format =
275+
drm_format_info(DRM_FORMAT_RGB332);
276+
new_crtc_state->color_mgmt_changed = true;
277+
}
278+
break;
279+
case DRM_FORMAT_C8:
280+
/*
281+
* Restore original output. Emulation of XRGB8888 set RBG332
282+
* output format and hardware palette. This needs to be undone
283+
* when we switch back to DRM_FORMAT_C8.
284+
*/
285+
if (new_sysfb_crtc_state->format->format == DRM_FORMAT_RGB332) {
286+
new_sysfb_crtc_state->format = sysfb->fb_format;
287+
new_crtc_state->color_mgmt_changed = true;
288+
}
289+
break;
290+
}
291+
break;
292+
};
293+
294+
return 0;
295+
}
296+
203297
static const struct drm_plane_helper_funcs vesadrm_primary_plane_helper_funcs = {
204-
DRM_SYSFB_PLANE_HELPER_FUNCS,
298+
DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
299+
.atomic_check = vesadrm_primary_plane_helper_atomic_check,
300+
.atomic_update = drm_sysfb_plane_helper_atomic_update,
301+
.atomic_disable = drm_sysfb_plane_helper_atomic_disable,
302+
.get_scanout_buffer = drm_sysfb_plane_helper_get_scanout_buffer,
205303
};
206304

207305
static const struct drm_plane_funcs vesadrm_primary_plane_funcs = {
@@ -224,6 +322,20 @@ static void vesadrm_crtc_helper_atomic_flush(struct drm_crtc *crtc,
224322
*/
225323
if (crtc_state->enable && crtc_state->color_mgmt_changed) {
226324
switch (sysfb->fb_format->format) {
325+
/*
326+
* Index formats
327+
*/
328+
case DRM_FORMAT_C8:
329+
if (sysfb_crtc_state->format->format == DRM_FORMAT_RGB332) {
330+
vesadrm_fill_palette_lut(vesa, sysfb_crtc_state->format);
331+
} else if (crtc->state->gamma_lut) {
332+
vesadrm_load_palette_lut(vesa,
333+
sysfb_crtc_state->format,
334+
crtc_state->gamma_lut->data);
335+
} else {
336+
vesadrm_fill_palette_lut(vesa, sysfb_crtc_state->format);
337+
}
338+
break;
227339
/*
228340
* Component formats
229341
*/

include/video/pixel_format.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ struct pixel_format {
2020
};
2121
};
2222

23+
#define PIXEL_FORMAT_C8 \
24+
{ 8, true, { .index = {0, 8}, } }
25+
2326
#define PIXEL_FORMAT_XRGB1555 \
2427
{ 16, false, { .alpha = {0, 0}, .red = {10, 5}, .green = {5, 5}, .blue = {0, 5} } }
2528

0 commit comments

Comments
 (0)