[PATCH v2 3/3] drm/format-helper: Move drm_fb_build_fourcc_list() to sysfb helpers

José Expósito jose.exposito89 at gmail.com
Fri Jun 13 14:53:55 UTC 2025


On Thu, Jun 12, 2025 at 03:52:24PM +0200, Thomas Zimmermann wrote:
> Only sysfb drivers use drm_fb_build_fourcc_list(). Move the function
> to sysfb helpers and rename it accordingly. Update drivers and tests.
> 
> v2:
> - select DRM_SYSFB_HELPER (kernel test robot)
> 
> Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de>
> Acked-by: Maxime Ripard <mripard at kernel.org>
> Acked-by: Javier Martinez Canillas <javierm at redhat.com>

Reviewed-by: José Expósito <jose.exposito89 at gmail.com

>
> ---
>  drivers/gpu/drm/Kconfig.debug                 |   1 +
>  drivers/gpu/drm/drm_format_helper.c           | 138 ------------------
>  drivers/gpu/drm/sysfb/drm_sysfb_helper.h      |   4 +
>  drivers/gpu/drm/sysfb/drm_sysfb_modeset.c     | 138 ++++++++++++++++++
>  drivers/gpu/drm/sysfb/efidrm.c                |   4 +-
>  drivers/gpu/drm/sysfb/ofdrm.c                 |   5 +-
>  drivers/gpu/drm/sysfb/simpledrm.c             |   5 +-
>  drivers/gpu/drm/sysfb/vesadrm.c               |   4 +-
>  .../gpu/drm/tests/drm_sysfb_modeset_test.c    |   9 +-
>  include/drm/drm_format_helper.h               |   4 -
>  10 files changed, 156 insertions(+), 156 deletions(-)
> 
> diff --git a/drivers/gpu/drm/Kconfig.debug b/drivers/gpu/drm/Kconfig.debug
> index fa6ee76f4d3c..05dc43c0b8c5 100644
> --- a/drivers/gpu/drm/Kconfig.debug
> +++ b/drivers/gpu/drm/Kconfig.debug
> @@ -70,6 +70,7 @@ config DRM_KUNIT_TEST
>  	select DRM_GEM_SHMEM_HELPER
>  	select DRM_KUNIT_TEST_HELPERS
>  	select DRM_LIB_RANDOM
> +	select DRM_SYSFB_HELPER
>  	select PRIME_NUMBERS
>  	default KUNIT_ALL_TESTS
>  	help
> diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
> index 73b5a80771cc..da79100895ff 100644
> --- a/drivers/gpu/drm/drm_format_helper.c
> +++ b/drivers/gpu/drm/drm_format_helper.c
> @@ -1338,141 +1338,3 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc
>  	}
>  }
>  EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono);
> -
> -static uint32_t drm_fb_nonalpha_fourcc(uint32_t fourcc)
> -{
> -	/* only handle formats with depth != 0 and alpha channel */
> -	switch (fourcc) {
> -	case DRM_FORMAT_ARGB1555:
> -		return DRM_FORMAT_XRGB1555;
> -	case DRM_FORMAT_ABGR1555:
> -		return DRM_FORMAT_XBGR1555;
> -	case DRM_FORMAT_RGBA5551:
> -		return DRM_FORMAT_RGBX5551;
> -	case DRM_FORMAT_BGRA5551:
> -		return DRM_FORMAT_BGRX5551;
> -	case DRM_FORMAT_ARGB8888:
> -		return DRM_FORMAT_XRGB8888;
> -	case DRM_FORMAT_ABGR8888:
> -		return DRM_FORMAT_XBGR8888;
> -	case DRM_FORMAT_RGBA8888:
> -		return DRM_FORMAT_RGBX8888;
> -	case DRM_FORMAT_BGRA8888:
> -		return DRM_FORMAT_BGRX8888;
> -	case DRM_FORMAT_ARGB2101010:
> -		return DRM_FORMAT_XRGB2101010;
> -	case DRM_FORMAT_ABGR2101010:
> -		return DRM_FORMAT_XBGR2101010;
> -	case DRM_FORMAT_RGBA1010102:
> -		return DRM_FORMAT_RGBX1010102;
> -	case DRM_FORMAT_BGRA1010102:
> -		return DRM_FORMAT_BGRX1010102;
> -	}
> -
> -	return fourcc;
> -}
> -
> -static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t fourcc)
> -{
> -	const uint32_t *fourccs_end = fourccs + nfourccs;
> -
> -	while (fourccs < fourccs_end) {
> -		if (*fourccs == fourcc)
> -			return true;
> -		++fourccs;
> -	}
> -	return false;
> -}
> -
> -/**
> - * drm_fb_build_fourcc_list - Filters a list of supported color formats against
> - *                            the device's native formats
> - * @dev: DRM device
> - * @native_fourccs: 4CC codes of natively supported color formats
> - * @native_nfourccs: The number of entries in @native_fourccs
> - * @fourccs_out: Returns 4CC codes of supported color formats
> - * @nfourccs_out: The number of available entries in @fourccs_out
> - *
> - * This function create a list of supported color format from natively
> - * supported formats and additional emulated formats.
> - * At a minimum, most userspace programs expect at least support for
> - * XRGB8888 on the primary plane. Devices that have to emulate the
> - * format, and possibly others, can use drm_fb_build_fourcc_list() to
> - * create a list of supported color formats. The returned list can
> - * be handed over to drm_universal_plane_init() et al. Native formats
> - * will go before emulated formats. Native formats with alpha channel
> - * will be replaced by such without, as primary planes usually don't
> - * support alpha. Other heuristics might be applied
> - * to optimize the order. Formats near the beginning of the list are
> - * usually preferred over formats near the end of the list.
> - *
> - * Returns:
> - * The number of color-formats 4CC codes returned in @fourccs_out.
> - */
> -size_t drm_fb_build_fourcc_list(struct drm_device *dev,
> -				const u32 *native_fourccs, size_t native_nfourccs,
> -				u32 *fourccs_out, size_t nfourccs_out)
> -{
> -	/*
> -	 * XRGB8888 is the default fallback format for most of userspace
> -	 * and it's currently the only format that should be emulated for
> -	 * the primary plane. Only if there's ever another default fallback,
> -	 * it should be added here.
> -	 */
> -	static const uint32_t extra_fourccs[] = {
> -		DRM_FORMAT_XRGB8888,
> -	};
> -	static const size_t extra_nfourccs = ARRAY_SIZE(extra_fourccs);
> -
> -	u32 *fourccs = fourccs_out;
> -	const u32 *fourccs_end = fourccs_out + nfourccs_out;
> -	size_t i;
> -
> -	/*
> -	 * The device's native formats go first.
> -	 */
> -
> -	for (i = 0; i < native_nfourccs; ++i) {
> -		/*
> -		 * Several DTs, boot loaders and firmware report native
> -		 * alpha formats that are non-alpha formats instead. So
> -		 * replace alpha formats by non-alpha formats.
> -		 */
> -		u32 fourcc = drm_fb_nonalpha_fourcc(native_fourccs[i]);
> -
> -		if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) {
> -			continue; /* skip duplicate entries */
> -		} else if (fourccs == fourccs_end) {
> -			drm_warn(dev, "Ignoring native format %p4cc\n", &fourcc);
> -			continue; /* end of available output buffer */
> -		}
> -
> -		drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc);
> -
> -		*fourccs = fourcc;
> -		++fourccs;
> -	}
> -
> -	/*
> -	 * The extra formats, emulated by the driver, go second.
> -	 */
> -
> -	for (i = 0; (i < extra_nfourccs) && (fourccs < fourccs_end); ++i) {
> -		u32 fourcc = extra_fourccs[i];
> -
> -		if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) {
> -			continue; /* skip duplicate and native entries */
> -		} else if (fourccs == fourccs_end) {
> -			drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc);
> -			continue; /* end of available output buffer */
> -		}
> -
> -		drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc);
> -
> -		*fourccs = fourcc;
> -		++fourccs;
> -	}
> -
> -	return fourccs - fourccs_out;
> -}
> -EXPORT_SYMBOL(drm_fb_build_fourcc_list);
> diff --git a/drivers/gpu/drm/sysfb/drm_sysfb_helper.h b/drivers/gpu/drm/sysfb/drm_sysfb_helper.h
> index cb08a88242cc..1424b63dde99 100644
> --- a/drivers/gpu/drm/sysfb/drm_sysfb_helper.h
> +++ b/drivers/gpu/drm/sysfb/drm_sysfb_helper.h
> @@ -93,6 +93,10 @@ static inline struct drm_sysfb_device *to_drm_sysfb_device(struct drm_device *de
>   * Plane
>   */
>  
> +size_t drm_sysfb_build_fourcc_list(struct drm_device *dev,
> +				   const u32 *native_fourccs, size_t native_nfourccs,
> +				   u32 *fourccs_out, size_t nfourccs_out);
> +
>  int drm_sysfb_plane_helper_atomic_check(struct drm_plane *plane,
>  					struct drm_atomic_state *new_state);
>  void drm_sysfb_plane_helper_atomic_update(struct drm_plane *plane,
> diff --git a/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c b/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c
> index ffaa2522ab96..1bcdb5ee8f09 100644
> --- a/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c
> +++ b/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c
> @@ -47,6 +47,144 @@ EXPORT_SYMBOL(drm_sysfb_mode);
>   * Plane
>   */
>  
> +static u32 to_nonalpha_fourcc(u32 fourcc)
> +{
> +	/* only handle formats with depth != 0 and alpha channel */
> +	switch (fourcc) {
> +	case DRM_FORMAT_ARGB1555:
> +		return DRM_FORMAT_XRGB1555;
> +	case DRM_FORMAT_ABGR1555:
> +		return DRM_FORMAT_XBGR1555;
> +	case DRM_FORMAT_RGBA5551:
> +		return DRM_FORMAT_RGBX5551;
> +	case DRM_FORMAT_BGRA5551:
> +		return DRM_FORMAT_BGRX5551;
> +	case DRM_FORMAT_ARGB8888:
> +		return DRM_FORMAT_XRGB8888;
> +	case DRM_FORMAT_ABGR8888:
> +		return DRM_FORMAT_XBGR8888;
> +	case DRM_FORMAT_RGBA8888:
> +		return DRM_FORMAT_RGBX8888;
> +	case DRM_FORMAT_BGRA8888:
> +		return DRM_FORMAT_BGRX8888;
> +	case DRM_FORMAT_ARGB2101010:
> +		return DRM_FORMAT_XRGB2101010;
> +	case DRM_FORMAT_ABGR2101010:
> +		return DRM_FORMAT_XBGR2101010;
> +	case DRM_FORMAT_RGBA1010102:
> +		return DRM_FORMAT_RGBX1010102;
> +	case DRM_FORMAT_BGRA1010102:
> +		return DRM_FORMAT_BGRX1010102;
> +	}
> +
> +	return fourcc;
> +}
> +
> +static bool is_listed_fourcc(const u32 *fourccs, size_t nfourccs, u32 fourcc)
> +{
> +	const u32 *fourccs_end = fourccs + nfourccs;
> +
> +	while (fourccs < fourccs_end) {
> +		if (*fourccs == fourcc)
> +			return true;
> +		++fourccs;
> +	}
> +	return false;
> +}
> +
> +/**
> + * drm_sysfb_build_fourcc_list - Filters a list of supported color formats against
> + *                               the device's native formats
> + * @dev: DRM device
> + * @native_fourccs: 4CC codes of natively supported color formats
> + * @native_nfourccs: The number of entries in @native_fourccs
> + * @fourccs_out: Returns 4CC codes of supported color formats
> + * @nfourccs_out: The number of available entries in @fourccs_out
> + *
> + * This function create a list of supported color format from natively
> + * supported formats and additional emulated formats.
> + * At a minimum, most userspace programs expect at least support for
> + * XRGB8888 on the primary plane. Sysfb devices that have to emulate
> + * the format should use drm_sysfb_build_fourcc_list() to create a list
> + * of supported color formats. The returned list can be handed over to
> + * drm_universal_plane_init() et al. Native formats will go before
> + * emulated formats. Native formats with alpha channel will be replaced
> + * by equal formats without alpha channel, as primary planes usually
> + * don't support alpha. Other heuristics might be applied to optimize
> + * the sorting order. Formats near the beginning of the list are usually
> + * preferred over formats near the end of the list.
> + *
> + * Returns:
> + * The number of color-formats 4CC codes returned in @fourccs_out.
> + */
> +size_t drm_sysfb_build_fourcc_list(struct drm_device *dev,
> +				   const u32 *native_fourccs, size_t native_nfourccs,
> +				   u32 *fourccs_out, size_t nfourccs_out)
> +{
> +	/*
> +	 * XRGB8888 is the default fallback format for most of userspace
> +	 * and it's currently the only format that should be emulated for
> +	 * the primary plane. Only if there's ever another default fallback,
> +	 * it should be added here.
> +	 */
> +	static const u32 extra_fourccs[] = {
> +		DRM_FORMAT_XRGB8888,
> +	};
> +	static const size_t extra_nfourccs = ARRAY_SIZE(extra_fourccs);
> +
> +	u32 *fourccs = fourccs_out;
> +	const u32 *fourccs_end = fourccs_out + nfourccs_out;
> +	size_t i;
> +
> +	/*
> +	 * The device's native formats go first.
> +	 */
> +
> +	for (i = 0; i < native_nfourccs; ++i) {
> +		/*
> +		 * Several DTs, boot loaders and firmware report native
> +		 * alpha formats that are non-alpha formats instead. So
> +		 * replace alpha formats by non-alpha formats.
> +		 */
> +		u32 fourcc = to_nonalpha_fourcc(native_fourccs[i]);
> +
> +		if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) {
> +			continue; /* skip duplicate entries */
> +		} else if (fourccs == fourccs_end) {
> +			drm_warn(dev, "Ignoring native format %p4cc\n", &fourcc);
> +			continue; /* end of available output buffer */
> +		}
> +
> +		drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc);
> +
> +		*fourccs = fourcc;
> +		++fourccs;
> +	}
> +
> +	/*
> +	 * The extra formats, emulated by the driver, go second.
> +	 */
> +
> +	for (i = 0; (i < extra_nfourccs) && (fourccs < fourccs_end); ++i) {
> +		u32 fourcc = extra_fourccs[i];
> +
> +		if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) {
> +			continue; /* skip duplicate and native entries */
> +		} else if (fourccs == fourccs_end) {
> +			drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc);
> +			continue; /* end of available output buffer */
> +		}
> +
> +		drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc);
> +
> +		*fourccs = fourcc;
> +		++fourccs;
> +	}
> +
> +	return fourccs - fourccs_out;
> +}
> +EXPORT_SYMBOL(drm_sysfb_build_fourcc_list);
> +
>  int drm_sysfb_plane_helper_atomic_check(struct drm_plane *plane,
>  					struct drm_atomic_state *new_state)
>  {
> diff --git a/drivers/gpu/drm/sysfb/efidrm.c b/drivers/gpu/drm/sysfb/efidrm.c
> index 46912924636a..9562f9dc7835 100644
> --- a/drivers/gpu/drm/sysfb/efidrm.c
> +++ b/drivers/gpu/drm/sysfb/efidrm.c
> @@ -271,8 +271,8 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
>  
>  	/* Primary plane */
>  
> -	nformats = drm_fb_build_fourcc_list(dev, &format->format, 1,
> -					    efi->formats, ARRAY_SIZE(efi->formats));
> +	nformats = drm_sysfb_build_fourcc_list(dev, &format->format, 1,
> +					       efi->formats, ARRAY_SIZE(efi->formats));
>  
>  	primary_plane = &efi->primary_plane;
>  	ret = drm_universal_plane_init(dev, primary_plane, 0, &efidrm_primary_plane_funcs,
> diff --git a/drivers/gpu/drm/sysfb/ofdrm.c b/drivers/gpu/drm/sysfb/ofdrm.c
> index c9415f0cb3ed..8d8ab39c5f36 100644
> --- a/drivers/gpu/drm/sysfb/ofdrm.c
> +++ b/drivers/gpu/drm/sysfb/ofdrm.c
> @@ -15,7 +15,6 @@
>  #include <drm/drm_drv.h>
>  #include <drm/drm_edid.h>
>  #include <drm/drm_fbdev_shmem.h>
> -#include <drm/drm_format_helper.h>
>  #include <drm/drm_framebuffer.h>
>  #include <drm/drm_gem_atomic_helper.h>
>  #include <drm/drm_gem_framebuffer_helper.h>
> @@ -1015,8 +1014,8 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv,
>  
>  	/* Primary plane */
>  
> -	nformats = drm_fb_build_fourcc_list(dev, &format->format, 1,
> -					    odev->formats, ARRAY_SIZE(odev->formats));
> +	nformats = drm_sysfb_build_fourcc_list(dev, &format->format, 1,
> +					       odev->formats, ARRAY_SIZE(odev->formats));
>  
>  	primary_plane = &odev->primary_plane;
>  	ret = drm_universal_plane_init(dev, primary_plane, 0, &ofdrm_primary_plane_funcs,
> diff --git a/drivers/gpu/drm/sysfb/simpledrm.c b/drivers/gpu/drm/sysfb/simpledrm.c
> index a1c3119330de..8530a3ef8a7a 100644
> --- a/drivers/gpu/drm/sysfb/simpledrm.c
> +++ b/drivers/gpu/drm/sysfb/simpledrm.c
> @@ -18,7 +18,6 @@
>  #include <drm/drm_device.h>
>  #include <drm/drm_drv.h>
>  #include <drm/drm_fbdev_shmem.h>
> -#include <drm/drm_format_helper.h>
>  #include <drm/drm_framebuffer.h>
>  #include <drm/drm_gem_atomic_helper.h>
>  #include <drm/drm_gem_framebuffer_helper.h>
> @@ -765,8 +764,8 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv,
>  
>  	/* Primary plane */
>  
> -	nformats = drm_fb_build_fourcc_list(dev, &format->format, 1,
> -					    sdev->formats, ARRAY_SIZE(sdev->formats));
> +	nformats = drm_sysfb_build_fourcc_list(dev, &format->format, 1,
> +					       sdev->formats, ARRAY_SIZE(sdev->formats));
>  
>  	primary_plane = &sdev->primary_plane;
>  	ret = drm_universal_plane_init(dev, primary_plane, 0, &simpledrm_primary_plane_funcs,
> diff --git a/drivers/gpu/drm/sysfb/vesadrm.c b/drivers/gpu/drm/sysfb/vesadrm.c
> index 7945544ba73e..86e0b88dd51b 100644
> --- a/drivers/gpu/drm/sysfb/vesadrm.c
> +++ b/drivers/gpu/drm/sysfb/vesadrm.c
> @@ -402,8 +402,8 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv,
>  
>  	/* Primary plane */
>  
> -	nformats = drm_fb_build_fourcc_list(dev, &format->format, 1,
> -					    vesa->formats, ARRAY_SIZE(vesa->formats));
> +	nformats = drm_sysfb_build_fourcc_list(dev, &format->format, 1,
> +					       vesa->formats, ARRAY_SIZE(vesa->formats));
>  
>  	primary_plane = &vesa->primary_plane;
>  	ret = drm_universal_plane_init(dev, primary_plane, 0, &vesadrm_primary_plane_funcs,
> diff --git a/drivers/gpu/drm/tests/drm_sysfb_modeset_test.c b/drivers/gpu/drm/tests/drm_sysfb_modeset_test.c
> index 88a4bf28c745..33acd3f02dc6 100644
> --- a/drivers/gpu/drm/tests/drm_sysfb_modeset_test.c
> +++ b/drivers/gpu/drm/tests/drm_sysfb_modeset_test.c
> @@ -2,10 +2,11 @@
>  
>  #include <kunit/test.h>
>  
> -#include <drm/drm_format_helper.h>
>  #include <drm/drm_fourcc.h>
>  #include <drm/drm_kunit_helpers.h>
>  
> +#include "../sysfb/drm_sysfb_helper.h"
> +
>  #define TEST_BUF_SIZE 50
>  
>  struct fb_build_fourcc_list_case {
> @@ -141,9 +142,9 @@ static void drm_test_fb_build_fourcc_list(struct kunit *test)
>  	drm = __drm_kunit_helper_alloc_drm_device(test, dev, sizeof(*drm), 0, DRIVER_MODESET);
>  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm);
>  
> -	nfourccs_out = drm_fb_build_fourcc_list(drm, params->native_fourccs,
> -						params->native_fourccs_size,
> -						fourccs_out, TEST_BUF_SIZE);
> +	nfourccs_out = drm_sysfb_build_fourcc_list(drm, params->native_fourccs,
> +						   params->native_fourccs_size,
> +						   fourccs_out, TEST_BUF_SIZE);
>  
>  	KUNIT_EXPECT_EQ(test, nfourccs_out, params->expected_fourccs_size);
>  	KUNIT_EXPECT_MEMEQ(test, fourccs_out, params->expected, TEST_BUF_SIZE);
> diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h
> index 49a2e09155d1..0d3ee2a1313f 100644
> --- a/include/drm/drm_format_helper.h
> +++ b/include/drm/drm_format_helper.h
> @@ -134,8 +134,4 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc
>  			     const struct iosys_map *src, const struct drm_framebuffer *fb,
>  			     const struct drm_rect *clip, struct drm_format_conv_state *state);
>  
> -size_t drm_fb_build_fourcc_list(struct drm_device *dev,
> -				const u32 *native_fourccs, size_t native_nfourccs,
> -				u32 *fourccs_out, size_t nfourccs_out);
> -
>  #endif /* __LINUX_DRM_FORMAT_HELPER_H */
> -- 
> 2.49.0
> 


More information about the dri-devel mailing list