[PATCH v6 3/3] drm: Add GUD USB Display driver
Noralf Trønnes
noralf at tronnes.org
Thu Feb 25 18:06:40 UTC 2021
Den 25.02.2021 10.58, skrev Peter Stuge:
> Hi Noralf,
>
> Noralf Trønnes wrote:
>> The driver supports a one bit monochrome transfer format: R1. This is not
>> implemented in the gadget driver. It is added in preparation for future
>> monochrome e-ink displays.
>
> I forgot, but I have a two-tone (black/red) e-ink display here, and I
> also have a 3-bpp RGB TFT display.
>
> Should we add maybe R2 and R3? (or R3/R8 for number of colours?)
>
> I'm particularly considering the 3-bpp RGB panel for GUD use now, and
> while it will surely work with say a 16-bit RGB mode many bits will
> be wasted in the process.
>
> What are your thoughts? Would you take a patch for that now, later, never?
>
I've been anticipating the need for more formats, but I didn't want to
add them without having a user. Otherwise I could end up adding stuff
that would never be used. If you can test, there's no problem adding
support for more formats now.
The R1 name is derived from DRM_FORMAT_R8 which is a 8 bit monochrome
(or one color channel) format.
Linux has these one byte color pixel formats currently defined:
/* color index */
#define DRM_FORMAT_C8 fourcc_code('C', '8', ' ', ' ') /* [7:0] C */
/* 8 bpp Red */
#define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ') /* [7:0] R */
/* 8 bpp RGB */
#define DRM_FORMAT_RGB332 fourcc_code('R', 'G', 'B', '8') /* [7:0] R:G:B
3:3:2 */
#define DRM_FORMAT_BGR233 fourcc_code('B', 'G', 'R', '8') /* [7:0] B:G:R
2:3:3 */
And these two color formats:
/* 16 bpp RG */
#define DRM_FORMAT_RG88 fourcc_code('R', 'G', '8', '8') /* [15:0] R:G
8:8 little endian */
#define DRM_FORMAT_GR88 fourcc_code('G', 'R', '8', '8') /* [15:0] G:R
8:8 little endian */
/* 32 bpp RG */
#define DRM_FORMAT_RG1616 fourcc_code('R', 'G', '3', '2') /* [31:0] R:G
16:16 little endian */
#define DRM_FORMAT_GR1616 fourcc_code('G', 'R', '3', '2') /* [31:0] G:R
16:16 little endian */
Building on that I would define a 2 bpp RG format like this in the driver:
static const struct drm_format_info gud_drm_format_rg11 = {
.format = GUD_DRM_FORMAT_RG11,
.num_planes = 1,
.char_per_block = { 1, 0, 0 },
.block_w = { 4, 0, 0 }, /* 4 pixels per block/byte */
.block_h = { 1, 0, 0 },
.hsub = 1,
.vsub = 1,
};
And a 3 bpp RGB format like this:
static const struct drm_format_info gud_drm_format_rgb111 = {
.format = GUD_DRM_FORMAT_RGB111,
.num_planes = 1,
.char_per_block = { 1, 0, 0 },
.block_w = { 2, 0, 0 }, /* 2 pixels per block/byte */
.block_h = { 1, 0, 0 },
.hsub = 1,
.vsub = 1,
};
The MIPI DBI standard defines 2 ways to transmit 2x 3-bpp pixels in one
byte (X=pad bit):
- Option 1: X X R1 G1 B1 R2 G2 B2
- Option 2: X R1 G1 B1 X R2 G2 B2
So maybe we should have GUD_DRM_FORMAT_RGB111_OPTION1 and
GUD_DRM_FORMAT_RGB111_OPTION2?
Or just use option 2 and let the display fix it up if needed?
What format does your 3 bpp display use?
And then something like this for the conversion function:
static size_t gud_xrgb8888_to_color(u8 *dst, const struct
drm_format_info *format,
u32 *src, struct drm_framebuffer *fb,
struct drm_rect *rect)
{
unsigned int block_width = drm_format_info_block_width(format, 0);
unsigned int x, y, width, height;
u8 r, g, b, *block = dst; /* Assign to silence compiler warning */
size_t len;
WARN_ON_ONCE(format->char_per_block[0] != 1);
/* Start on a byte boundary */
rect->x1 = ALIGN_DOWN(rect->x1, block_width);
width = drm_rect_width(rect);
height = drm_rect_height(rect);
len = drm_format_info_min_pitch(format, 0, width) * height;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
if (!(x % block_width)) {
block = dst++;
*block = 0;
}
/* r,g,b are bytes so no need to mask out anything explicitly */
r = *src >> 16;
g = *src >> 8;
b = *src++;
switch (format->format) {
case GUD_DRM_FORMAT_RG11:
*block <<= 2;
*block |= ((r >> 7) << 1) | (g >> 7);
break;
case GUD_DRM_FORMAT_RGB111_OPTION1:
*block <<= 3;
*block |= ((r >> 7) << 2) | ((g >> 7) << 1) | (b >> 7);
break;
case GUD_DRM_FORMAT_RGB111_OPTION2:
*block <<= 4;
*block |= ((r >> 7) << 2) | ((g >> 7) << 1) | (b >> 7);
break;
default:
WARN_ON_ONCE(1);
return len;
};
}
}
return len;
}
Noralf.
More information about the dri-devel
mailing list