uboot-tools/dm-video-enhancements-for-S...

435 lines
12 KiB
Diff

From patchwork Wed Sep 13 22:12:20 2017
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [U-Boot,1/3] dm: video: Fix cache flushes
X-Patchwork-Submitter: Rob Clark <robdclark@gmail.com>
X-Patchwork-Id: 813662
X-Patchwork-Delegate: sjg@chromium.org
Message-Id: <20170913221227.21091-2-robdclark@gmail.com>
To: U-Boot Mailing List <u-boot@lists.denx.de>
Date: Wed, 13 Sep 2017 18:12:20 -0400
From: Rob Clark <robdclark@gmail.com>
List-Id: U-Boot discussion <u-boot.lists.denx.de>
Content can come to screen via putc() and we cannot always rely on
updates ending with a puts(). This is the case with efi_console output
to vidconsole. Fixes corruption with Shell.efi.
Signed-off-by: Rob Clark <robdclark@gmail.com>
---
drivers/video/vidconsole-uclass.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index b5afd72227..e081d5a0ee 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -163,6 +163,7 @@ static void vidconsole_putc(struct stdio_dev *sdev, const char ch)
struct udevice *dev = sdev->priv;
vidconsole_put_char(dev, ch);
+ video_sync(dev->parent);
}
static void vidconsole_puts(struct stdio_dev *sdev, const char *s)
@@ -260,6 +261,8 @@ static int do_video_puts(cmd_tbl_t *cmdtp, int flag, int argc,
for (s = argv[1]; *s; s++)
vidconsole_put_char(dev, *s);
+ video_sync(dev->parent);
+
return 0;
}
From patchwork Wed Sep 13 22:12:21 2017
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [U-Boot,2/3] dm: video: Add basic ANSI escape sequence support
X-Patchwork-Submitter: Rob Clark <robdclark@gmail.com>
X-Patchwork-Id: 813649
X-Patchwork-Delegate: sjg@chromium.org
Message-Id: <20170913221227.21091-3-robdclark@gmail.com>
To: U-Boot Mailing List <u-boot@lists.denx.de>
Date: Wed, 13 Sep 2017 18:12:21 -0400
From: Rob Clark <robdclark@gmail.com>
List-Id: U-Boot discussion <u-boot.lists.denx.de>
Really just the subset that is needed by efi_console. Perhaps more will
be added later, for example color support would be useful to implement
efi_cout_set_attribute().
Signed-off-by: Rob Clark <robdclark@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
drivers/video/Kconfig | 8 +++
drivers/video/vidconsole-uclass.c | 109 ++++++++++++++++++++++++++++++++++++++
drivers/video/video-uclass.c | 4 +-
include/video.h | 7 +++
include/video_console.h | 11 ++++
5 files changed, 136 insertions(+), 3 deletions(-)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 082cc4a528..add156cb70 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -44,6 +44,14 @@ config VIDEO_BPP32
this option, such displays will not be supported and console output
will be empty.
+config VIDEO_ANSI
+ bool "Support ANSI escape sequences in video console"
+ depends on DM_VIDEO
+ default y if DM_VIDEO
+ help
+ Enable ANSI escape sequence decoding for a more fully functional
+ console.
+
config CONSOLE_NORMAL
bool "Support a simple text console"
depends on DM_VIDEO
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index e081d5a0ee..0a88cc0a42 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -9,6 +9,7 @@
*/
#include <common.h>
+#include <linux/ctype.h>
#include <dm.h>
#include <video.h>
#include <video_console.h>
@@ -107,12 +108,120 @@ static void vidconsole_newline(struct udevice *dev)
video_sync(dev->parent);
}
+static char *parsenum(char *s, int *num)
+{
+ char *end;
+ *num = simple_strtol(s, &end, 10);
+ return end;
+}
+
+/*
+ * Process a character while accumulating an escape string. Chars are
+ * accumulated into escape_buf until the end of escape sequence is
+ * found, at which point the sequence is parsed and processed.
+ */
+static void vidconsole_escape_char(struct udevice *dev, char ch)
+{
+ struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
+
+ if (!IS_ENABLED(CONFIG_VIDEO_ANSI))
+ goto error;
+
+ /* Sanity checking for bogus ESC sequences: */
+ if (priv->escape_len >= sizeof(priv->escape_buf))
+ goto error;
+ if (priv->escape_len == 0 && ch != '[')
+ goto error;
+
+ priv->escape_buf[priv->escape_len++] = ch;
+
+ /*
+ * Escape sequences are terminated by a letter, so keep
+ * accumulating until we get one:
+ */
+ if (!isalpha(ch))
+ return;
+
+ /*
+ * clear escape mode first, otherwise things will get highly
+ * surprising if you hit any debug prints that come back to
+ * this console.
+ */
+ priv->escape = 0;
+
+ switch (ch) {
+ case 'H':
+ case 'f': {
+ int row, col;
+ char *s = priv->escape_buf;
+
+ /*
+ * Set cursor position: [%d;%df or [%d;%dH
+ */
+ s++; /* [ */
+ s = parsenum(s, &row);
+ s++; /* ; */
+ s = parsenum(s, &col);
+
+ priv->ycur = row * priv->y_charsize;
+ priv->xcur_frac = priv->xstart_frac +
+ VID_TO_POS(col * priv->x_charsize);
+
+ break;
+ }
+ case 'J': {
+ int mode;
+
+ /*
+ * Clear part/all screen:
+ * [J or [0J - clear screen from cursor down
+ * [1J - clear screen from cursor up
+ * [2J - clear entire screen
+ *
+ * TODO we really only handle entire-screen case, others
+ * probably require some additions to video-uclass (and
+ * are not really needed yet by efi_console)
+ */
+ parsenum(priv->escape_buf + 1, &mode);
+
+ if (mode == 2) {
+ video_clear(dev->parent);
+ video_sync(dev->parent);
+ priv->ycur = 0;
+ priv->xcur_frac = priv->xstart_frac;
+ } else {
+ debug("unsupported clear mode: %d\n", mode);
+ }
+ break;
+ }
+ default:
+ debug("unrecognized escape sequence: %*s\n",
+ priv->escape_len, priv->escape_buf);
+ }
+
+ return;
+
+error:
+ /* something went wrong, just revert to normal mode: */
+ priv->escape = 0;
+ return;
+}
+
int vidconsole_put_char(struct udevice *dev, char ch)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
int ret;
+ if (priv->escape) {
+ vidconsole_escape_char(dev, ch);
+ return 0;
+ }
+
switch (ch) {
+ case '\x1b':
+ priv->escape_len = 0;
+ priv->escape = 1;
+ break;
case '\a':
/* beep */
break;
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index 3036e3a1f2..0163039821 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -87,7 +87,7 @@ int video_reserve(ulong *addrp)
return 0;
}
-static int video_clear(struct udevice *dev)
+void video_clear(struct udevice *dev)
{
struct video_priv *priv = dev_get_uclass_priv(dev);
@@ -100,8 +100,6 @@ static int video_clear(struct udevice *dev)
} else {
memset(priv->fb, priv->colour_bg, priv->fb_size);
}
-
- return 0;
}
/* Flush video activity to the caches */
diff --git a/include/video.h b/include/video.h
index 5b4e78b182..61ff653121 100644
--- a/include/video.h
+++ b/include/video.h
@@ -115,6 +115,13 @@ struct video_ops {
int video_reserve(ulong *addrp);
/**
+ * video_clear() - Clear a device's frame buffer to background color.
+ *
+ * @dev: Device to clear
+ */
+void video_clear(struct udevice *dev);
+
+/**
* video_sync() - Sync a device's frame buffer with its hardware
*
* Some frame buffers are cached or have a secondary frame buffer. This
diff --git a/include/video_console.h b/include/video_console.h
index 26047934da..9dce234bd9 100644
--- a/include/video_console.h
+++ b/include/video_console.h
@@ -29,6 +29,9 @@
* @xsize_frac: Width of the display in fractional units
* @xstart_frac: Left margin for the text console in fractional units
* @last_ch: Last character written to the text console on this line
+ * @escape: TRUE if currently accumulating an ANSI escape sequence
+ * @escape_len: Length of accumulated escape sequence so far
+ * @escape_buf: Buffer to accumulate escape sequence
*/
struct vidconsole_priv {
struct stdio_dev sdev;
@@ -42,6 +45,14 @@ struct vidconsole_priv {
int xsize_frac;
int xstart_frac;
int last_ch;
+ /*
+ * ANSI escape sequences are accumulated character by character,
+ * starting after the ESC char (0x1b) until the entire sequence
+ * is consumed at which point it is acted upon.
+ */
+ int escape;
+ int escape_len;
+ char escape_buf[32];
};
/**
From patchwork Wed Sep 13 22:12:22 2017
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [U-Boot,3/3] dm: video: Add color ANSI escape sequence support
X-Patchwork-Submitter: Rob Clark <robdclark@gmail.com>
X-Patchwork-Id: 813661
X-Patchwork-Delegate: sjg@chromium.org
Message-Id: <20170913221227.21091-4-robdclark@gmail.com>
To: U-Boot Mailing List <u-boot@lists.denx.de>
Date: Wed, 13 Sep 2017 18:12:22 -0400
From: Rob Clark <robdclark@gmail.com>
List-Id: U-Boot discussion <u-boot.lists.denx.de>
Note that this doesn't differentiate (due to lack of information in
video_priv) between different possible component orders for 32bpp.
But the main user at this point is efi_loader, and GOP expects xBGR
so any video drivers that this is incorrect for already have problems.
(Also, conveniently, this matches what simple-framebuffer bindings
expect for kernels that use the simple-framebuffer DT binding to
take over the bootloader display.)
Signed-off-by: Rob Clark <robdclark@gmail.com>
---
drivers/video/vidconsole-uclass.c | 94 +++++++++++++++++++++++++++++++++++++++
1 file changed, 94 insertions(+)
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index 0a88cc0a42..820540b1bf 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -108,6 +108,41 @@ static void vidconsole_newline(struct udevice *dev)
video_sync(dev->parent);
}
+static const struct {
+ unsigned r;
+ unsigned g;
+ unsigned b;
+} colors[] = {
+ { 0x00, 0x00, 0x00 }, /* black */
+ { 0xff, 0x00, 0x00 }, /* red */
+ { 0x00, 0xff, 0x00 }, /* green */
+ { 0xff, 0xff, 0x00 }, /* yellow */
+ { 0x00, 0x00, 0xff }, /* blue */
+ { 0xff, 0x00, 0xff }, /* magenta */
+ { 0x00, 0xff, 0xff }, /* cyan */
+ { 0xff, 0xff, 0xff }, /* white */
+};
+
+static void set_color(struct video_priv *priv, unsigned idx, unsigned *c)
+{
+ switch (priv->bpix) {
+ case VIDEO_BPP16:
+ *c = ((colors[idx].r >> 3) << 0) |
+ ((colors[idx].g >> 2) << 5) |
+ ((colors[idx].b >> 3) << 11);
+ break;
+ case VIDEO_BPP32:
+ *c = 0xff000000 |
+ (colors[idx].r << 0) |
+ (colors[idx].g << 8) |
+ (colors[idx].b << 16);
+ break;
+ default:
+ /* unsupported, leave current color in place */
+ break;
+ }
+}
+
static char *parsenum(char *s, int *num)
{
char *end;
@@ -194,6 +229,65 @@ static void vidconsole_escape_char(struct udevice *dev, char ch)
}
break;
}
+ case 'm': {
+ struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+ char *s = priv->escape_buf;
+ char *end = &priv->escape_buf[priv->escape_len];
+
+ /*
+ * Set graphics mode: [%d;...;%dm
+ *
+ * Currently only supports the color attributes:
+ *
+ * Foreground Colors:
+ *
+ * 30 Black
+ * 31 Red
+ * 32 Green
+ * 33 Yellow
+ * 34 Blue
+ * 35 Magenta
+ * 36 Cyan
+ * 37 White
+ *
+ * Background Colors:
+ *
+ * 40 Black
+ * 41 Red
+ * 42 Green
+ * 43 Yellow
+ * 44 Blue
+ * 45 Magenta
+ * 46 Cyan
+ * 47 White
+ */
+
+ s++; /* [ */
+ while (s < end) {
+ int val;
+
+ s = parsenum(s, &val);
+ s++;
+
+ switch (val) {
+ case 30 ... 37:
+ /* fg color */
+ set_color(vid_priv, val - 30,
+ (unsigned *)&vid_priv->colour_fg);
+ break;
+ case 40 ... 47:
+ /* bg color */
+ set_color(vid_priv, val - 40,
+ (unsigned *)&vid_priv->colour_bg);
+ break;
+ default:
+ /* unknown/unsupported */
+ break;
+ }
+ }
+
+ break;
+ }
default:
debug("unrecognized escape sequence: %*s\n",
priv->escape_len, priv->escape_buf);