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

drm/format-helper: Add drm_fb_swab()

This replaces drm_fb_swab16() with drm_fb_swab() supporting 16 and 32-bit.
Also make pixel line caching optional.

v2:
- Bail out on cpp != 2 && 4 (Sam)

Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20200509141619.32970-8-noralf@tronnes.org

+44 -23
+41 -20
drivers/gpu/drm/drm_format_helper.c
··· 79 79 EXPORT_SYMBOL(drm_fb_memcpy_dstclip); 80 80 81 81 /** 82 - * drm_fb_swab16 - Swap bytes into clip buffer 83 - * @dst: RGB565 destination buffer 84 - * @vaddr: RGB565 source buffer 82 + * drm_fb_swab - Swap bytes into clip buffer 83 + * @dst: Destination buffer 84 + * @src: Source buffer 85 85 * @fb: DRM framebuffer 86 86 * @clip: Clip rectangle area to copy 87 + * @cached: Source buffer is mapped cached (eg. not write-combined) 88 + * 89 + * If @cached is false a temporary buffer is used to cache one pixel line at a 90 + * time to speed up slow uncached reads. 91 + * 92 + * This function does not apply clipping on dst, i.e. the destination 93 + * is a small buffer containing the clip rect only. 87 94 */ 88 - void drm_fb_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb, 89 - struct drm_rect *clip) 95 + void drm_fb_swab(void *dst, void *src, struct drm_framebuffer *fb, 96 + struct drm_rect *clip, bool cached) 90 97 { 91 - size_t len = (clip->x2 - clip->x1) * sizeof(u16); 98 + u8 cpp = fb->format->cpp[0]; 99 + size_t len = drm_rect_width(clip) * cpp; 100 + u16 *src16, *dst16 = dst; 101 + u32 *src32, *dst32 = dst; 92 102 unsigned int x, y; 93 - u16 *src, *buf; 103 + void *buf = NULL; 94 104 95 - /* 96 - * The cma memory is write-combined so reads are uncached. 97 - * Speed up by fetching one line at a time. 98 - */ 99 - buf = kmalloc(len, GFP_KERNEL); 100 - if (!buf) 105 + if (WARN_ON_ONCE(cpp != 2 && cpp != 4)) 101 106 return; 102 107 108 + if (!cached) 109 + buf = kmalloc(len, GFP_KERNEL); 110 + 111 + src += clip_offset(clip, fb->pitches[0], cpp); 112 + 103 113 for (y = clip->y1; y < clip->y2; y++) { 104 - src = vaddr + (y * fb->pitches[0]); 105 - src += clip->x1; 106 - memcpy(buf, src, len); 107 - src = buf; 108 - for (x = clip->x1; x < clip->x2; x++) 109 - *dst++ = swab16(*src++); 114 + if (buf) { 115 + memcpy(buf, src, len); 116 + src16 = buf; 117 + src32 = buf; 118 + } else { 119 + src16 = src; 120 + src32 = src; 121 + } 122 + 123 + for (x = clip->x1; x < clip->x2; x++) { 124 + if (cpp == 4) 125 + *dst32++ = swab32(*src32++); 126 + else 127 + *dst16++ = swab16(*src16++); 128 + } 129 + 130 + src += fb->pitches[0]; 110 131 } 111 132 112 133 kfree(buf); 113 134 } 114 - EXPORT_SYMBOL(drm_fb_swab16); 135 + EXPORT_SYMBOL(drm_fb_swab); 115 136 116 137 static void drm_fb_xrgb8888_to_rgb565_line(u16 *dbuf, u32 *sbuf, 117 138 unsigned int pixels,
+1 -1
drivers/gpu/drm/drm_mipi_dbi.c
··· 217 217 switch (fb->format->format) { 218 218 case DRM_FORMAT_RGB565: 219 219 if (swap) 220 - drm_fb_swab16(dst, src, fb, clip); 220 + drm_fb_swab(dst, src, fb, clip, !import_attach); 221 221 else 222 222 drm_fb_memcpy(dst, src, fb, clip); 223 223 break;
+2 -2
include/drm/drm_format_helper.h
··· 14 14 void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr, 15 15 struct drm_framebuffer *fb, 16 16 struct drm_rect *clip); 17 - void drm_fb_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb, 18 - struct drm_rect *clip); 17 + void drm_fb_swab(void *dst, void *src, struct drm_framebuffer *fb, 18 + struct drm_rect *clip, bool cached); 19 19 void drm_fb_xrgb8888_to_rgb565(void *dst, void *vaddr, 20 20 struct drm_framebuffer *fb, 21 21 struct drm_rect *clip, bool swab);