[PATCH 00/16] video: Enhancements to Truetype console

This series includes some minor enhancements to the Truetype console to allow it to support multiple fonts and sizes at the same time. This is useful for displays where the title needs to be in a larger font than the rest of the text on the display.
The fonts must still be compiled into U-Boot, but now it is possible to change fonts as needed.
Some other minor fixes and tweaks are included as well.
This is mostly in service of the upcoming VBE boot menu which needs to make better use of fonts.
Simon Glass (16): video: Move console colours to the video uclass video: Provide a function to set the cursor position video: Use vidconsole_put_string() to write a string video: Move the console commands to cmd/ video: Move and rename DM_HX8238D option video: Allow filling the display with a colour video: Add function to obtain the U-Boot logo video: Tidy up the check for valid fonts video: Refactor to allow more than one font size video: Record the truetype font name video: Add a function to select the truetype metrics video: Add a way to change the font name and size video: Enable the cls command by default video: Add commands to list and change fonts video: Add a function to get the dimensions of a BMP image video: Add a way to get the default font height
arch/arm/mach-omap2/am33xx/Kconfig | 2 +- cmd/Kconfig | 14 +- cmd/Makefile | 3 + cmd/font.c | 81 +++++++++ cmd/video.c | 73 ++++++++ configs/sandbox_defconfig | 1 + doc/usage/cmd/font.rst | 52 ++++++ doc/usage/index.rst | 1 + drivers/video/Kconfig | 43 +++-- drivers/video/Makefile | 2 +- drivers/video/console_truetype.c | 265 +++++++++++++++++++++++------ drivers/video/vidconsole-uclass.c | 145 ++-------------- drivers/video/video-uclass.c | 102 ++++++++++- drivers/video/video_bmp.c | 16 +- include/test/suites.h | 1 + include/video.h | 75 +++++++- include/video_console.h | 64 +++---- test/cmd/Makefile | 1 + test/cmd/font.c | 77 +++++++++ test/cmd_ut.c | 6 + 20 files changed, 777 insertions(+), 247 deletions(-) create mode 100644 cmd/font.c create mode 100644 cmd/video.c create mode 100644 doc/usage/cmd/font.rst create mode 100644 test/cmd/font.c

At present these are attached to vidconsole which means that the video uclass requires that a console is enabled. This is not the intention. The colours are a reasonable way of indexing common colours in any case, so move them to the video uclass instead.
Rename vid_console_color() to video_index_to_colour() now that it is more generic. Also fix the inconsistent spelling in these functions.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/vidconsole-uclass.c | 74 +++---------------------------- drivers/video/video-uclass.c | 66 ++++++++++++++++++++++++++- include/video.h | 35 +++++++++++++++ include/video_console.h | 37 ---------------- 4 files changed, 104 insertions(+), 108 deletions(-)
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index f42db40d4cd..f67027c67be 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -19,15 +19,6 @@ #include <video_font.h> /* Bitmap font for code page 437 */ #include <linux/ctype.h>
-/* - * Structure to describe a console color - */ -struct vid_rgb { - u32 r; - u32 g; - u32 b; -}; - /* By default we scroll by a single line */ #ifndef CONFIG_CONSOLE_SCROLL_LINES #define CONFIG_CONSOLE_SCROLL_LINES 1 @@ -124,61 +115,6 @@ static void vidconsole_newline(struct udevice *dev) } }
-static const struct vid_rgb colors[VID_COLOR_COUNT] = { - { 0x00, 0x00, 0x00 }, /* black */ - { 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 }, /* bright blue */ - { 0xff, 0x00, 0xff }, /* bright magenta */ - { 0x00, 0xff, 0xff }, /* bright cyan */ - { 0xff, 0xff, 0xff }, /* white */ -}; - -u32 vid_console_color(struct video_priv *priv, unsigned int idx) -{ - switch (priv->bpix) { - case VIDEO_BPP16: - if (CONFIG_IS_ENABLED(VIDEO_BPP16)) { - return ((colors[idx].r >> 3) << 11) | - ((colors[idx].g >> 2) << 5) | - ((colors[idx].b >> 3) << 0); - } - break; - case VIDEO_BPP32: - if (CONFIG_IS_ENABLED(VIDEO_BPP32)) { - if (priv->format == VIDEO_X2R10G10B10) - return (colors[idx].r << 22) | - (colors[idx].g << 12) | - (colors[idx].b << 2); - else - return (colors[idx].r << 16) | - (colors[idx].g << 8) | - (colors[idx].b << 0); - } - break; - default: - break; - } - - /* - * For unknown bit arrangements just support - * black and white. - */ - if (idx) - return 0xffffff; /* white */ - - return 0x000000; /* black */ -} - static char *parsenum(char *s, int *num) { char *end; @@ -441,28 +377,28 @@ static void vidconsole_escape_char(struct udevice *dev, char ch) case 1: /* bold */ vid_priv->fg_col_idx |= 8; - vid_priv->colour_fg = vid_console_color( + vid_priv->colour_fg = video_index_to_colour( vid_priv, vid_priv->fg_col_idx); break; case 7: /* reverse video */ - vid_priv->colour_fg = vid_console_color( + vid_priv->colour_fg = video_index_to_colour( vid_priv, vid_priv->bg_col_idx); - vid_priv->colour_bg = vid_console_color( + vid_priv->colour_bg = video_index_to_colour( vid_priv, vid_priv->fg_col_idx); break; case 30 ... 37: /* foreground color */ vid_priv->fg_col_idx &= ~7; vid_priv->fg_col_idx |= val - 30; - vid_priv->colour_fg = vid_console_color( + vid_priv->colour_fg = video_index_to_colour( vid_priv, vid_priv->fg_col_idx); break; case 40 ... 47: /* background color, also mask the bold bit */ vid_priv->bg_col_idx &= ~0xf; vid_priv->bg_col_idx |= val - 40; - vid_priv->colour_bg = vid_console_color( + vid_priv->colour_bg = video_index_to_colour( vid_priv, vid_priv->bg_col_idx); break; default: diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index 01e8af5ac67..b258a8a00fc 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -64,6 +64,13 @@ 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); @@ -154,6 +161,61 @@ int video_clear(struct udevice *dev) return video_sync(dev, false); }
+static const struct vid_rgb colours[VID_COLOUR_COUNT] = { + { 0x00, 0x00, 0x00 }, /* black */ + { 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 }, /* bright blue */ + { 0xff, 0x00, 0xff }, /* bright magenta */ + { 0x00, 0xff, 0xff }, /* bright cyan */ + { 0xff, 0xff, 0xff }, /* white */ +}; + +u32 video_index_to_colour(struct video_priv *priv, unsigned int idx) +{ + switch (priv->bpix) { + 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); + } + break; + case VIDEO_BPP32: + if (CONFIG_IS_ENABLED(VIDEO_BPP32)) { + if (priv->format == VIDEO_X2R10G10B10) + return (colours[idx].r << 22) | + (colours[idx].g << 12) | + (colours[idx].b << 2); + else + return (colours[idx].r << 16) | + (colours[idx].g << 8) | + (colours[idx].b << 0); + } + break; + default: + break; + } + + /* + * For unknown bit arrangements just support + * black and white. + */ + if (idx) + return 0xffffff; /* white */ + + return 0x000000; /* black */ +} + void video_set_default_colors(struct udevice *dev, bool invert) { struct video_priv *priv = dev_get_uclass_priv(dev); @@ -176,8 +238,8 @@ void video_set_default_colors(struct udevice *dev, bool invert) } priv->fg_col_idx = fore; priv->bg_col_idx = back; - priv->colour_fg = vid_console_color(priv, fore); - priv->colour_bg = vid_console_color(priv, back); + priv->colour_fg = video_index_to_colour(priv, fore); + priv->colour_bg = video_index_to_colour(priv, back); }
/* Flush video activity to the caches */ diff --git a/include/video.h b/include/video.h index 43e2c899778..1c30aea73c0 100644 --- a/include/video.h +++ b/include/video.h @@ -131,6 +131,41 @@ struct video_ops {
#define video_get_ops(dev) ((struct video_ops *)(dev)->driver->ops)
+/** enum colour_idx - the 16 colors supported by consoles */ +enum colour_idx { + VID_BLACK = 0, + VID_RED, + VID_GREEN, + VID_BROWN, + VID_BLUE, + VID_MAGENTA, + VID_CYAN, + VID_LIGHT_GRAY, + VID_GRAY, + VID_LIGHT_RED, + VID_LIGHT_GREEN, + VID_YELLOW, + VID_LIGHT_BLUE, + VID_LIGHT_MAGENTA, + VID_LIGHT_CYAN, + VID_WHITE, + + VID_COLOUR_COUNT +}; + +/** + * video_index_to_colour() - convert a color code to a pixel's internal + * representation + * + * The caller has to guarantee that the color index is less than + * VID_COLOR_COUNT. + * + * @priv private data of the console device + * @idx color index + * Return: color value + */ +u32 video_index_to_colour(struct video_priv *priv, unsigned int idx); + /** * video_reserve() - Reserve frame-buffer memory for video devices * diff --git a/include/video_console.h b/include/video_console.h index 5921767fbf0..72edd419191 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -15,30 +15,6 @@ struct video_priv; #define VID_TO_PIXEL(x) ((x) / VID_FRAC_DIV) #define VID_TO_POS(x) ((x) * VID_FRAC_DIV)
-/* - * The 16 colors supported by the console - */ -enum color_idx { - VID_BLACK = 0, - VID_RED, - VID_GREEN, - VID_BROWN, - VID_BLUE, - VID_MAGENTA, - VID_CYAN, - VID_LIGHT_GRAY, - VID_GRAY, - VID_LIGHT_RED, - VID_LIGTH_GREEN, - VID_YELLOW, - VID_LIGHT_BLUE, - VID_LIGHT_MAGENTA, - VID_LIGHT_CYAN, - VID_WHITE, - - VID_COLOR_COUNT -}; - /** * struct vidconsole_priv - uclass-private data about a console device * @@ -243,19 +219,6 @@ int vidconsole_put_string(struct udevice *dev, const char *str); void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row);
-/** - * vid_console_color() - convert a color code to a pixel's internal - * representation - * - * The caller has to guarantee that the color index is less than - * VID_COLOR_COUNT. - * - * @priv private data of the console device - * @idx color index - * Return: color value - */ -u32 vid_console_color(struct video_priv *priv, unsigned int idx); - #ifdef CONFIG_VIDEO_COPY /** * vidconsole_sync_copy() - Sync back to the copy framebuffer

Add an exported function which allows the cursor position to be set to pixel granularity. Make use of this in the existing code.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/vidconsole-uclass.c | 18 +++++++++++++----- include/video_console.h | 12 ++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index f67027c67be..53263580e3b 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -122,6 +122,15 @@ static char *parsenum(char *s, int *num) return end; }
+void vidconsole_set_cursor_pos(struct udevice *dev, int x, int y) +{ + struct vidconsole_priv *priv = dev_get_uclass_priv(dev); + + priv->xcur_frac = VID_TO_POS(x); + priv->xstart_frac = priv->xcur_frac; + priv->ycur = y; +} + /** * set_cursor_position() - set cursor position * @@ -614,12 +623,11 @@ void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row) struct vidconsole_priv *priv = dev_get_uclass_priv(dev); struct udevice *vid_dev = dev->parent; struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev); + short x, y;
- col *= priv->x_charsize; - row *= priv->y_charsize; - priv->xcur_frac = VID_TO_POS(min_t(short, col, vid_priv->xsize - 1)); - priv->xstart_frac = priv->xcur_frac; - priv->ycur = min_t(short, row, vid_priv->ysize - 1); + x = min_t(short, col * priv->x_charsize, vid_priv->xsize - 1); + y = min_t(short, row * priv->y_charsize, vid_priv->ysize - 1); + vidconsole_set_cursor_pos(dev, x, y); }
static int do_video_setcursor(struct cmd_tbl *cmdtp, int flag, int argc, diff --git a/include/video_console.h b/include/video_console.h index 72edd419191..76c4b10acf6 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -219,6 +219,18 @@ int vidconsole_put_string(struct udevice *dev, const char *str); void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row);
+/** + * vidconsole_set_cursor_pos() - set cursor position + * + * The cursor is set to the new position and the start-of-line information is + * updated to the same position, so that a newline will return to @x + * + * @dev: video console device to update + * @x: x position from left in pixels + * @y: y position from top in pixels + */ +void vidconsole_set_cursor_pos(struct udevice *dev, int x, int y); + #ifdef CONFIG_VIDEO_COPY /** * vidconsole_sync_copy() - Sync back to the copy framebuffer

Use the existing function rather that duplicating the code. Also fix up the missing error handling.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/vidconsole-uclass.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 53263580e3b..d5667191e0a 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -652,17 +652,18 @@ static int do_video_puts(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct udevice *dev; - const char *s; + int ret;
if (argc != 2) return CMD_RET_USAGE;
if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev)) return CMD_RET_FAILURE; - for (s = argv[1]; *s; s++) - vidconsole_put_char(dev, *s); + ret = vidconsole_put_string(dev, argv[1]); + if (!ret) + ret = video_sync(dev->parent, false);
- return video_sync(dev->parent, false); + return ret ? CMD_RET_FAILURE : 0; }
U_BOOT_CMD(

Move these commands and the implementation to the cmd/ directory, which is where most commands are kept.
Signed-off-by: Simon Glass sjg@chromium.org ---
cmd/Kconfig | 12 +++++ cmd/Makefile | 2 + cmd/video.c | 73 +++++++++++++++++++++++++++++++ drivers/video/Kconfig | 8 ---- drivers/video/vidconsole-uclass.c | 62 -------------------------- 5 files changed, 87 insertions(+), 70 deletions(-) create mode 100644 cmd/video.c
diff --git a/cmd/Kconfig b/cmd/Kconfig index bfa12ce12a7..a512a55c031 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2137,6 +2137,18 @@ config CMD_UUID The two commands are very similar except for the endianness of the output.
+config CMD_VIDCONSOLE + bool "lcdputs and setcurs" + depends on DM_VIDEO + default y + help + Enabling this will provide 'setcurs' and 'lcdputs' commands which + support cursor positioning and drawing strings on the video + console (framebuffer). + + The name 'lcdputs' is a bit of a misnomer, but so named because the + video device is often an LCD. + endmenu
source "cmd/ti/Kconfig" diff --git a/cmd/Makefile b/cmd/Makefile index cf6ce1bd6fd..86a77805f88 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -176,6 +176,8 @@ obj-$(CONFIG_CMD_WDT) += wdt.o obj-$(CONFIG_CMD_LZMADEC) += lzmadec.o obj-$(CONFIG_CMD_UFS) += ufs.o obj-$(CONFIG_CMD_USB) += usb.o disk.o +obj-$(CONFIG_CMD_VIDCONSOLE) += video.o + obj-$(CONFIG_CMD_FASTBOOT) += fastboot.o obj-$(CONFIG_CMD_FS_UUID) += fs_uuid.o
diff --git a/cmd/video.c b/cmd/video.c new file mode 100644 index 00000000000..e6b0b553136 --- /dev/null +++ b/cmd/video.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * video commands + * + * Copyright 2022 Google LLC + * Written by Simon Glass sjg@chromium.org + */ + +#include <common.h> +#include <command.h> +#include <dm.h> +#include <video.h> +#include <video_console.h> + +void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row) +{ + struct vidconsole_priv *priv = dev_get_uclass_priv(dev); + struct udevice *vid_dev = dev->parent; + struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev); + short x, y; + + x = min_t(short, col * priv->x_charsize, vid_priv->xsize - 1); + y = min_t(short, row * priv->y_charsize, vid_priv->ysize - 1); + vidconsole_set_cursor_pos(dev, x, y); +} + +static int do_video_setcursor(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + unsigned int col, row; + struct udevice *dev; + + if (argc != 3) + return CMD_RET_USAGE; + + if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev)) + return CMD_RET_FAILURE; + col = dectoul(argv[1], NULL); + row = dectoul(argv[2], NULL); + vidconsole_position_cursor(dev, col, row); + + return 0; +} + +static int do_video_puts(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct udevice *dev; + int ret; + + if (argc != 2) + return CMD_RET_USAGE; + + if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev)) + return CMD_RET_FAILURE; + ret = vidconsole_put_string(dev, argv[1]); + if (!ret) + ret = video_sync(dev->parent, false); + + return ret ? CMD_RET_FAILURE : 0; +} + +U_BOOT_CMD( + setcurs, 3, 1, do_video_setcursor, + "set cursor position within screen", + " <col> <row> in character" +); + +U_BOOT_CMD( + lcdputs, 2, 1, do_video_puts, + "print string on video framebuffer", + " <string>" +); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 4ecc158c460..c9fc4a3a583 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -85,14 +85,6 @@ config BACKLIGHT_GPIO it understands the standard device tree (leds/backlight/gpio-backlight.txt)
-config CMD_VIDCONSOLE - bool "Enable vidconsole commands lcdputs and setcurs" - depends on DM_VIDEO - default y - help - Enabling this will provide 'setcurs' and 'lcdputs' commands which - support cursor positioning and drawing strings on video framebuffer. - config VIDEO_BPP8 bool "Support 8-bit-per-pixel displays" depends on DM_VIDEO diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index d5667191e0a..17d4f2f6d08 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -616,65 +616,3 @@ int vidconsole_memmove(struct udevice *dev, void *dst, const void *src, return vidconsole_sync_copy(dev, dst, dst + size); } #endif - -#if CONFIG_IS_ENABLED(CMD_VIDCONSOLE) -void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row) -{ - struct vidconsole_priv *priv = dev_get_uclass_priv(dev); - struct udevice *vid_dev = dev->parent; - struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev); - short x, y; - - x = min_t(short, col * priv->x_charsize, vid_priv->xsize - 1); - y = min_t(short, row * priv->y_charsize, vid_priv->ysize - 1); - vidconsole_set_cursor_pos(dev, x, y); -} - -static int do_video_setcursor(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) -{ - unsigned int col, row; - struct udevice *dev; - - if (argc != 3) - return CMD_RET_USAGE; - - if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev)) - return CMD_RET_FAILURE; - col = dectoul(argv[1], NULL); - row = dectoul(argv[2], NULL); - vidconsole_position_cursor(dev, col, row); - - return 0; -} - -static int do_video_puts(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) -{ - struct udevice *dev; - int ret; - - if (argc != 2) - return CMD_RET_USAGE; - - if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev)) - return CMD_RET_FAILURE; - ret = vidconsole_put_string(dev, argv[1]); - if (!ret) - ret = video_sync(dev->parent, false); - - return ret ? CMD_RET_FAILURE : 0; -} - -U_BOOT_CMD( - setcurs, 3, 1, do_video_setcursor, - "set cursor position within screen", - " <col> <row> in character" -); - -U_BOOT_CMD( - lcdputs, 2, 1, do_video_puts, - "print string on video framebuffer", - " <string>" -); -#endif /* CONFIG_IS_ENABLED(CMD_VIDCONSOLE) */

Hi Simon,
On Thu, 6 Oct 2022 at 17:36, Simon Glass sjg@chromium.org wrote:
Move these commands and the implementation to the cmd/ directory, which is where most commands are kept.
Signed-off-by: Simon Glass sjg@chromium.org
cmd/Kconfig | 12 +++++ cmd/Makefile | 2 + cmd/video.c | 73 +++++++++++++++++++++++++++++++ drivers/video/Kconfig | 8 ---- drivers/video/vidconsole-uclass.c | 62 -------------------------- 5 files changed, 87 insertions(+), 70 deletions(-) create mode 100644 cmd/video.c
diff --git a/cmd/Kconfig b/cmd/Kconfig index bfa12ce12a7..a512a55c031 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2137,6 +2137,18 @@ config CMD_UUID The two commands are very similar except for the endianness of the output.
+config CMD_VIDCONSOLE
bool "lcdputs and setcurs"
depends on DM_VIDEO
default y
help
Enabling this will provide 'setcurs' and 'lcdputs' commands which
support cursor positioning and drawing strings on the video
console (framebuffer).
The name 'lcdputs' is a bit of a misnomer, but so named because the
video device is often an LCD.
endmenu
source "cmd/ti/Kconfig" diff --git a/cmd/Makefile b/cmd/Makefile index cf6ce1bd6fd..86a77805f88 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -176,6 +176,8 @@ obj-$(CONFIG_CMD_WDT) += wdt.o obj-$(CONFIG_CMD_LZMADEC) += lzmadec.o obj-$(CONFIG_CMD_UFS) += ufs.o obj-$(CONFIG_CMD_USB) += usb.o disk.o +obj-$(CONFIG_CMD_VIDCONSOLE) += video.o
obj-$(CONFIG_CMD_FASTBOOT) += fastboot.o obj-$(CONFIG_CMD_FS_UUID) += fs_uuid.o
diff --git a/cmd/video.c b/cmd/video.c new file mode 100644 index 00000000000..e6b0b553136 --- /dev/null +++ b/cmd/video.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- video commands
- Copyright 2022 Google LLC
- Written by Simon Glass sjg@chromium.org
- */
+#include <common.h> +#include <command.h> +#include <dm.h> +#include <video.h> +#include <video_console.h>
+void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row) +{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
struct udevice *vid_dev = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
short x, y;
x = min_t(short, col * priv->x_charsize, vid_priv->xsize - 1);
y = min_t(short, row * priv->y_charsize, vid_priv->ysize - 1);
vidconsole_set_cursor_pos(dev, x, y);
+}
+static int do_video_setcursor(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
unsigned int col, row;
struct udevice *dev;
if (argc != 3)
return CMD_RET_USAGE;
if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev))
return CMD_RET_FAILURE;
col = dectoul(argv[1], NULL);
row = dectoul(argv[2], NULL);
vidconsole_position_cursor(dev, col, row);
return 0;
+}
+static int do_video_puts(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
struct udevice *dev;
int ret;
if (argc != 2)
return CMD_RET_USAGE;
if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev))
return CMD_RET_FAILURE;
ret = vidconsole_put_string(dev, argv[1]);
if (!ret)
ret = video_sync(dev->parent, false);
return ret ? CMD_RET_FAILURE : 0;
+}
+U_BOOT_CMD(
setcurs, 3, 1, do_video_setcursor,
"set cursor position within screen",
" <col> <row> in character"
+);
+U_BOOT_CMD(
lcdputs, 2, 1, do_video_puts,
"print string on video framebuffer",
" <string>"
+); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 4ecc158c460..c9fc4a3a583 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -85,14 +85,6 @@ config BACKLIGHT_GPIO it understands the standard device tree (leds/backlight/gpio-backlight.txt)
-config CMD_VIDCONSOLE
bool "Enable vidconsole commands lcdputs and setcurs"
depends on DM_VIDEO
default y
help
Enabling this will provide 'setcurs' and 'lcdputs' commands which
support cursor positioning and drawing strings on video framebuffer.
config VIDEO_BPP8 bool "Support 8-bit-per-pixel displays" depends on DM_VIDEO diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index d5667191e0a..17d4f2f6d08 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -616,65 +616,3 @@ int vidconsole_memmove(struct udevice *dev, void *dst, const void *src, return vidconsole_sync_copy(dev, dst, dst + size); } #endif
-#if CONFIG_IS_ENABLED(CMD_VIDCONSOLE) -void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row) -{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
struct udevice *vid_dev = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
short x, y;
x = min_t(short, col * priv->x_charsize, vid_priv->xsize - 1);
y = min_t(short, row * priv->y_charsize, vid_priv->ysize - 1);
vidconsole_set_cursor_pos(dev, x, y);
-}
-static int do_video_setcursor(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
-{
unsigned int col, row;
struct udevice *dev;
if (argc != 3)
return CMD_RET_USAGE;
if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev))
return CMD_RET_FAILURE;
col = dectoul(argv[1], NULL);
row = dectoul(argv[2], NULL);
vidconsole_position_cursor(dev, col, row);
return 0;
-}
-static int do_video_puts(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
-{
struct udevice *dev;
int ret;
if (argc != 2)
return CMD_RET_USAGE;
if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev))
return CMD_RET_FAILURE;
ret = vidconsole_put_string(dev, argv[1]);
if (!ret)
ret = video_sync(dev->parent, false);
return ret ? CMD_RET_FAILURE : 0;
-}
-U_BOOT_CMD(
setcurs, 3, 1, do_video_setcursor,
"set cursor position within screen",
" <col> <row> in character"
-);
-U_BOOT_CMD(
lcdputs, 2, 1, do_video_puts,
"print string on video framebuffer",
" <string>"
-);
-#endif /* CONFIG_IS_ENABLED(CMD_VIDCONSOLE) */
2.38.0.rc1.362.ged0d419d3c-goog
Acked-by: Ilias Apalodimas ilias.apalodimas@linaro.org

This is actually a panel, not a video device. Rename the option, move it into the right place and make it depend on PANEL.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/arm/mach-omap2/am33xx/Kconfig | 2 +- drivers/video/Kconfig | 20 ++++++++++---------- drivers/video/Makefile | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/arch/arm/mach-omap2/am33xx/Kconfig b/arch/arm/mach-omap2/am33xx/Kconfig index 987ab367ece..25e97cfc386 100644 --- a/arch/arm/mach-omap2/am33xx/Kconfig +++ b/arch/arm/mach-omap2/am33xx/Kconfig @@ -95,7 +95,7 @@ config TARGET_AM335X_GUARDIAN select DM_SERIAL select DM_GPIO select DM_VIDEO - select DM_PANEL_HX8238D + select PANEL_HX8238D
config TARGET_AM335X_SL50 bool "Support am335x_sl50" diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index c9fc4a3a583..44ab9e708f5 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -163,16 +163,6 @@ config CONSOLE_TRUETYPE With this option you can adjust the text size and use a variety of fonts. Note that this is noticeably slower than with normal console.
-config DM_PANEL_HX8238D - bool "Enable Himax HX-8238D LCD driver" - depends on DM_VIDEO - help - Support for HX-8238D LCD Panel - The HX8238-D is a single chip controller and driver LSI that - integrates the power circuit. - It can drive a maximum 960x240 dot graphics on a-TFT panel - displays in 16M colors with dithering. - config CONSOLE_TRUETYPE_SIZE int "TrueType font size" depends on CONSOLE_TRUETYPE @@ -218,6 +208,16 @@ config SIMPLE_PANEL This turns on a simple panel driver that enables a compatible video panel.
+config PANEL_HX8238D + bool "Enable Himax HX-8238D LCD driver" + depends on PANEL + help + Support for HX-8238D LCD Panel + The HX8238-D is a single chip controller and driver LSI that + integrates the power circuit. + It can drive a maximum 960x240 dot graphics on a-TFT panel + displays in 16M colors with dithering. + source "drivers/video/fonts/Kconfig"
config VIDCONSOLE_AS_LCD diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 7019b263963..5a673549321 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -15,7 +15,7 @@ obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi-host-uclass.o obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o obj-$(CONFIG_DM_VIDEO) += video_bmp.o obj-$(CONFIG_PANEL) += panel-uclass.o -obj-$(CONFIG_DM_PANEL_HX8238D) += hx8238d.o +obj-$(CONFIG_PANEL_HX8238D) += hx8238d.o obj-$(CONFIG_SIMPLE_PANEL) += simple_panel.o
obj-$(CONFIG_VIDEO_LOGO) += u_boot_logo.o

Generalise the video_clear() function to allow filling with a different colour.
Tidy up the comments while we are here.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/video-uclass.c | 20 ++++++++++++++++---- include/video.h | 13 +++++++++++-- 2 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index b258a8a00fc..9f22da02528 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -126,7 +126,7 @@ int video_reserve(ulong *addrp) return 0; }
-int video_clear(struct udevice *dev) +int video_fill(struct udevice *dev, u32 colour) { struct video_priv *priv = dev_get_uclass_priv(dev); int ret; @@ -138,7 +138,7 @@ int video_clear(struct udevice *dev) u16 *end = priv->fb + priv->fb_size;
while (ppix < end) - *ppix++ = priv->colour_bg; + *ppix++ = colour; break; } case VIDEO_BPP32: @@ -147,11 +147,11 @@ int video_clear(struct udevice *dev) u32 *end = priv->fb + priv->fb_size;
while (ppix < end) - *ppix++ = priv->colour_bg; + *ppix++ = colour; break; } default: - memset(priv->fb, priv->colour_bg, priv->fb_size); + memset(priv->fb, colour, priv->fb_size); break; } ret = video_sync_copy(dev, priv->fb, priv->fb + priv->fb_size); @@ -161,6 +161,18 @@ int video_clear(struct udevice *dev) return video_sync(dev, false); }
+int video_clear(struct udevice *dev) +{ + struct video_priv *priv = dev_get_uclass_priv(dev); + int ret; + + ret = video_fill(dev, priv->colour_bg); + if (ret) + return ret; + + return 0; +} + static const struct vid_rgb colours[VID_COLOUR_COUNT] = { { 0x00, 0x00, 0x00 }, /* black */ { 0xc0, 0x00, 0x00 }, /* red */ diff --git a/include/video.h b/include/video.h index 1c30aea73c0..4c216d851b6 100644 --- a/include/video.h +++ b/include/video.h @@ -185,13 +185,22 @@ u32 video_index_to_colour(struct video_priv *priv, unsigned int idx); int video_reserve(ulong *addrp);
/** - * video_clear() - Clear a device's frame buffer to background color. + * video_clear() - Clear a device's frame buffer to background colour. * * @dev: Device to clear - * Return: 0 + * Return: 0 on success */ int video_clear(struct udevice *dev);
+/** + * video_fill() - Fill a device's frame buffer to a colour. + * + * @dev: Device to fill + * @colour: Colour to use, in the frame buffer's format + * Return: 0 on success + */ +int video_fill(struct udevice *dev, u32 colour); + /** * video_sync() - Sync a device's frame buffer with its hardware *

It is useful to show the logo from other code, coming in a later feature. Add a function to obtain it.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/video-uclass.c | 5 +++++ include/video.h | 7 +++++++ 2 files changed, 12 insertions(+)
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index 9f22da02528..fbe1ad169e9 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -406,6 +406,11 @@ int video_sync_copy_all(struct udevice *dev)
SPLASH_DECL(u_boot_logo);
+void *video_get_u_boot_logo(void) +{ + return SPLASH_START(u_boot_logo); +} + static int show_splash(struct udevice *dev) { u8 *data = SPLASH_START(u_boot_logo); diff --git a/include/video.h b/include/video.h index 4c216d851b6..2e68dd717ef 100644 --- a/include/video.h +++ b/include/video.h @@ -319,4 +319,11 @@ static inline int video_sync_copy_all(struct udevice *dev) */ bool video_is_active(void);
+/** + * video_get_u_boot_logo() - Get a pointer to the U-Boot logo + * + * Returns: Pointer to logo + */ +void *video_get_u_boot_logo(void); + #endif

Put this check into a function so we can use it elsewhere. Also drop the macros which do the same thing but are not actually used.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/console_truetype.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index c04b449a6d5..1331ce8d896 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -526,9 +526,18 @@ static struct font_info font_table[] = { {} /* sentinel */ };
-#define FONT_BEGIN(name) __ttf_ ## name ## _begin -#define FONT_END(name) __ttf_ ## name ## _end -#define FONT_IS_VALID(name) (abs(FONT_END(name) - FONT_BEGIN) > 4) +/** + * font_valid() - Check if a font-table entry is valid + * + * Depending on available files in the build system, fonts may end up being + * empty. + * + * @return true if the entry is valid + */ +static inline bool font_valid(struct font_info *tab) +{ + return abs(tab->begin - tab->end) > 4; +}
/** * console_truetype_find_font() - Find a suitable font @@ -542,7 +551,7 @@ static u8 *console_truetype_find_font(void) struct font_info *tab;
for (tab = font_table; tab->begin; tab++) { - if (abs(tab->begin - tab->end) > 4) { + if (font_valid(tab)) { debug("%s: Font '%s', at %p, size %lx\n", __func__, tab->name, tab->begin, (ulong)(tab->end - tab->begin));

At present the truetype console supports only a single font and size. It is useful to be able to support different combinations. As a first step, move the metrics into there own structure and allow having multiple metrics.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/Kconfig | 15 ++++ drivers/video/console_truetype.c | 140 +++++++++++++++++++++---------- 2 files changed, 113 insertions(+), 42 deletions(-)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 44ab9e708f5..32938376655 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -176,6 +176,21 @@ config CONSOLE_TRUETYPE_SIZE method to select the display's physical size, which would allow U-Boot to calculate the correct font size.
+config CONSOLE_TRUETYPE_MAX_METRICS + int "TrueType maximum number of font / size combinations" + depends on CONSOLE_TRUETYPE + default 10 if EXPO + default 1 + help + This sets the number of font / size combinations which can be used by + the console. For simple console use a single font is enough. When + boot menus are in use, this may need to be increased. + + Note that a separate entry is needed for each font size, even if the + font itself is the same. This is because the entry caches various + font metrics which are expensive to regenerate each time the font + size changes. + config SYS_WHITE_ON_BLACK bool "Display console as white on a black background" default y if ARCH_AT91 || ARCH_EXYNOS || ARCH_ROCKCHIP || ARCH_TEGRA || X86 || ARCH_SUNXI diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 1331ce8d896..ab7bcda197f 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -94,17 +94,15 @@ struct pos_info { #define POS_HISTORY_SIZE (CONFIG_SYS_CBSIZE * 11 / 10)
/** - * struct console_tt_priv - Private data for this driver + * struct console_tt_metrics - Information about a font / size combination + * + * This caches various font metrics which are expensive to regenerate each time + * the font size changes. There is one of these for each font / size combination + * that is being used * * @font_size: Vertical font size in pixels * @font_data: Pointer to TrueType font file contents * @font: TrueType font information for the current font - * @pos: List of cursor positions for each character written. This is - * used to handle backspace. We clear the frame buffer between - * the last position and the current position, thus erasing the - * last character. We record enough characters to go back to the - * start of the current command line. - * @pos_ptr: Current position in the position history * @baseline: Pixel offset of the font's baseline from the cursor position. * This is the 'ascent' of the font, scaled to pixel coordinates. * It measures the distance from the baseline to the top of the @@ -113,25 +111,45 @@ struct pos_info { * of the font. It is used by the STB library to generate images * of the correct size. */ -struct console_tt_priv { +struct console_tt_metrics { int font_size; - u8 *font_data; + const u8 *font_data; stbtt_fontinfo font; - struct pos_info pos[POS_HISTORY_SIZE]; - int pos_ptr; int baseline; double scale; };
+/** + * struct console_tt_priv - Private data for this driver + * + * @cur_met: Current metrics being used + * @metrics: List metrics that can be used + * @num_metrics: Number of available metrics + * @pos: List of cursor positions for each character written. This is + * used to handle backspace. We clear the frame buffer between + * the last position and the current position, thus erasing the + * last character. We record enough characters to go back to the + * start of the current command line. + * @pos_ptr: Current position in the position history + */ +struct console_tt_priv { + struct console_tt_metrics *cur_met; + struct console_tt_metrics metrics[CONFIG_CONSOLE_TRUETYPE_MAX_METRICS]; + int num_metrics; + struct pos_info pos[POS_HISTORY_SIZE]; + int pos_ptr; +}; + static int console_truetype_set_row(struct udevice *dev, uint row, int clr) { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); struct console_tt_priv *priv = dev_get_priv(dev); + struct console_tt_metrics *met = priv->cur_met; void *end, *line; int ret;
- line = vid_priv->fb + row * priv->font_size * vid_priv->line_length; - end = line + priv->font_size * vid_priv->line_length; + line = vid_priv->fb + row * met->font_size * vid_priv->line_length; + end = line + met->font_size * vid_priv->line_length;
switch (vid_priv->bpix) { #ifdef CONFIG_VIDEO_BPP8 @@ -176,19 +194,20 @@ static int console_truetype_move_rows(struct udevice *dev, uint rowdst, { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); struct console_tt_priv *priv = dev_get_priv(dev); + struct console_tt_metrics *met = priv->cur_met; void *dst; void *src; int i, diff, ret;
- dst = vid_priv->fb + rowdst * priv->font_size * vid_priv->line_length; - src = vid_priv->fb + rowsrc * priv->font_size * vid_priv->line_length; - ret = vidconsole_memmove(dev, dst, src, priv->font_size * + dst = vid_priv->fb + rowdst * met->font_size * vid_priv->line_length; + src = vid_priv->fb + rowsrc * met->font_size * vid_priv->line_length; + ret = vidconsole_memmove(dev, dst, src, met->font_size * vid_priv->line_length * count); if (ret) return ret;
/* Scroll up our position history */ - diff = (rowsrc - rowdst) * priv->font_size; + diff = (rowsrc - rowdst) * met->font_size; for (i = 0; i < priv->pos_ptr; i++) priv->pos[i].ypos -= diff;
@@ -202,7 +221,8 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, struct udevice *vid = dev->parent; struct video_priv *vid_priv = dev_get_uclass_priv(vid); struct console_tt_priv *priv = dev_get_priv(dev); - stbtt_fontinfo *font = &priv->font; + struct console_tt_metrics *met = priv->cur_met; + stbtt_fontinfo *font = &met->font; int width, height, xoff, yoff; double xpos, x_shift; int lsb; @@ -222,7 +242,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, * this character */ xpos = frac(VID_TO_PIXEL((double)x)); if (vc_priv->last_ch) { - xpos += priv->scale * stbtt_GetCodepointKernAdvance(font, + xpos += met->scale * stbtt_GetCodepointKernAdvance(font, vc_priv->last_ch, ch); }
@@ -233,7 +253,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, * it dictates how much the cursor will move forward on the line. */ x_shift = xpos - (double)tt_floor(xpos); - xpos += advance * priv->scale; + xpos += advance * met->scale; width_frac = (int)VID_TO_POS(xpos); if (x + width_frac >= vc_priv->xsize_frac) return -EAGAIN; @@ -252,7 +272,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, * image of the character. For empty characters, like ' ', data will * return NULL; */ - data = stbtt_GetCodepointBitmapSubpixel(font, priv->scale, priv->scale, + data = stbtt_GetCodepointBitmapSubpixel(font, met->scale, met->scale, x_shift, 0, ch, &width, &height, &xoff, &yoff); if (!data) @@ -262,7 +282,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, bits = data; start = vid_priv->fb + y * vid_priv->line_length + VID_TO_PIXEL(x) * VNBYTES(vid_priv->bpix); - linenum = priv->baseline + yoff; + linenum = met->baseline + yoff; if (linenum > 0) start += linenum * vid_priv->line_length; line = start; @@ -562,42 +582,78 @@ static u8 *console_truetype_find_font(void) return NULL; }
+/** + * vidconsole_add_metrics() - Add a new font/size combination + * + * @dev: Video console device to update + * @font_name: Name of font + * @font_size: Size of the font (norminal pixel height) + * @font_data: Pointer to the font data + * @return 0 if OK, -EPERM if stbtt failed, -E2BIG if the the metrics table is + * full + */ +static int vidconsole_add_metrics(struct udevice *dev, const void *font_data, + uint font_size) +{ + struct console_tt_priv *priv = dev_get_priv(dev); + struct console_tt_metrics *met; + stbtt_fontinfo *font; + int ascent; + + if (priv->num_metrics == CONFIG_CONSOLE_TRUETYPE_MAX_METRICS) + return log_msg_ret("num", -E2BIG); + + met = &priv->metrics[priv->num_metrics]; + met->font_size = font_size; + met->font_data = font_data; + + font = &met->font; + if (!stbtt_InitFont(font, font_data, 0)) { + debug("%s: Font init failed\n", __func__); + return -EPERM; + } + + /* Pre-calculate some things we will need regularly */ + met->scale = stbtt_ScaleForPixelHeight(font, font_size); + stbtt_GetFontVMetrics(font, &ascent, 0, 0); + met->baseline = (int)(ascent * met->scale); + + return priv->num_metrics++; +} + static int console_truetype_probe(struct udevice *dev) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct console_tt_priv *priv = dev_get_priv(dev); struct udevice *vid_dev = dev->parent; struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev); - stbtt_fontinfo *font = &priv->font; - int ascent; + void *font_data; + uint font_size; + int ret;
debug("%s: start\n", __func__); if (vid_priv->font_size) - priv->font_size = vid_priv->font_size; + font_size = vid_priv->font_size; else - priv->font_size = CONFIG_CONSOLE_TRUETYPE_SIZE; - priv->font_data = console_truetype_find_font(); - if (!priv->font_data) { + font_size = CONFIG_CONSOLE_TRUETYPE_SIZE; + font_data = console_truetype_find_font(); + if (!font_data) { debug("%s: Could not find any fonts\n", __func__); return -EBFONT; }
- vc_priv->x_charsize = priv->font_size; - vc_priv->y_charsize = priv->font_size; - vc_priv->xstart_frac = VID_TO_POS(2); - vc_priv->cols = vid_priv->xsize / priv->font_size; - vc_priv->rows = vid_priv->ysize / priv->font_size; - vc_priv->tab_width_frac = VID_TO_POS(priv->font_size) * 8 / 2; + ret = vidconsole_add_metrics(dev, font_data, font_size); + if (ret < 0) + return log_msg_ret("add", ret); + priv->cur_met = &priv->metrics[ret];
- if (!stbtt_InitFont(font, priv->font_data, 0)) { - debug("%s: Font init failed\n", __func__); - return -EPERM; - } + vc_priv->x_charsize = font_size; + vc_priv->y_charsize = font_size; + vc_priv->xstart_frac = VID_TO_POS(2); + vc_priv->cols = vid_priv->xsize / font_size; + vc_priv->rows = vid_priv->ysize / font_size; + vc_priv->tab_width_frac = VID_TO_POS(font_size) * 8 / 2;
- /* Pre-calculate some things we will need regularly */ - priv->scale = stbtt_ScaleForPixelHeight(font, priv->font_size); - stbtt_GetFontVMetrics(font, &ascent, 0, 0); - priv->baseline = (int)(ascent * priv->scale); debug("%s: ready\n", __func__);
return 0;

Add this to the metrics so we can later adjust the font size without changing the font itself.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/console_truetype.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index ab7bcda197f..6ef3fae8a32 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -100,6 +100,7 @@ struct pos_info { * the font size changes. There is one of these for each font / size combination * that is being used * + * @font_name: Name of the font * @font_size: Vertical font size in pixels * @font_data: Pointer to TrueType font file contents * @font: TrueType font information for the current font @@ -112,6 +113,7 @@ struct pos_info { * of the correct size. */ struct console_tt_metrics { + const char *font_name; int font_size; const u8 *font_data; stbtt_fontinfo font; @@ -562,11 +564,11 @@ static inline bool font_valid(struct font_info *tab) /** * console_truetype_find_font() - Find a suitable font * - * This searched for the first available font. + * This searches for the first available font. * - * Return: pointer to the font, or NULL if none is found + * Return: pointer to the font-table entry, or NULL if none is found */ -static u8 *console_truetype_find_font(void) +static struct font_info *console_truetype_find_font(void) { struct font_info *tab;
@@ -575,7 +577,7 @@ static u8 *console_truetype_find_font(void) debug("%s: Font '%s', at %p, size %lx\n", __func__, tab->name, tab->begin, (ulong)(tab->end - tab->begin)); - return tab->begin; + return tab; } }
@@ -592,8 +594,8 @@ static u8 *console_truetype_find_font(void) * @return 0 if OK, -EPERM if stbtt failed, -E2BIG if the the metrics table is * full */ -static int vidconsole_add_metrics(struct udevice *dev, const void *font_data, - uint font_size) +static int vidconsole_add_metrics(struct udevice *dev, const char *font_name, + uint font_size, const void *font_data) { struct console_tt_priv *priv = dev_get_priv(dev); struct console_tt_metrics *met; @@ -604,6 +606,7 @@ static int vidconsole_add_metrics(struct udevice *dev, const void *font_data, return log_msg_ret("num", -E2BIG);
met = &priv->metrics[priv->num_metrics]; + met->font_name = font_name; met->font_size = font_size; met->font_data = font_data;
@@ -627,7 +630,7 @@ static int console_truetype_probe(struct udevice *dev) struct console_tt_priv *priv = dev_get_priv(dev); struct udevice *vid_dev = dev->parent; struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev); - void *font_data; + struct font_info *tab; uint font_size; int ret;
@@ -636,13 +639,13 @@ static int console_truetype_probe(struct udevice *dev) font_size = vid_priv->font_size; else font_size = CONFIG_CONSOLE_TRUETYPE_SIZE; - font_data = console_truetype_find_font(); - if (!font_data) { + tab = console_truetype_find_font(); + if (!tab) { debug("%s: Could not find any fonts\n", __func__); return -EBFONT; }
- ret = vidconsole_add_metrics(dev, font_data, font_size); + ret = vidconsole_add_metrics(dev, tab->name, font_size, tab->begin); if (ret < 0) return log_msg_ret("add", ret); priv->cur_met = &priv->metrics[ret];

Move this code into a function so we can call it later when we want to change the font.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/console_truetype.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 6ef3fae8a32..5fc737a9ff2 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -624,9 +624,24 @@ static int vidconsole_add_metrics(struct udevice *dev, const char *font_name, return priv->num_metrics++; }
-static int console_truetype_probe(struct udevice *dev) +static void select_metrics(struct udevice *dev, struct console_tt_metrics *met) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); + struct console_tt_priv *priv = dev_get_priv(dev); + struct udevice *vid_dev = dev_get_parent(dev); + struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev); + + priv->cur_met = met; + vc_priv->x_charsize = met->font_size; + vc_priv->y_charsize = met->font_size; + vc_priv->xstart_frac = VID_TO_POS(2); + vc_priv->cols = vid_priv->xsize / met->font_size; + vc_priv->rows = vid_priv->ysize / met->font_size; + vc_priv->tab_width_frac = VID_TO_POS(met->font_size) * 8 / 2; +} + +static int console_truetype_probe(struct udevice *dev) +{ struct console_tt_priv *priv = dev_get_priv(dev); struct udevice *vid_dev = dev->parent; struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev); @@ -650,12 +665,7 @@ static int console_truetype_probe(struct udevice *dev) return log_msg_ret("add", ret); priv->cur_met = &priv->metrics[ret];
- vc_priv->x_charsize = font_size; - vc_priv->y_charsize = font_size; - vc_priv->xstart_frac = VID_TO_POS(2); - vc_priv->cols = vid_priv->xsize / font_size; - vc_priv->rows = vid_priv->ysize / font_size; - vc_priv->tab_width_frac = VID_TO_POS(font_size) * 8 / 2; + select_metrics(dev, &priv->metrics[ret]);
debug("%s: ready\n", __func__);

It is useful to be able to support multiple fonts. Add a function to handle this as well as one to list the available fonts.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/console_truetype.c | 75 ++++++++++++++++++++++++++++++++ include/video_console.h | 16 +++++++ 2 files changed, 91 insertions(+)
diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 5fc737a9ff2..09421e7a905 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -584,6 +584,16 @@ static struct font_info *console_truetype_find_font(void) return NULL; }
+void vidconsole_list_fonts(void) +{ + struct font_info *tab; + + for (tab = font_table; tab->begin; tab++) { + if (abs(tab->begin - tab->end) > 4) + printf("%s\n", tab->name); + } +} + /** * vidconsole_add_metrics() - Add a new font/size combination * @@ -624,6 +634,30 @@ static int vidconsole_add_metrics(struct udevice *dev, const char *font_name, return priv->num_metrics++; }
+/** + * find_metrics() - Find the metrics for a given font and size + * + * @dev: Video console device to update + * @name: Name of font + * @size: Size of the font (norminal pixel height) + * @return metrics, if found, else NULL + */ +static struct console_tt_metrics *find_metrics(struct udevice *dev, + const char *name, uint size) +{ + struct console_tt_priv *priv = dev_get_priv(dev); + int i; + + for (i = 0; i < priv->num_metrics; i++) { + struct console_tt_metrics *met = &priv->metrics[i]; + + if (!strcmp(name, met->font_name) && met->font_size == size) + return met; + } + + return NULL; +} + static void select_metrics(struct udevice *dev, struct console_tt_metrics *met) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); @@ -640,6 +674,47 @@ static void select_metrics(struct udevice *dev, struct console_tt_metrics *met) vc_priv->tab_width_frac = VID_TO_POS(met->font_size) * 8 / 2; }
+int vidconsole_select_font(struct udevice *dev, const char *name, uint size) +{ + struct console_tt_priv *priv = dev_get_priv(dev); + struct console_tt_metrics *met; + struct font_info *tab; + + if (name || size) { + if (!size) + size = CONFIG_CONSOLE_TRUETYPE_SIZE; + if (!name) + name = priv->cur_met->font_name; + + met = find_metrics(dev, name, size); + if (!met) { + for (tab = font_table; tab->begin; tab++) { + if (font_valid(tab) && + !strcmp(name, tab->name)) { + int ret; + + ret = vidconsole_add_metrics(dev, + tab->name, size, tab->begin); + if (ret < 0) + return log_msg_ret("add", ret); + + met = &priv->metrics[ret]; + break; + } + } + } + if (!met) + return log_msg_ret("find", -ENOENT); + } else { + /* Use the default font */ + met = priv->metrics; + } + + select_metrics(dev, met); + + return 0; +} + static int console_truetype_probe(struct udevice *dev) { struct console_tt_priv *priv = dev_get_priv(dev); diff --git a/include/video_console.h b/include/video_console.h index 76c4b10acf6..bef926cd433 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -231,6 +231,22 @@ void vidconsole_position_cursor(struct udevice *dev, unsigned col, */ void vidconsole_set_cursor_pos(struct udevice *dev, int x, int y);
+/** + * vidconsole_list_fonts() - List the available fonts + * + * This shows a list on the console + */ +void vidconsole_list_fonts(void); + +/** + * vidconsole_select_font() - Select a font to use + * + * @dev: vidconsole device + * @name: Font name + * @size: Size of the font (norminal pixel height) or 0 for default + */ +int vidconsole_select_font(struct udevice *dev, const char *name, uint size); + #ifdef CONFIG_VIDEO_COPY /** * vidconsole_sync_copy() - Sync back to the copy framebuffer

This is enabled for LCD but not for VIDEO. Enable it since it is useful to be able to clear the screen and adds very little code.
Signed-off-by: Simon Glass sjg@chromium.org ---
cmd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmd/Kconfig b/cmd/Kconfig index a512a55c031..30094244fd0 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1915,7 +1915,7 @@ config CMD_CONITRACE config CMD_CLS bool "Enable clear screen command 'cls'" depends on DM_VIDEO || LCD || VIDEO - default y if LCD + default y if LCD || DM_VIDEO help Enable the 'cls' command which clears the screen contents on video frame buffer.

Add a new 'font' command which allows the fonts to be listed as well as selecting a different font and size.
Allow the test to run on sandbox, where multiple font/size combinations are supported, as well as sandbox_flattree, where they are not.
Signed-off-by: Simon Glass sjg@chromium.org ---
cmd/Makefile | 1 + cmd/font.c | 81 ++++++++++++++++++++++++++++++++ configs/sandbox_defconfig | 1 + doc/usage/cmd/font.rst | 52 ++++++++++++++++++++ doc/usage/index.rst | 1 + drivers/video/console_truetype.c | 10 ++++ include/test/suites.h | 1 + include/video_console.h | 9 ++++ test/cmd/Makefile | 1 + test/cmd/font.c | 77 ++++++++++++++++++++++++++++++ test/cmd_ut.c | 6 +++ 11 files changed, 240 insertions(+) create mode 100644 cmd/font.c create mode 100644 doc/usage/cmd/font.rst create mode 100644 test/cmd/font.c
diff --git a/cmd/Makefile b/cmd/Makefile index 86a77805f88..4288b3436ae 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -73,6 +73,7 @@ obj-$(CONFIG_CMD_EXT2) += ext2.o obj-$(CONFIG_CMD_FAT) += fat.o obj-$(CONFIG_CMD_FDT) += fdt.o obj-$(CONFIG_CMD_SQUASHFS) += sqfs.o +obj-$(CONFIG_CONSOLE_TRUETYPE) += font.o obj-$(CONFIG_CMD_FLASH) += flash.o obj-$(CONFIG_CMD_FPGA) += fpga.o obj-$(CONFIG_CMD_FPGAD) += fpgad.o diff --git a/cmd/font.c b/cmd/font.c new file mode 100644 index 00000000000..3e522f3aaa1 --- /dev/null +++ b/cmd/font.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * video commands + * + * Copyright 2022 Google LLC + * Written by Simon Glass sjg@chromium.org + */ + +#include <common.h> +#include <command.h> +#include <dm.h> +#include <video.h> +#include <video_console.h> + +static int do_font_list(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + vidconsole_list_fonts(); + + return 0; +} + +static int do_font_select(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct udevice *dev; + const char *name; + uint size = 0; + int ret; + + if (argc < 2) + return CMD_RET_USAGE; + + if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev)) + return CMD_RET_FAILURE; + name = argv[1]; + if (argc == 3) + size = dectoul(argv[2], NULL); + ret = vidconsole_select_font(dev, name, size); + if (ret) { + printf("Failed (error %d)\n", ret); + return CMD_RET_FAILURE; + } + + return 0; +} +static int do_font_size(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct udevice *dev; + uint size; + int ret; + + if (argc != 2) + return CMD_RET_USAGE; + + if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev)) + return CMD_RET_FAILURE; + + size = dectoul(argv[1], NULL); + ret = vidconsole_select_font(dev, NULL, size); + if (ret) { + printf("Failed (error %d)\n", ret); + return CMD_RET_FAILURE; + } + + return 0; +} + + +#ifdef CONFIG_SYS_LONGHELP +static char font_help_text[] = + "list - list available fonts\n" + "font select <name> [<size>] - select font to use\n" + "font size <size> - select font size to"; +#endif + +U_BOOT_CMD_WITH_SUBCMDS(font, "Fonts", font_help_text, + U_BOOT_SUBCMD_MKENT(list, 1, 1, do_font_list), + U_BOOT_SUBCMD_MKENT(select, 3, 1, do_font_select), + U_BOOT_SUBCMD_MKENT(size, 2, 1, do_font_size)); diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index df6a28ef249..4bb2a73ee60 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -293,6 +293,7 @@ CONFIG_DM_VIDEO=y CONFIG_VIDEO_COPY=y CONFIG_CONSOLE_ROTATION=y CONFIG_CONSOLE_TRUETYPE=y +CONFIG_CONSOLE_TRUETYPE_MAX_METRICS=10 CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y CONFIG_I2C_EDID=y CONFIG_VIDEO_SANDBOX_SDL=y diff --git a/doc/usage/cmd/font.rst b/doc/usage/cmd/font.rst new file mode 100644 index 00000000000..6fb08232703 --- /dev/null +++ b/doc/usage/cmd/font.rst @@ -0,0 +1,52 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +font command +============ + +Synopis +------- + +:: + + font list + font select <name> [<size>] + font size <size> + + +Description +----------- + +The *font* command allows selection of the font to use on the video console. +This is available when the Truetype console is in use. This is the case when +`CONFIG_CONSOLE_TRUETYPE` is enabled. + + +font list +~~~~~~~~~ + +This lists the available fonts, using the name of the font file in the build. + + +font select +~~~~~~~~~~~ + +This selects a new font and optionally changes the size. + + +font size +~~~~~~~~~ + +This changes the font size only. + + +Examples +-------- + +:: + + => font list + nimbus_sans_l_regular + cantoraone_regular + => font size 40 + => font select cantoraone_regular 20 + => diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 0fda121026e..483a7dcbf86 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -46,6 +46,7 @@ Shell commands cmd/fatinfo cmd/fatload cmd/fdt + cmd/font cmd/for cmd/gpio cmd/load diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 09421e7a905..6859c9fa116 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -715,6 +715,16 @@ int vidconsole_select_font(struct udevice *dev, const char *name, uint size) return 0; }
+const char *vidconsole_get_font(struct udevice *dev, uint *sizep) +{ + struct console_tt_priv *priv = dev_get_priv(dev); + struct console_tt_metrics *met = priv->cur_met; + + *sizep = met->font_size; + + return met->font_name; +} + static int console_truetype_probe(struct udevice *dev) { struct console_tt_priv *priv = dev_get_priv(dev); diff --git a/include/test/suites.h b/include/test/suites.h index 44025ccecd6..a01000e127b 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -39,6 +39,7 @@ int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc, int do_ut_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_env(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); +int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); diff --git a/include/video_console.h b/include/video_console.h index bef926cd433..d755eb73cf2 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -247,6 +247,15 @@ void vidconsole_list_fonts(void); */ int vidconsole_select_font(struct udevice *dev, const char *name, uint size);
+/** + * vidconsole_get_font() - get the current font name and size + * + * @dev: vidconsole device + * @sizep: Place to put the font size (nominal height in pixels) + * Returns: Current font name + */ +const char *vidconsole_get_font(struct udevice *dev, uint *sizep); + #ifdef CONFIG_VIDEO_COPY /** * vidconsole_sync_copy() - Sync back to the copy framebuffer diff --git a/test/cmd/Makefile b/test/cmd/Makefile index 1bb02d93a23..50375f7cf65 100644 --- a/test/cmd/Makefile +++ b/test/cmd/Makefile @@ -11,6 +11,7 @@ endif obj-y += mem.o obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o obj-$(CONFIG_CMD_FDT) += fdt.o +obj-$(CONFIG_CONSOLE_TRUETYPE) += font.o obj-$(CONFIG_CMD_LOADM) += loadm.o obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o obj-$(CONFIG_CMD_PINMUX) += pinmux.o diff --git a/test/cmd/font.c b/test/cmd/font.c new file mode 100644 index 00000000000..7a4156ade62 --- /dev/null +++ b/test/cmd/font.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Tests for font command + * + * Copyright 2022 Google LLC + */ + +#include <common.h> +#include <console.h> +#include <dm.h> +#include <video_console.h> +#include <test/suites.h> +#include <test/ut.h> + +/* Declare a new fdt test */ +#define FONT_TEST(_name, _flags) UNIT_TEST(_name, _flags, font_test) + +/* Test 'fdt addr' resizing an fdt */ +static int font_test_base(struct unit_test_state *uts) +{ + struct udevice *dev; + int max_metrics; + uint size; + int ret; + + ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev)); + ut_assertok(uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev)); + + ut_assertok(console_record_reset_enable()); + ut_assertok(run_command("font list", 0)); + ut_assert_nextline("nimbus_sans_l_regular"); + ut_assert_nextline("cantoraone_regular"); + ut_assertok(ut_check_console_end(uts)); + + ut_asserteq_str("nimbus_sans_l_regular", + vidconsole_get_font(dev, &size)); + ut_asserteq(18, size); + + max_metrics = 1; + if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE)) + max_metrics = IF_ENABLED_INT(CONFIG_CONSOLE_TRUETYPE, + CONFIG_CONSOLE_TRUETYPE_MAX_METRICS); + + ret = run_command("font select cantoraone_regular 40", 0); + if (max_metrics < 2) { + ut_asserteq(1, ret); + ut_assert_nextline("Failed (error -7)"); + ut_assertok(ut_check_console_end(uts)); + return 0; + } + + ut_assertok(ret); + ut_assertok(ut_check_console_end(uts)); + + ut_asserteq_str("cantoraone_regular", + vidconsole_get_font(dev, &size)); + ut_asserteq(40, size); + + ut_assertok(run_command("font size 30", 0)); + ut_assertok(ut_check_console_end(uts)); + + ut_asserteq_str("cantoraone_regular", + vidconsole_get_font(dev, &size)); + ut_asserteq(30, size); + + return 0; +} +FONT_TEST(font_test_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | + UT_TESTF_CONSOLE_REC | UT_TESTF_DM); + +int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + struct unit_test *tests = UNIT_TEST_SUITE_START(font_Test); + const int n_ents = UNIT_TEST_SUITE_COUNT(font_test); + + return cmd_ut_category("font", "font_test_", tests, n_ents, argc, argv); +} diff --git a/test/cmd_ut.c b/test/cmd_ut.c index 11c219b48ac..100bf869c26 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -49,6 +49,9 @@ static struct cmd_tbl cmd_ut_sub[] = { #ifdef CONFIG_CMD_FDT U_BOOT_CMD_MKENT(fdt, CONFIG_SYS_MAXARGS, 1, do_ut_fdt, "", ""), #endif +#ifdef CONFIG_CONSOLE_TRUETYPE + U_BOOT_CMD_MKENT(font, CONFIG_SYS_MAXARGS, 1, do_ut_font, "", ""), +#endif #ifdef CONFIG_UT_OPTEE U_BOOT_CMD_MKENT(optee, CONFIG_SYS_MAXARGS, 1, do_ut_optee, "", ""), #endif @@ -144,6 +147,9 @@ static char ut_help_text[] = #ifdef CONFIG_CMD_FDT "ut fdt [test-name] - test of the fdt command\n" #endif +#ifdef CONFIG_CONSOLE_TRUETYPE + "ut font [test-name] - test of the font command\n" +#endif #ifdef CONFIG_UT_LIB "ut lib [test-name] - test library functions\n" #endif

This is useful for some other users, so break this out into a function.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/video_bmp.c | 16 ++++++++++++---- include/video.h | 11 +++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c index 082895a50ec..6188a13e44e 100644 --- a/drivers/video/video_bmp.c +++ b/drivers/video/video_bmp.c @@ -229,6 +229,16 @@ static void video_splash_align_axis(int *axis, unsigned long panel_size, *axis = max(0, (int)axis_alignment); }
+void video_bmp_get_info(void *bmp_image, ulong *widthp, ulong *heightp, + uint *bpixp) +{ + struct bmp_image *bmp = bmp_image; + + *widthp = get_unaligned_le32(&bmp->header.width); + *heightp = get_unaligned_le32(&bmp->header.height); + *bpixp = get_unaligned_le16(&bmp->header.bit_count); +} + int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, bool align) { @@ -253,9 +263,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, return -EINVAL; }
- width = get_unaligned_le32(&bmp->header.width); - height = get_unaligned_le32(&bmp->header.height); - bmp_bpix = get_unaligned_le16(&bmp->header.bit_count); + video_bmp_get_info(bmp, &width, &height, &bmp_bpix); hdr_size = get_unaligned_le16(&bmp->header.size); debug("hdr_size=%d, bmp_bpix=%d\n", hdr_size, bmp_bpix); palette = (void *)bmp + 14 + hdr_size; @@ -283,7 +291,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, !(bmp_bpix == 24 && bpix == 16) && !(bmp_bpix == 24 && bpix == 32)) { printf("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n", - bpix, get_unaligned_le16(&bmp->header.bit_count)); + bpix, colours); return -EPERM; }
diff --git a/include/video.h b/include/video.h index 2e68dd717ef..32afb26a45b 100644 --- a/include/video.h +++ b/include/video.h @@ -223,6 +223,17 @@ int video_sync(struct udevice *vid, bool force); */ void video_sync_all(void);
+/** + * video_bmp_get_info() - Get information about a bitmap image + * + * @bmp_image: Pointer to BMP image to check + * @widthp: Returns width in pixels + * @heightp: Returns height in pixels + * @bpixp: Returns log2 of bits per pixel + */ +void video_bmp_get_info(void *bmp_image, ulong *widthp, ulong *heightp, + uint *bpixp); + /** * video_bmp_display() - Display a BMP file *

This is not as simple as it seems. Add a function to provide it so that the upcoming menu feature can space lines out correctly.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/video-uclass.c | 11 +++++++++++ include/video.h | 9 +++++++++ 2 files changed, 20 insertions(+)
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index fbe1ad169e9..0ce376ca3f1 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -421,6 +421,17 @@ static int show_splash(struct udevice *dev) return 0; }
+int video_default_font_height(struct udevice *dev) +{ + struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); + + if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE)) + return IF_ENABLED_INT(CONFIG_CONSOLE_TRUETYPE, + CONFIG_CONSOLE_TRUETYPE_SIZE); + + return vc_priv->y_charsize; +} + /* Set up the display ready for use */ static int video_post_probe(struct udevice *dev) { diff --git a/include/video.h b/include/video.h index 32afb26a45b..529f9685183 100644 --- a/include/video.h +++ b/include/video.h @@ -286,6 +286,15 @@ void video_set_flush_dcache(struct udevice *dev, bool flush); */ void video_set_default_colors(struct udevice *dev, bool invert);
+/** + * video_default_font_height() - Get the default font height + * + * @dev: video device + * Returns: Default font height in pixels, which depends on which console driver + * is in use + */ +int video_default_font_height(struct udevice *dev); + #ifdef CONFIG_VIDEO_COPY /** * vidconsole_sync_copy() - Sync back to the copy framebuffer

Hi Anatolij,
On Thu, 6 Oct 2022 at 08:36, Simon Glass sjg@chromium.org wrote:
This series includes some minor enhancements to the Truetype console to allow it to support multiple fonts and sizes at the same time. This is useful for displays where the title needs to be in a larger font than the rest of the text on the display.
The fonts must still be compiled into U-Boot, but now it is possible to change fonts as needed.
Some other minor fixes and tweaks are included as well.
This is mostly in service of the upcoming VBE boot menu which needs to make better use of fonts.
I sent this and another series with video patches. Any thoughts?
Regards, Simon

Hi Simon,
On Mon, 24 Oct 2022 05:45:34 -0600 Simon Glass sjg@chromium.org wrote:
Hi Anatolij,
On Thu, 6 Oct 2022 at 08:36, Simon Glass sjg@chromium.org wrote:
This series includes some minor enhancements to the Truetype console to allow it to support multiple fonts and sizes at the same time. This is useful for displays where the title needs to be in a larger font than the rest of the text on the display.
The fonts must still be compiled into U-Boot, but now it is possible to change fonts as needed.
Some other minor fixes and tweaks are included as well.
This is mostly in service of the upcoming VBE boot menu which needs to make better use of fonts.
I sent this and another series with video patches. Any thoughts?
I've applied both series. When applying, I changed patch
[PATCH 04/16] video: Move the console commands to cmd/
to keep vidconsole_position_cursor() in vidconsole uclass to avoid build errors in common/splash.c.
Thanks!
-- Anatolij

Hi Anatolij,
On Mon, 31 Oct 2022 at 07:56, Anatolij Gustschin agust@denx.de wrote:
Hi Simon,
On Mon, 24 Oct 2022 05:45:34 -0600 Simon Glass sjg@chromium.org wrote:
Hi Anatolij,
On Thu, 6 Oct 2022 at 08:36, Simon Glass sjg@chromium.org wrote:
This series includes some minor enhancements to the Truetype console to allow it to support multiple fonts and sizes at the same time. This is useful for displays where the title needs to be in a larger font than the rest of the text on the display.
The fonts must still be compiled into U-Boot, but now it is possible to change fonts as needed.
Some other minor fixes and tweaks are included as well.
This is mostly in service of the upcoming VBE boot menu which needs to make better use of fonts.
I sent this and another series with video patches. Any thoughts?
I've applied both series. When applying, I changed patch
[PATCH 04/16] video: Move the console commands to cmd/
to keep vidconsole_position_cursor() in vidconsole uclass to avoid build errors in common/splash.c.
Thanks for fixing that!
- Simon
Thanks!
-- Anatolij

On Thu, 6 Oct 2022 08:36:02 -0600 Simon Glass sjg@chromium.org wrote:
This series includes some minor enhancements to the Truetype console to allow it to support multiple fonts and sizes at the same time. This is useful for displays where the title needs to be in a larger font than the rest of the text on the display.
The fonts must still be compiled into U-Boot, but now it is possible to change fonts as needed.
Some other minor fixes and tweaks are included as well.
This is mostly in service of the upcoming VBE boot menu which needs to make better use of fonts.
...
Series applied to u-boot-video/master, thanks!
-- Anatolij
participants (3)
-
Anatolij Gustschin
-
Ilias Apalodimas
-
Simon Glass