[U-Boot] [PATCH 1/1] dm: video: Correct color ANSI escape sequence support

Heinrich Schuchardt xypron.glpk at gmx.de
Fri Jan 12 23:58:15 UTC 2018


Support increased intensity (bold).
Get RGB sequence in pixels right (swap blue and red).
Do not set reserved bits.
Use u32 instead of unsigned for color bit mask.

qemu-system-i386 -display sdl -vga virtio and
qemu-system-i386 -display sdl -vga cirrus
now display the same colors as
qemu-system-i386 -nographic

Testing is possible via

	setenv efi_selftest test output
	bootefi selftest

Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
---
 drivers/video/vidconsole-uclass.c | 53 ++++++++++++++++++++++++++-------------
 drivers/video/video-uclass.c      | 38 +++++++++++++++++++++++++---
 include/video.h                   |  6 +++--
 3 files changed, 74 insertions(+), 23 deletions(-)

diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index 5f63c12d6c..79c7f2113f 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -114,28 +114,35 @@ static const struct {
 	unsigned b;
 } colors[] = {
 	{ 0x00, 0x00, 0x00 },  /* black */
-	{ 0xff, 0x00, 0x00 },  /* red */
-	{ 0x00, 0xff, 0x00 },  /* green */
+	{ 0xc0, 0x00, 0x00 },  /* red */
+	{ 0x00, 0xc0, 0x00 },  /* green */
+	{ 0xc0, 0x60, 0x00 },  /* brown */
+	{ 0x00, 0x00, 0xc0 },  /* blue */
+	{ 0xc0, 0x00, 0xc0 },  /* magenta */
+	{ 0x00, 0xc0, 0xc0 },  /* cyan */
+	{ 0xc0, 0xc0, 0xc0 },  /* light gray */
+	{ 0x80, 0x80, 0x80 },  /* gray */
+	{ 0xff, 0x00, 0x00 },  /* bright red */
+	{ 0x00, 0xff, 0x00 },  /* bright green */
 	{ 0xff, 0xff, 0x00 },  /* yellow */
-	{ 0x00, 0x00, 0xff },  /* blue */
-	{ 0xff, 0x00, 0xff },  /* magenta */
-	{ 0x00, 0xff, 0xff },  /* cyan */
+	{ 0x00, 0x00, 0xff },  /* bright blue */
+	{ 0xff, 0x00, 0xff },  /* bright magenta */
+	{ 0x00, 0xff, 0xff },  /* bright cyan */
 	{ 0xff, 0xff, 0xff },  /* white */
 };
 
-static void set_color(struct video_priv *priv, unsigned idx, unsigned *c)
+static void set_color(struct video_priv *priv, unsigned int idx, u32 *c)
 {
 	switch (priv->bpix) {
 	case VIDEO_BPP16:
-		*c = ((colors[idx].r >> 3) << 0) |
-		     ((colors[idx].g >> 2) << 5) |
-		     ((colors[idx].b >> 3) << 11);
+		*c = ((colors[idx].r >> 3) << 11) |
+		     ((colors[idx].g >> 2) <<  5) |
+		     ((colors[idx].b >> 3) <<  0);
 		break;
 	case VIDEO_BPP32:
-		*c = 0xff000000 |
-		     (colors[idx].r << 0) |
-		     (colors[idx].g << 8) |
-		     (colors[idx].b << 16);
+		*c = (colors[idx].r << 16) |
+		     (colors[idx].g <<  8) |
+		     (colors[idx].b <<  0);
 		break;
 	default:
 		/* unsupported, leave current color in place */
@@ -270,18 +277,30 @@ static void vidconsole_escape_char(struct udevice *dev, char ch)
 			s++;
 
 			switch (val) {
+			case 0:
+				/* all attributes off */
+				vid_priv->fg &= 7;
+				break;
+			case 1:
+				/* bold */
+				vid_priv->fg |= 8;
+				set_color(vid_priv, vid_priv->fg,
+					  (unsigned int *)&vid_priv->colour_fg);
+				break;
 			case 30 ... 37:
 				/* fg color */
-				set_color(vid_priv, val - 30,
-					  (unsigned *)&vid_priv->colour_fg);
+				vid_priv->fg &= ~7;
+				vid_priv->fg |= val - 30;
+				set_color(vid_priv, vid_priv->fg,
+					  &vid_priv->colour_fg);
 				break;
 			case 40 ... 47:
 				/* bg color */
 				set_color(vid_priv, val - 40,
-					  (unsigned *)&vid_priv->colour_bg);
+					  &vid_priv->colour_bg);
 				break;
 			default:
-				/* unknown/unsupported */
+				/* ignore unsupported SGR parameter */
 				break;
 			}
 		}
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index dcaceed42c..8dfb6b1902 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -91,14 +91,26 @@ void video_clear(struct udevice *dev)
 {
 	struct video_priv *priv = dev_get_uclass_priv(dev);
 
-	if (priv->bpix == VIDEO_BPP32) {
+	switch (priv->bpix) {
+	case VIDEO_BPP16: {
+		u16 *ppix = priv->fb;
+		u16 *end = priv->fb + priv->fb_size;
+
+		while (ppix < end)
+			*ppix++ = priv->colour_bg;
+		break;
+	}
+	case VIDEO_BPP32: {
 		u32 *ppix = priv->fb;
 		u32 *end = priv->fb + priv->fb_size;
 
 		while (ppix < end)
 			*ppix++ = priv->colour_bg;
-	} else {
+		break;
+	}
+	default:
 		memset(priv->fb, priv->colour_bg, priv->fb_size);
+		break;
 	}
 }
 
@@ -193,9 +205,27 @@ static int video_post_probe(struct udevice *dev)
 
 	/* Set up colours - we could in future support other colours */
 #ifdef CONFIG_SYS_WHITE_ON_BLACK
-	priv->colour_fg = 0xffffff;
+	switch (priv->bpix) {
+	case VIDEO_BPP16:
+		priv->colour_fg = 0xc618;
+		break;
+	case VIDEO_BPP32:
+		priv->colour_fg = 0xc0c0c0;
+		break;
+	default:
+		priv->colour_fg = 0xffffff;
+		break;
+	}
+	priv->fg = 7;
 #else
-	priv->colour_bg = 0xffffff;
+	switch (priv->bpix) {
+	case VIDEO_BPP16:
+		priv->colour_bg = 0xcffff;
+		break;
+	default:
+		priv->colour_bg = 0xffffff;
+		break;
+	}
 #endif
 
 	if (!CONFIG_IS_ENABLED(NO_FB_CLEAR))
diff --git a/include/video.h b/include/video.h
index 61ff653121..c02e0315a7 100644
--- a/include/video.h
+++ b/include/video.h
@@ -67,6 +67,7 @@ enum video_log2_bpp {
  * @flush_dcache:	true to enable flushing of the data cache after
  *		the LCD is updated
  * @cmap:	Colour map for 8-bit-per-pixel displays
+ * @fg:		Foreground color code (bit 3 = bold, bit 0-2 = color)
  */
 struct video_priv {
 	/* Things set up by the driver: */
@@ -84,10 +85,11 @@ struct video_priv {
 	void *fb;
 	int fb_size;
 	int line_length;
-	int colour_fg;
-	int colour_bg;
+	u32 colour_fg;
+	u32 colour_bg;
 	bool flush_dcache;
 	ushort *cmap;
+	u8 fg;
 };
 
 /* Placeholder - there are no video operations at present */
-- 
2.15.1



More information about the U-Boot mailing list