@@ -397,7 +397,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y,
if (vid_priv->colour_bg)
val = 255 - val;
- if (vid_priv->format == VIDEO_X2R10G10B10)
+ if (vid_priv->format == VIDEO_XRGB2101010)
out = val << 2 | val << 12 | val << 22;
else
out = val | val << 8 | val << 16;
@@ -923,7 +923,7 @@ static int truetype_set_cursor_visible(struct udevice *dev, bool visible,
for (i = 0; i < width; i++) {
int out;
- if (vid_priv->format == VIDEO_X2R10G10B10)
+ if (vid_priv->format == VIDEO_XRGB2101010)
out = val << 2 | val << 12 | val << 22;
else
out = val | val << 8 | val << 16;
@@ -72,7 +72,7 @@ static int simple_video_probe(struct udevice *dev)
} else if (strcmp(format, "a2r10g10b10") == 0 ||
strcmp(format, "x2r10g10b10") == 0) {
uc_priv->bpix = VIDEO_BPP32;
- uc_priv->format = VIDEO_X2R10G10B10;
+ uc_priv->format = VIDEO_XRGB2101010;
} else {
log_err("%s: invalid format: %s\n", __func__, format);
return -EINVAL;
@@ -65,13 +65,6 @@ struct video_uc_priv {
ulong video_ptr;
};
-/** struct vid_rgb - Describes a video colour */
-struct vid_rgb {
- u32 r;
- u32 g;
- u32 b;
-};
-
void video_set_flush_dcache(struct udevice *dev, bool flush)
{
struct video_priv *priv = dev_get_uclass_priv(dev);
@@ -259,7 +252,7 @@ int video_clear(struct udevice *dev)
return 0;
}
-static const struct vid_rgb colours[VID_COLOUR_COUNT] = {
+static const struct video_rgb colours[VID_COLOUR_COUNT] = {
{ 0x00, 0x00, 0x00 }, /* black */
{ 0xc0, 0x00, 0x00 }, /* red */
{ 0x00, 0xc0, 0x00 }, /* green */
@@ -281,30 +274,17 @@ static const struct vid_rgb colours[VID_COLOUR_COUNT] = {
u32 video_index_to_colour(struct video_priv *priv, enum colour_idx idx)
{
switch (priv->bpix) {
+ case VIDEO_BPP8:
+ if (CONFIG_IS_ENABLED(VIDEO_BPP8))
+ return video_rgb_to_pixel8(priv->format, colours[idx]);
+ break;
case VIDEO_BPP16:
- if (CONFIG_IS_ENABLED(VIDEO_BPP16)) {
- return ((colours[idx].r >> 3) << 11) |
- ((colours[idx].g >> 2) << 5) |
- ((colours[idx].b >> 3) << 0);
- }
+ if (CONFIG_IS_ENABLED(VIDEO_BPP16))
+ return video_rgb_to_pixel16(priv->format, colours[idx]);
break;
case VIDEO_BPP32:
- if (CONFIG_IS_ENABLED(VIDEO_BPP32)) {
- switch (priv->format) {
- case VIDEO_X2R10G10B10:
- return (colours[idx].r << 22) |
- (colours[idx].g << 12) |
- (colours[idx].b << 2);
- case VIDEO_RGBA8888:
- return (colours[idx].r << 24) |
- (colours[idx].g << 16) |
- (colours[idx].b << 8) | 0xff;
- default:
- return (colours[idx].r << 16) |
- (colours[idx].g << 8) |
- (colours[idx].b << 0);
- }
- }
+ if (CONFIG_IS_ENABLED(VIDEO_BPP32))
+ return video_rgb_to_pixel32(priv->format, colours[idx]);
break;
default:
break;
@@ -80,7 +80,7 @@ static void write_pix8(u8 *fb, uint bpix, enum video_format eformat,
*fb++ = cte->red;
*fb++ = cte->green;
*fb++ = cte->blue;
- } else if (eformat == VIDEO_X2R10G10B10) {
+ } else if (eformat == VIDEO_XRGB2101010) {
*(u32 *)fb = get_bmp_col_x2r10g10b10(cte);
} else if (eformat == VIDEO_RGBA8888) {
*(u32 *)fb = get_bmp_col_rgba8888(cte);
@@ -385,7 +385,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
(bmap[0] >> 3);
bmap += 3;
fb += 2;
- } else if (eformat == VIDEO_X2R10G10B10) {
+ } else if (eformat == VIDEO_XRGB2101010) {
u32 pix;
pix = *bmap++ << 2U;
@@ -422,7 +422,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
if (CONFIG_IS_ENABLED(BMP_32BPP)) {
for (i = 0; i < height; ++i) {
for (j = 0; j < width; j++) {
- if (eformat == VIDEO_X2R10G10B10) {
+ if (eformat == VIDEO_XRGB2101010) {
u32 pix;
pix = *bmap++ << 2U;
@@ -8,6 +8,8 @@
#define _VIDEO_H_
#include <stdio_dev.h>
+#include <video_format.h>
+#include <asm/byteorder.h>
struct udevice;
@@ -44,35 +46,6 @@ enum video_polarity {
VIDEO_ACTIVE_LOW, /* Pins are active low */
};
-/*
- * Bits per pixel selector. Each value n is such that the bits-per-pixel is
- * 2 ^ n
- */
-enum video_log2_bpp {
- VIDEO_BPP1 = 0,
- VIDEO_BPP2,
- VIDEO_BPP4,
- VIDEO_BPP8,
- VIDEO_BPP16,
- VIDEO_BPP32,
-};
-
-/*
- * Convert enum video_log2_bpp to bytes and bits. Note we omit the outer
- * brackets to allow multiplication by fractional pixels.
- */
-#define VNBYTES(bpix) ((1 << (bpix)) / 8)
-
-#define VNBITS(bpix) (1 << (bpix))
-
-enum video_format {
- VIDEO_UNKNOWN,
- VIDEO_RGBA8888,
- VIDEO_X8B8G8R8,
- VIDEO_X8R8G8B8,
- VIDEO_X2R10G10B10,
-};
-
/**
* struct video_priv - Device information used by the video uclass
*
new file mode 100644
@@ -0,0 +1,161 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2024 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ */
+
+#ifndef _VIDEO_FORMAT_H_
+#define _VIDEO_FORMAT_H_
+
+#include <compiler.h>
+
+/*
+ * Bits per pixel selector. Each value n is such that the bits-per-pixel is
+ * 2 ^ n
+ */
+enum video_log2_bpp {
+ VIDEO_BPP8 = 3,
+ VIDEO_BPP16,
+ VIDEO_BPP32,
+};
+
+/*
+ * Convert enum video_log2_bpp to bytes and bits. Note we omit the outer
+ * brackets to allow multiplication by fractional pixels.
+ */
+#define VNBYTES(bpix) ((1 << (bpix)) / 8)
+
+#define VNBITS(bpix) (1 << (bpix))
+
+/* Struct video_rgb - Describes a video colour, always 8 bpc */
+struct video_rgb {
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+};
+
+/* Naming respects linux/include/uapi/drm/drm_fourcc.h */
+enum video_format {
+ VIDEO_DEFAULT = 0,
+ VIDEO_RGB332, /* [7:0] R:G:B 3:3:2 */
+ VIDEO_RGB565, /* [15:0] R:G:B 5:6:5 little endian */
+ VIDEO_RGB565_BE, /* [15:0] R:G:B 5:6:5 big endian */
+ VIDEO_XRGB8888, /* [31:0] x:R:G:B 8:8:8:8 little endian */
+ VIDEO_BGRX8888, /* [31:0] B:G:R:x 8:8:8:8 little endian */
+ VIDEO_XRGB8888_BE = VIDEO_BGRX8888,
+ VIDEO_XBGR8888, /* [31:0] x:B:G:R 8:8:8:8 little endian */
+ VIDEO_RGBA8888, /* [31:0] R:G:B:A 8:8:8:8 little endian */
+ VIDEO_XRGB2101010, /* [31:0] x:R:G:B 2:10:10:10 little endian */
+ VIDEO_XRGB2101010_BE, /* [31:0] x:R:G:B 2:10:10:10 big endian */
+ VIDEO_FMT_END
+};
+
+/**
+ * video_rgb_to_pixel8() - convert a RGB color to a 8 bit pixel's
+ * memory representation.
+ *
+ * @video_format Format of pixel
+ * @rgb RGB color
+ * Return: color value
+ */
+static inline uint8_t video_rgb_to_pixel8(enum video_format format,
+ struct video_rgb rgb)
+{
+ switch (format) {
+ case VIDEO_DEFAULT:
+ case VIDEO_RGB332:
+ return ((rgb.r >> 5) << 5) |
+ ((rgb.g >> 5) << 2) |
+ (rgb.b >> 6);
+ default:
+ break;
+ }
+ return 0;
+}
+
+/**
+ * video_rgb_to_pixel16() - convert a RGB color to a 16 bit pixel's
+ * memory representation.
+ *
+ * @video_format Format of pixel
+ * @rgb RGB color
+ * Return: color value
+ */
+static inline uint16_t video_rgb_to_pixel16(enum video_format format,
+ struct video_rgb rgb)
+{
+ unsigned int val = 0;
+
+ /* Handle layout first */
+ switch (format) {
+ case VIDEO_DEFAULT:
+ case VIDEO_RGB565:
+ case VIDEO_RGB565_BE:
+ val = ((rgb.r >> 3) << 11) |
+ ((rgb.g >> 2) << 5) |
+ ((rgb.b >> 3) << 0);
+ break;
+ default:
+ break;
+ }
+
+ /* Then handle endian */
+ switch (format) {
+ case VIDEO_RGB565_BE:
+ return cpu_to_be16(val);
+ default:
+ return cpu_to_le16(val);
+ }
+
+}
+
+/**
+ * video_rgb_to_pixel32() - convert a RGB color to a 32 bit pixel's
+ * memory representation.
+ *
+ * @video_format Format of pixel
+ * @rgb RGB color
+ * Return: color value
+ */
+static inline uint32_t video_rgb_to_pixel32(enum video_format format,
+ struct video_rgb rgb)
+{
+ unsigned int val = 0;
+
+ /* Handle layout first */
+ switch (format) {
+#ifdef __LITTLE_ENDIAN
+ case VIDEO_DEFAULT:
+#endif
+ case VIDEO_XRGB8888:
+ val = (rgb.r << 16) | (rgb.g << 8) | rgb.b;
+ break;
+#ifdef __BIG_ENDIAN
+ case VIDEO_DEFAULT:
+#endif
+ case VIDEO_BGRX8888:
+ val = (rgb.b << 24) | (rgb.g << 8) | (rgb.r << 8);
+ break;
+ case VIDEO_XBGR8888:
+ val = (rgb.b << 16) | (rgb.g << 8) | rgb.b;
+ break;
+ case VIDEO_RGBA8888:
+ val = (rgb.r << 24) | (rgb.g << 16) | (rgb.b << 8) | 0xff;
+ break;
+ case VIDEO_XRGB2101010:
+ case VIDEO_XRGB2101010_BE:
+ val = (rgb.r << 22) | (rgb.g << 12) | (rgb.b << 2);
+ default:
+ break;
+ }
+
+ /* Then handle endian */
+ switch (format) {
+ case VIDEO_XRGB2101010_BE:
+ return cpu_to_be32(val);
+ default:
+ return cpu_to_le32(val);
+ }
+
+ return 0;
+}
+#endif
@@ -531,7 +531,7 @@ efi_status_t efi_gop_register(void)
gopobj->info.height = row;
if (bpix == VIDEO_BPP32)
{
- if (format == VIDEO_X2R10G10B10) {
+ if (format == VIDEO_XRGB2101010) {
gopobj->info.pixel_format = EFI_GOT_BITMASK;
gopobj->info.pixel_bitmask[0] = 0x3ff00000; /* red */
gopobj->info.pixel_bitmask[1] = 0x000ffc00; /* green */
Our current approach on naming pixel formats and handling them is a little bit confusing, we don't consider endian for framebuffers. Using Linux's naming approach instead to improve robustness of the system, also consider both endians for all pixel formats. Formats and RGB->Pixel conversion functions are stripped to video_format.h so we can include them in sdl.c without pull in all u-boot headers, and inline those conversion functions everywhere. Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com> --- drivers/video/console_truetype.c | 4 +- drivers/video/simplefb.c | 2 +- drivers/video/video-uclass.c | 38 +++------ drivers/video/video_bmp.c | 6 +- include/video.h | 31 +------- include/video_format.h | 161 +++++++++++++++++++++++++++++++++++++++ lib/efi_loader/efi_gop.c | 2 +- 7 files changed, 179 insertions(+), 65 deletions(-)