Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

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

+72 -33
+44 -24
drivers/gpu/drm/drm_format_helper.c
··· 559 559 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb565); 560 560 } 561 561 562 - static __always_inline u32 drm_xrgb8888_to_rgb565_swab(u32 pix) 563 - { 564 - return swab16(drm_pixel_xrgb8888_to_rgb565(pix)); 565 - } 566 - 567 - /* TODO: implement this helper as conversion to RGB565|BIG_ENDIAN */ 568 - static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf, 569 - unsigned int pixels) 570 - { 571 - drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_xrgb8888_to_rgb565_swab); 572 - } 573 - 574 562 /** 575 563 * drm_fb_xrgb8888_to_rgb565 - Convert XRGB8888 to RGB565 clip buffer 576 564 * @dst: Array of RGB565 destination buffers ··· 568 580 * @fb: DRM framebuffer 569 581 * @clip: Clip rectangle area to copy 570 582 * @state: Transform and conversion state 571 - * @swab: Swap bytes 572 583 * 573 584 * This function copies parts of a framebuffer to display memory and converts the 574 585 * color format during the process. Destination and framebuffer formats must match. The ··· 582 595 */ 583 596 void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch, 584 597 const struct iosys_map *src, const struct drm_framebuffer *fb, 585 - const struct drm_rect *clip, struct drm_format_conv_state *state, 586 - bool swab) 598 + const struct drm_rect *clip, struct drm_format_conv_state *state) 587 599 { 588 600 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 589 601 2, 590 602 }; 591 603 592 - void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels); 593 - 594 - if (swab) 595 - xfrm_line = drm_fb_xrgb8888_to_rgb565_swab_line; 596 - else 597 - xfrm_line = drm_fb_xrgb8888_to_rgb565_line; 598 - 599 - drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, xfrm_line); 604 + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 605 + drm_fb_xrgb8888_to_rgb565_line); 600 606 } 601 607 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565); 608 + 609 + static void drm_fb_xrgb8888_to_rgb565be_line(void *dbuf, const void *sbuf, 610 + unsigned int pixels) 611 + { 612 + drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb565be); 613 + } 614 + 615 + /** 616 + * drm_fb_xrgb8888_to_rgb565be - Convert XRGB8888 to RGB565|DRM_FORMAT_BIG_ENDIAN clip buffer 617 + * @dst: Array of RGB565BE destination buffers 618 + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 619 + * within @dst; can be NULL if scanlines are stored next to each other. 620 + * @src: Array of XRGB8888 source buffer 621 + * @fb: DRM framebuffer 622 + * @clip: Clip rectangle area to copy 623 + * @state: Transform and conversion state 624 + * 625 + * This function copies parts of a framebuffer to display memory and converts the 626 + * color format during the process. Destination and framebuffer formats must match. The 627 + * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 628 + * least as many entries as there are planes in @fb's format. Each entry stores the 629 + * value for the format's respective color plane at the same index. 630 + * 631 + * This function does not apply clipping on @dst (i.e. the destination is at the 632 + * top-left corner). 633 + * 634 + * Drivers can use this function for RGB565BE devices that don't support XRGB8888 natively. 635 + */ 636 + void drm_fb_xrgb8888_to_rgb565be(struct iosys_map *dst, const unsigned int *dst_pitch, 637 + const struct iosys_map *src, const struct drm_framebuffer *fb, 638 + const struct drm_rect *clip, struct drm_format_conv_state *state) 639 + { 640 + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 641 + 2, 642 + }; 643 + 644 + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 645 + drm_fb_xrgb8888_to_rgb565be_line); 646 + } 647 + EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565be); 602 648 603 649 static void drm_fb_xrgb8888_to_xrgb1555_line(void *dbuf, const void *sbuf, unsigned int pixels) 604 650 { ··· 1208 1188 return 0; 1209 1189 } else if (fb_format == DRM_FORMAT_XRGB8888) { 1210 1190 if (dst_format == DRM_FORMAT_RGB565) { 1211 - drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, state, false); 1191 + drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, state); 1212 1192 return 0; 1213 1193 } else if (dst_format == DRM_FORMAT_XRGB1555) { 1214 1194 drm_fb_xrgb8888_to_xrgb1555(dst, dst_pitch, src, fb, clip, state);
+6
drivers/gpu/drm/drm_format_internal.h
··· 5 5 6 6 #include <linux/bits.h> 7 7 #include <linux/types.h> 8 + #include <linux/swab.h> 8 9 9 10 /* 10 11 * Each pixel-format conversion helper takes a raw pixel in a ··· 58 57 return ((pix & 0x00f80000) >> 8) | 59 58 ((pix & 0x0000fc00) >> 5) | 60 59 ((pix & 0x000000f8) >> 3); 60 + } 61 + 62 + static inline u32 drm_pixel_xrgb8888_to_rgb565be(u32 pix) 63 + { 64 + return swab16(drm_pixel_xrgb8888_to_rgb565(pix)); 61 65 } 62 66 63 67 static inline u32 drm_pixel_xrgb8888_to_rgbx5551(u32 pix)
+7 -1
drivers/gpu/drm/drm_mipi_dbi.c
··· 230 230 case DRM_FORMAT_XRGB8888: 231 231 switch (dbidev->pixel_format) { 232 232 case DRM_FORMAT_RGB565: 233 - drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, src, fb, clip, fmtcnv_state, swap); 233 + if (swap) { 234 + drm_fb_xrgb8888_to_rgb565be(&dst_map, NULL, src, fb, clip, 235 + fmtcnv_state); 236 + } else { 237 + drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, src, fb, clip, 238 + fmtcnv_state); 239 + } 234 240 break; 235 241 case DRM_FORMAT_RGB888: 236 242 drm_fb_xrgb8888_to_rgb888(&dst_map, NULL, src, fb, clip, fmtcnv_state);
+7 -2
drivers/gpu/drm/gud/gud_pipe.c
··· 188 188 } else if (format->format == DRM_FORMAT_RGB332) { 189 189 drm_fb_xrgb8888_to_rgb332(&dst, NULL, src, fb, rect, fmtcnv_state); 190 190 } else if (format->format == DRM_FORMAT_RGB565) { 191 - drm_fb_xrgb8888_to_rgb565(&dst, NULL, src, fb, rect, fmtcnv_state, 192 - gud_is_big_endian()); 191 + if (gud_is_big_endian()) { 192 + drm_fb_xrgb8888_to_rgb565be(&dst, NULL, src, fb, rect, 193 + fmtcnv_state); 194 + } else { 195 + drm_fb_xrgb8888_to_rgb565(&dst, NULL, src, fb, rect, 196 + fmtcnv_state); 197 + } 193 198 } else if (format->format == DRM_FORMAT_RGB888) { 194 199 drm_fb_xrgb8888_to_rgb888(&dst, NULL, src, fb, rect, fmtcnv_state); 195 200 } else {
+4 -4
drivers/gpu/drm/tests/drm_format_helper_test.c
··· 735 735 NULL : &result->dst_pitch; 736 736 737 737 drm_fb_xrgb8888_to_rgb565(&dst, dst_pitch, &src, &fb, &params->clip, 738 - &fmtcnv_state, false); 738 + &fmtcnv_state); 739 739 buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); 740 740 KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); 741 741 742 742 buf = dst.vaddr; /* restore original value of buf */ 743 - drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, &params->clip, 744 - &fmtcnv_state, true); 743 + drm_fb_xrgb8888_to_rgb565be(&dst, &result->dst_pitch, &src, &fb, &params->clip, 744 + &fmtcnv_state); 745 745 buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); 746 746 KUNIT_EXPECT_MEMEQ(test, buf, result->expected_swab, dst_size); 747 747 ··· 749 749 memset(buf, 0, dst_size); 750 750 751 751 drm_fb_xrgb8888_to_rgb565(&dst, dst_pitch, &src, &fb, &params->clip, 752 - &fmtcnv_state, false); 752 + &fmtcnv_state); 753 753 buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); 754 754 KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); 755 755 }
+4 -2
include/drm/drm_format_helper.h
··· 82 82 const struct drm_rect *clip, struct drm_format_conv_state *state); 83 83 void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch, 84 84 const struct iosys_map *src, const struct drm_framebuffer *fb, 85 - const struct drm_rect *clip, struct drm_format_conv_state *state, 86 - bool swab); 85 + const struct drm_rect *clip, struct drm_format_conv_state *state); 86 + void drm_fb_xrgb8888_to_rgb565be(struct iosys_map *dst, const unsigned int *dst_pitch, 87 + const struct iosys_map *src, const struct drm_framebuffer *fb, 88 + const struct drm_rect *clip, struct drm_format_conv_state *state); 87 89 void drm_fb_xrgb8888_to_xrgb1555(struct iosys_map *dst, const unsigned int *dst_pitch, 88 90 const struct iosys_map *src, const struct drm_framebuffer *fb, 89 91 const struct drm_rect *clip, struct drm_format_conv_state *state);