[PATCH] drm/format-helper: Split off byte swapping from drm_fb_xrgb8888_to_rgb565()

Jocelyn Falempe jfalempe at redhat.com
Fri Jun 27 07:21:09 UTC 2025


On 25/06/2025 13:48, Thomas Zimmermann wrote:
> Move big-endian support from drm_fb_xrgb8888_to_rgb565() into the new
> helper drm_xrgb8888_to_rgb565be(). The functionality is required for
> displays with big-endian byte order. Update all callers.
> 
> With the change applied, drm_fb_xrgb8888_to_rgb565() has the same
> signature as the other conversion functions, which is required for
> further updates to drm_fb_blit(). Also makes the format-conversion
> helper available to panic handlers, if necessary.

Thanks, it looks good to me.

Reviewed-by: Jocelyn Falempe <jfalempe at redhat.com>

> 
> Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de>
> ---
>   drivers/gpu/drm/drm_format_helper.c           | 66 ++++++++++++-------
>   drivers/gpu/drm/drm_format_internal.h         |  6 ++
>   drivers/gpu/drm/drm_mipi_dbi.c                |  8 ++-
>   drivers/gpu/drm/gud/gud_pipe.c                |  9 ++-
>   .../gpu/drm/tests/drm_format_helper_test.c    |  8 +--
>   include/drm/drm_format_helper.h               |  6 +-
>   6 files changed, 71 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
> index 99d9f7bbc261..8f3daf38ca63 100644
> --- a/drivers/gpu/drm/drm_format_helper.c
> +++ b/drivers/gpu/drm/drm_format_helper.c
> @@ -559,18 +559,6 @@ static void drm_fb_xrgb8888_to_rgb565_line(void *dbuf, const void *sbuf, unsigne
>   	drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb565);
>   }
>   
> -static __always_inline u32 drm_xrgb8888_to_rgb565_swab(u32 pix)
> -{
> -	return swab16(drm_pixel_xrgb8888_to_rgb565(pix));
> -}
> -
> -/* TODO: implement this helper as conversion to RGB565|BIG_ENDIAN */
> -static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf,
> -						unsigned int pixels)
> -{
> -	drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_xrgb8888_to_rgb565_swab);
> -}
> -
>   /**
>    * drm_fb_xrgb8888_to_rgb565 - Convert XRGB8888 to RGB565 clip buffer
>    * @dst: Array of RGB565 destination buffers
> @@ -580,7 +568,6 @@ static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf,
>    * @fb: DRM framebuffer
>    * @clip: Clip rectangle area to copy
>    * @state: Transform and conversion state
> - * @swab: Swap bytes
>    *
>    * This function copies parts of a framebuffer to display memory and converts the
>    * color format during the process. Destination and framebuffer formats must match. The
> @@ -595,23 +582,56 @@ static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf,
>    */
>   void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch,
>   			       const struct iosys_map *src, const struct drm_framebuffer *fb,
> -			       const struct drm_rect *clip, struct drm_format_conv_state *state,
> -			       bool swab)
> +			       const struct drm_rect *clip, struct drm_format_conv_state *state)
>   {
>   	static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
>   		2,
>   	};
>   
> -	void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels);
> +	drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
> +		    drm_fb_xrgb8888_to_rgb565_line);
> +}
> +EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565);
> +
> +static void drm_fb_xrgb8888_to_rgb565be_line(void *dbuf, const void *sbuf,
> +					     unsigned int pixels)
> +{
> +	drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb565be);
> +}
>   
> -	if (swab)
> -		xfrm_line = drm_fb_xrgb8888_to_rgb565_swab_line;
> -	else
> -		xfrm_line = drm_fb_xrgb8888_to_rgb565_line;
> +/**
> + * drm_fb_xrgb8888_to_rgb565be - Convert XRGB8888 to RGB565|DRM_FORMAT_BIG_ENDIAN clip buffer
> + * @dst: Array of RGB565BE destination buffers
> + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
> + *             within @dst; can be NULL if scanlines are stored next to each other.
> + * @src: Array of XRGB8888 source buffer
> + * @fb: DRM framebuffer
> + * @clip: Clip rectangle area to copy
> + * @state: Transform and conversion state
> + *
> + * This function copies parts of a framebuffer to display memory and converts the
> + * color format during the process. Destination and framebuffer formats must match. The
> + * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
> + * least as many entries as there are planes in @fb's format. Each entry stores the
> + * value for the format's respective color plane at the same index.
> + *
> + * This function does not apply clipping on @dst (i.e. the destination is at the
> + * top-left corner).
> + *
> + * Drivers can use this function for RGB565BE devices that don't support XRGB8888 natively.
> + */
> +void drm_fb_xrgb8888_to_rgb565be(struct iosys_map *dst, const unsigned int *dst_pitch,
> +				 const struct iosys_map *src, const struct drm_framebuffer *fb,
> +				 const struct drm_rect *clip, struct drm_format_conv_state *state)
> +{
> +	static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
> +		2,
> +	};
>   
> -	drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, xfrm_line);
> +	drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
> +		    drm_fb_xrgb8888_to_rgb565be_line);
>   }
> -EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565);
> +EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565be);
>   
>   static void drm_fb_xrgb8888_to_xrgb1555_line(void *dbuf, const void *sbuf, unsigned int pixels)
>   {
> @@ -1188,7 +1208,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d
>   		return 0;
>   	} else if (fb_format == DRM_FORMAT_XRGB8888) {
>   		if (dst_format == DRM_FORMAT_RGB565) {
> -			drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, state, false);
> +			drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, state);
>   			return 0;
>   		} else if (dst_format == DRM_FORMAT_XRGB1555) {
>   			drm_fb_xrgb8888_to_xrgb1555(dst, dst_pitch, src, fb, clip, state);
> diff --git a/drivers/gpu/drm/drm_format_internal.h b/drivers/gpu/drm/drm_format_internal.h
> index 9428d5cfebc5..ce29dd05bcc5 100644
> --- a/drivers/gpu/drm/drm_format_internal.h
> +++ b/drivers/gpu/drm/drm_format_internal.h
> @@ -5,6 +5,7 @@
>   
>   #include <linux/bits.h>
>   #include <linux/types.h>
> +#include <linux/swab.h>
>   
>   /*
>    * Each pixel-format conversion helper takes a raw pixel in a
> @@ -59,6 +60,11 @@ static inline u32 drm_pixel_xrgb8888_to_rgb565(u32 pix)
>   	       ((pix & 0x000000f8) >> 3);
>   }
>   
> +static inline u32 drm_pixel_xrgb8888_to_rgb565be(u32 pix)
> +{
> +	return swab16(drm_pixel_xrgb8888_to_rgb565(pix));
> +}
> +
>   static inline u32 drm_pixel_xrgb8888_to_rgbx5551(u32 pix)
>   {
>   	return ((pix & 0x00f80000) >> 8) |
> diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
> index ba4be6be5d28..e33c78fc8fbd 100644
> --- a/drivers/gpu/drm/drm_mipi_dbi.c
> +++ b/drivers/gpu/drm/drm_mipi_dbi.c
> @@ -230,7 +230,13 @@ int mipi_dbi_buf_copy(void *dst, struct iosys_map *src, struct drm_framebuffer *
>   	case DRM_FORMAT_XRGB8888:
>   		switch (dbidev->pixel_format) {
>   		case DRM_FORMAT_RGB565:
> -			drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, src, fb, clip, fmtcnv_state, swap);
> +			if (swap) {
> +				drm_fb_xrgb8888_to_rgb565be(&dst_map, NULL, src, fb, clip,
> +							    fmtcnv_state);
> +			} else {
> +				drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, src, fb, clip,
> +							  fmtcnv_state);
> +			}
>   			break;
>   		case DRM_FORMAT_RGB888:
>   			drm_fb_xrgb8888_to_rgb888(&dst_map, NULL, src, fb, clip, fmtcnv_state);
> diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c
> index adadd526641d..8d548d08f127 100644
> --- a/drivers/gpu/drm/gud/gud_pipe.c
> +++ b/drivers/gpu/drm/gud/gud_pipe.c
> @@ -188,8 +188,13 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb,
>   		} else if (format->format == DRM_FORMAT_RGB332) {
>   			drm_fb_xrgb8888_to_rgb332(&dst, NULL, src, fb, rect, fmtcnv_state);
>   		} else if (format->format == DRM_FORMAT_RGB565) {
> -			drm_fb_xrgb8888_to_rgb565(&dst, NULL, src, fb, rect, fmtcnv_state,
> -						  gud_is_big_endian());
> +			if (gud_is_big_endian()) {
> +				drm_fb_xrgb8888_to_rgb565be(&dst, NULL, src, fb, rect,
> +							    fmtcnv_state);
> +			} else {
> +				drm_fb_xrgb8888_to_rgb565(&dst, NULL, src, fb, rect,
> +							  fmtcnv_state);
> +			}
>   		} else if (format->format == DRM_FORMAT_RGB888) {
>   			drm_fb_xrgb8888_to_rgb888(&dst, NULL, src, fb, rect, fmtcnv_state);
>   		} else {
> diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c
> index ad06762db671..7299fa8971ce 100644
> --- a/drivers/gpu/drm/tests/drm_format_helper_test.c
> +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c
> @@ -735,13 +735,13 @@ static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test)
>   		NULL : &result->dst_pitch;
>   
>   	drm_fb_xrgb8888_to_rgb565(&dst, dst_pitch, &src, &fb, &params->clip,
> -				  &fmtcnv_state, false);
> +				  &fmtcnv_state);
>   	buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
>   	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
>   
>   	buf = dst.vaddr; /* restore original value of buf */
> -	drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, &params->clip,
> -				  &fmtcnv_state, true);
> +	drm_fb_xrgb8888_to_rgb565be(&dst, &result->dst_pitch, &src, &fb, &params->clip,
> +				    &fmtcnv_state);
>   	buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
>   	KUNIT_EXPECT_MEMEQ(test, buf, result->expected_swab, dst_size);
>   
> @@ -749,7 +749,7 @@ static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test)
>   	memset(buf, 0, dst_size);
>   
>   	drm_fb_xrgb8888_to_rgb565(&dst, dst_pitch, &src, &fb, &params->clip,
> -				  &fmtcnv_state, false);
> +				  &fmtcnv_state);
>   	buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
>   	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
>   }
> diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h
> index 0d3ee2a1313f..562bc383ece4 100644
> --- a/include/drm/drm_format_helper.h
> +++ b/include/drm/drm_format_helper.h
> @@ -82,8 +82,10 @@ void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pi
>   			       const struct drm_rect *clip, struct drm_format_conv_state *state);
>   void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch,
>   			       const struct iosys_map *src, const struct drm_framebuffer *fb,
> -			       const struct drm_rect *clip, struct drm_format_conv_state *state,
> -			       bool swab);
> +			       const struct drm_rect *clip, struct drm_format_conv_state *state);
> +void drm_fb_xrgb8888_to_rgb565be(struct iosys_map *dst, const unsigned int *dst_pitch,
> +				 const struct iosys_map *src, const struct drm_framebuffer *fb,
> +				 const struct drm_rect *clip, struct drm_format_conv_state *state);
>   void drm_fb_xrgb8888_to_xrgb1555(struct iosys_map *dst, const unsigned int *dst_pitch,
>   				 const struct iosys_map *src, const struct drm_framebuffer *fb,
>   				 const struct drm_rect *clip, struct drm_format_conv_state *state);



More information about the dri-devel mailing list