]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/format-helper: Split off byte swapping from drm_fb_xrgb8888_to_rgb565()
authorThomas Zimmermann <tzimmermann@suse.de>
Wed, 25 Jun 2025 11:48:22 +0000 (13:48 +0200)
committerThomas Zimmermann <tzimmermann@suse.de>
Fri, 27 Jun 2025 13:59:23 +0000 (15:59 +0200)
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.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com>
Link: https://lore.kernel.org/r/20250625114911.1121301-1-tzimmermann@suse.de
drivers/gpu/drm/drm_format_helper.c
drivers/gpu/drm/drm_format_internal.h
drivers/gpu/drm/drm_mipi_dbi.c
drivers/gpu/drm/gud/gud_pipe.c
drivers/gpu/drm/tests/drm_format_helper_test.c
include/drm/drm_format_helper.h

index 99d9f7bbc261fc6525eb0711c42c2dc44b1eb0b9..8f3daf38ca639d3d39742c2c9fa0c54a3a9297a5 100644 (file)
@@ -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);
index 9428d5cfebc53f39c1662398a6cff37455035598..ce29dd05bcc5580418eb9beefe68d7a1ca3544a8 100644 (file)
@@ -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) |
index ba4be6be5d2849c653220cfbca236a4a2c4d1a56..e33c78fc8fbd722565306b5d16ba389ad0e68343 100644 (file)
@@ -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);
index adadd526641d2ab994b867533d8f7e60248953e1..8d548d08f127f1b7f9b93cd9a86663d1f058eea3 100644 (file)
@@ -188,8 +188,13 @@ retry:
                } 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 {
index ad06762db6719f1b24fd9e38ee9a0cefa39d1d7f..7299fa8971ce5a5695c4dbb43d7682d86a886727 100644 (file)
@@ -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);
 }
index 0d3ee2a1313f0d22c37f4cfaccefb0c1cbb0f110..562bc383ece4e90d96aa92b47b4f69609f825a6e 100644 (file)
@@ -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);