[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, ¶ms->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, ¶ms->clip,
> - &fmtcnv_state, true);
> + drm_fb_xrgb8888_to_rgb565be(&dst, &result->dst_pitch, &src, &fb, ¶ms->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, ¶ms->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