@@ -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+
203297static 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
207305static 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 */
0 commit comments