lkml.org 
[lkml]   [2022]   [Jul]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 2/3] drm/format-helper: Fix endianness in drm_fb_*_to_*() conversion helpers
Date
DRM formats are defined to be little-endian, unless the
DRM_FORMAT_BIG_ENDIAN flag is set. Hence when converting from one
format to another, multi-byte pixel values loaded from memory must be
converted from little-endian to host-endian. Conversely, multi-byte
pixel values written to memory must be converted from host-endian to
little-endian. Currently only drm_fb_xrgb8888_to_rgb332_line() includes
endianness handling.

Fix this by adding endianness handling to all conversion functions that
process multi-byte pixel values.

Note that the conversion to RGB565 is special, as there are two
versions: with and without byteswapping of the RGB565 pixel data.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
Tested with WIP atari_drm, which supports native big-endian RGB565.

Notes:
- Most of these are used only by GUD or simpledrm (the latter through
drm_fb_blit_toio()).
Interestingly, drm_fb_xrgb8888_to_rgb332() was introduced for GUD,
and always had correct endiannes handling...
- drm_fb_xrgb8888_to_gray8() is also used by st7586.c.
---
drivers/gpu/drm/drm_format_helper.c | 80 +++++++++++++++++------------
1 file changed, 46 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
index a3ccd8bc966fd816..c6182b5de78b0bd8 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -279,14 +279,16 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb332);
static void drm_fb_xrgb8888_to_rgb565_line(void *dbuf, const void *sbuf, unsigned int pixels)
{
u16 *dbuf16 = dbuf;
- const u32 *sbuf32 = sbuf;
+ const __le32 *sbuf32 = sbuf;
unsigned int x;
u16 val16;
+ u32 pix;

for (x = 0; x < pixels; x++) {
- val16 = ((sbuf32[x] & 0x00F80000) >> 8) |
- ((sbuf32[x] & 0x0000FC00) >> 5) |
- ((sbuf32[x] & 0x000000F8) >> 3);
+ pix = le32_to_cpu(sbuf32[x]);
+ val16 = ((pix & 0x00F80000) >> 8) |
+ ((pix & 0x0000FC00) >> 5) |
+ ((pix & 0x000000F8) >> 3);
dbuf16[x] = val16;
}
}
@@ -295,14 +297,16 @@ static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf,
unsigned int pixels)
{
u16 *dbuf16 = dbuf;
- const u32 *sbuf32 = sbuf;
+ const __le32 *sbuf32 = sbuf;
unsigned int x;
u16 val16;
+ u32 pix;

for (x = 0; x < pixels; x++) {
- val16 = ((sbuf32[x] & 0x00F80000) >> 8) |
- ((sbuf32[x] & 0x0000FC00) >> 5) |
- ((sbuf32[x] & 0x000000F8) >> 3);
+ pix = le32_to_cpu(sbuf32[x]);
+ val16 = ((pix & 0x00F80000) >> 8) |
+ ((pix & 0x0000FC00) >> 5) |
+ ((pix & 0x000000F8) >> 3);
dbuf16[x] = swab16(val16);
}
}
@@ -360,13 +364,15 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565_toio);
static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigned int pixels)
{
u8 *dbuf8 = dbuf;
- const u32 *sbuf32 = sbuf;
+ const __le32 *sbuf32 = sbuf;
unsigned int x;
+ u32 pix;

for (x = 0; x < pixels; x++) {
- *dbuf8++ = (sbuf32[x] & 0x000000FF) >> 0;
- *dbuf8++ = (sbuf32[x] & 0x0000FF00) >> 8;
- *dbuf8++ = (sbuf32[x] & 0x00FF0000) >> 16;
+ pix = le32_to_cpu(sbuf32[x]);
+ *dbuf8++ = (pix & 0x000000FF) >> 0;
+ *dbuf8++ = (pix & 0x0000FF00) >> 8;
+ *dbuf8++ = (pix & 0x00FF0000) >> 16;
}
}

@@ -410,17 +416,19 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888_toio);

static void drm_fb_rgb565_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
{
- u32 *dbuf32 = dbuf;
- const u16 *sbuf16 = sbuf;
+ __le32 *dbuf32 = dbuf;
+ const __le16 *sbuf16 = sbuf;
unsigned int x;

- for (x = 0; x < pixels; x++, ++sbuf16, ++dbuf32) {
- u32 val32 = ((*sbuf16 & 0xf800) << 8) |
- ((*sbuf16 & 0x07e0) << 5) |
- ((*sbuf16 & 0x001f) << 3);
- *dbuf32 = 0xff000000 | val32 |
- ((val32 >> 3) & 0x00070007) |
- ((val32 >> 2) & 0x00000300);
+ for (x = 0; x < pixels; x++) {
+ u16 val16 = le16_to_cpu(sbuf16[x]);
+ u32 val32 = ((val16 & 0xf800) << 8) |
+ ((val16 & 0x07e0) << 5) |
+ ((val16 & 0x001f) << 3);
+ val32 = 0xff000000 | val32 |
+ ((val32 >> 3) & 0x00070007) |
+ ((val32 >> 2) & 0x00000300);
+ dbuf32[x] = cpu_to_le32(val32);
}
}

@@ -434,7 +442,7 @@ static void drm_fb_rgb565_to_xrgb8888_toio(void __iomem *dst, unsigned int dst_p

static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
{
- u32 *dbuf32 = dbuf;
+ __le32 *dbuf32 = dbuf;
const u8 *sbuf8 = sbuf;
unsigned int x;

@@ -442,7 +450,8 @@ static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigne
u8 r = *sbuf8++;
u8 g = *sbuf8++;
u8 b = *sbuf8++;
- *dbuf32++ = 0xff000000 | (r << 16) | (g << 8) | b;
+ u32 pix = 0xff000000 | (r << 16) | (g << 8) | b;
+ dbuf32[x] = cpu_to_le32(pix);
}
}

@@ -456,16 +465,19 @@ static void drm_fb_rgb888_to_xrgb8888_toio(void __iomem *dst, unsigned int dst_p

static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels)
{
- u32 *dbuf32 = dbuf;
- const u32 *sbuf32 = sbuf;
+ __le32 *dbuf32 = dbuf;
+ const __le32 *sbuf32 = sbuf;
unsigned int x;
u32 val32;
+ u32 pix;

for (x = 0; x < pixels; x++) {
- val32 = ((sbuf32[x] & 0x000000FF) << 2) |
- ((sbuf32[x] & 0x0000FF00) << 4) |
- ((sbuf32[x] & 0x00FF0000) << 6);
- *dbuf32++ = val32 | ((val32 >> 8) & 0x00300C03);
+ pix = le32_to_cpu(sbuf32[x]);
+ val32 = ((pix & 0x000000FF) << 2) |
+ ((pix & 0x0000FF00) << 4) |
+ ((pix & 0x00FF0000) << 6);
+ pix = val32 | ((val32 >> 8) & 0x00300C03);
+ *dbuf32++ = cpu_to_le32(pix);
}
}

@@ -494,17 +506,17 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010_toio);
static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels)
{
u8 *dbuf8 = dbuf;
- const u32 *sbuf32 = sbuf;
+ const __le32 *sbuf32 = sbuf;
unsigned int x;

for (x = 0; x < pixels; x++) {
- u8 r = (*sbuf32 & 0x00ff0000) >> 16;
- u8 g = (*sbuf32 & 0x0000ff00) >> 8;
- u8 b = *sbuf32 & 0x000000ff;
+ u32 pix = le32_to_cpu(sbuf32[x]);
+ u8 r = (pix & 0x00ff0000) >> 16;
+ u8 g = (pix & 0x0000ff00) >> 8;
+ u8 b = pix & 0x000000ff;

/* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */
*dbuf8++ = (3 * r + 6 * g + b) / 10;
- sbuf32++;
}
}

--
2.25.1
\
 
 \ /
  Last update: 2022-07-08 20:23    [W:0.121 / U:0.528 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site