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

Message ID 20180112235815.29270-1-xypron.glpk@gmx.de
State New
Delegated to: Anatolij Gustschin
Headers show
Series
  • [U-Boot,1/1] dm: video: Correct color ANSI escape sequence support
Related show

Commit Message

Heinrich Schuchardt Jan. 12, 2018, 11:58 p.m.
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@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(-)

Patch

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 */