[PATCH 1/3] video: add support for drawing 8bpp bitmap on 32bpp framebuffer

Anatolij Gustschin agust at denx.de
Wed Feb 5 17:49:57 CET 2020


cfb_console driver supported 8bpp bitmap drawing on 24bpp/32bpp
displays and some boards used this configuration for drawing
the logo. After conversion to DM_VIDEO the logo drawing on such
boards doesn't work any more due to missing rendering code in the
updated bmp command code for DM_VIDEO. Add 8bpp bitmap support
for 32bpp displays.

Signed-off-by: Anatolij Gustschin <agust at denx.de>
---
 drivers/video/video-uclass.c |  6 ++++
 drivers/video/video_bmp.c    | 62 ++++++++++++++++++++++++------------
 include/video.h              |  2 +-
 3 files changed, 48 insertions(+), 22 deletions(-)

diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index 12057c8a5b..44380a38d9 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -228,6 +228,12 @@ static int video_post_probe(struct udevice *dev)
 	struct udevice *cons;
 	int ret;
 
+	if (priv->bpix == VIDEO_BPP32) {
+		priv->cmap = realloc(priv->cmap, 256 * sizeof(uint));
+		if (!priv->cmap)
+			return -ENOMEM;
+	}
+
 	/* Set up the line and display size */
 	priv->fb = map_sysmem(plat->base, plat->size);
 	if (!priv->line_length)
diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c
index 8768228029..79d6c6afa5 100644
--- a/drivers/video/video_bmp.c
+++ b/drivers/video/video_bmp.c
@@ -172,16 +172,29 @@ static void video_set_cmap(struct udevice *dev,
 			   struct bmp_color_table_entry *cte, unsigned colours)
 {
 	struct video_priv *priv = dev_get_uclass_priv(dev);
+	u16 *cmap16;
+	u32 *cmap32;
 	int i;
-	ushort *cmap = priv->cmap;
 
 	debug("%s: colours=%d\n", __func__, colours);
-	for (i = 0; i < colours; ++i) {
-		*cmap = ((cte->red   << 8) & 0xf800) |
-			((cte->green << 3) & 0x07e0) |
-			((cte->blue  >> 3) & 0x001f);
-		cmap++;
-		cte++;
+	if (priv->bpix == VIDEO_BPP16) {
+		cmap16 = priv->cmap;
+		for (i = 0; i < colours; ++i) {
+			*cmap16 = ((cte->red << 8) & 0xf800) |
+				((cte->green << 3) & 0x07e0) |
+				((cte->blue  >> 3) & 0x001f);
+			cmap16++;
+			cte++;
+		}
+	} else if (priv->bpix == VIDEO_BPP32) {
+		cmap32 = priv->cmap;
+		for (i = 0; i < colours; ++i) {
+			*cmap32 = (cte->red  << 16) |
+				  (cte->green << 8) |
+				  cte->blue;
+			cmap32++;
+			cte++;
+		}
 	}
 }
 
@@ -189,7 +202,8 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
 		      bool align)
 {
 	struct video_priv *priv = dev_get_uclass_priv(dev);
-	ushort *cmap_base = NULL;
+	u32 *cmap32_base = NULL;
+	u16 *cmap16_base = NULL;
 	int i, j;
 	uchar *fb;
 	struct bmp_image *bmp = map_sysmem(bmp_image, 0);
@@ -227,11 +241,11 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
 	}
 
 	/*
-	 * We support displaying 8bpp and 24bpp BMPs on 16bpp LCDs
-	 * and displaying 24bpp BMPs on 32bpp LCDs
+	 * We support displaying 8bpp and 24bpp BMPs on 16bpp or 32bpp LCDs
 	 */
 	if (bpix != bmp_bpix &&
 	    !(bmp_bpix == 8 && bpix == 16) &&
+	    !(bmp_bpix == 8 && bpix == 32) &&
 	    !(bmp_bpix == 24 && bpix == 16) &&
 	    !(bmp_bpix == 24 && bpix == 32)) {
 		printf("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",
@@ -264,36 +278,42 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
 	switch (bmp_bpix) {
 	case 1:
 	case 8: {
-		cmap_base = priv->cmap;
 #ifdef CONFIG_VIDEO_BMP_RLE8
 		u32 compression = get_unaligned_le32(&bmp->header.compression);
 		debug("compressed %d %d\n", compression, BMP_BI_RLE8);
 		if (compression == BMP_BI_RLE8) {
 			if (bpix != 16) {
 				/* TODO implement render code for bpix != 16 */
-				printf("Error: only support 16 bpix");
+				printf("Error: only support 16 bpix\n");
 				return -EPROTONOSUPPORT;
 			}
-			video_display_rle8_bitmap(dev, bmp, cmap_base, fb, x,
+			video_display_rle8_bitmap(dev, bmp, priv->cmap, fb, x,
 						  y, width, height);
 			break;
 		}
 #endif
 
-		if (bpix != 16)
-			byte_width = width;
-		else
+		cmap16_base = priv->cmap;
+		cmap32_base = priv->cmap;
+
+		if (bpix == 16)
 			byte_width = width * 2;
+		else if (bpix == 32)
+			byte_width = width * 4;
+		else
+			byte_width = width;
 
 		for (i = 0; i < height; ++i) {
 			WATCHDOG_RESET();
 			for (j = 0; j < width; j++) {
-				if (bpix != 16) {
-					fb_put_byte(&fb, &bmap);
-				} else {
-					*(uint16_t *)fb = cmap_base[*bmap];
-					bmap++;
+				if (bpix == 16) {
+					*(uint16_t *)fb = cmap16_base[*bmap++];
 					fb += sizeof(uint16_t) / sizeof(*fb);
+				} else if (bpix == 32) {
+					*(uint32_t *)fb = cmap32_base[*bmap++];
+					fb += 4;
+				} else {
+					fb_put_byte(&fb, &bmap);
 				}
 			}
 			bmap += (padded_width - width);
diff --git a/include/video.h b/include/video.h
index e7c58e86cb..2f3183f873 100644
--- a/include/video.h
+++ b/include/video.h
@@ -93,7 +93,7 @@ struct video_priv {
 	u32 colour_fg;
 	u32 colour_bg;
 	bool flush_dcache;
-	ushort *cmap;
+	void *cmap;
 	u8 fg_col_idx;
 	u8 bg_col_idx;
 };
-- 
2.17.1



More information about the U-Boot mailing list