diff options
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/Kconfig | 30 | ||||
-rw-r--r-- | drivers/video/Makefile | 6 | ||||
-rw-r--r-- | drivers/video/console_core.c | 212 | ||||
-rw-r--r-- | drivers/video/console_normal.c | 177 | ||||
-rw-r--r-- | drivers/video/console_rotate.c | 371 | ||||
-rw-r--r-- | drivers/video/console_truetype.c | 3 | ||||
-rw-r--r-- | drivers/video/coreboot.c | 2 | ||||
-rw-r--r-- | drivers/video/efi.c | 138 | ||||
-rw-r--r-- | drivers/video/vidconsole-uclass.c | 23 | ||||
-rw-r--r-- | drivers/video/vidconsole_internal.h | 120 | ||||
-rw-r--r-- | drivers/video/video-uclass.c | 36 |
11 files changed, 672 insertions, 446 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 2a76d19cc8e..60f4a4bf9cc 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -16,6 +16,35 @@ config VIDEO if VIDEO +config VIDEO_FONT_4X6 + bool "4 x 6 font size" + help + Font for video console driver, 4 x 6 pixels. + Provides character bitmap data in header file. + When selecting multiple fonts, you may want to enable CMD_SELECT_FONT too. + +config VIDEO_FONT_8X16 + bool "8 x 16 font size" + default y + help + Font for video console driver, 8 x 16 pixels + Provides character bitmap data in header file. + When selecting multiple fonts, you may want to enable CMD_SELECT_FONT too. + +config VIDEO_FONT_SUN12X22 + bool "12 x 22 font size" + help + Font for video console driver, 12 x 22 pixels + Provides character bitmap data in header file. + When selecting multiple fonts, you may want to enable CMD_SELECT_FONT too. + +config VIDEO_FONT_16X32 + bool "16 x 32 font size" + help + Font for video console driver, 16 x 32 pixels + Provides character bitmap data in header file. + When selecting multiple fonts, you may want to enable CMD_SELECT_FONT too. + config VIDEO_LOGO bool "Show the U-Boot logo on the display" default y if !SPLASH_SCREEN @@ -150,6 +179,7 @@ config CONSOLE_ROTATION config CONSOLE_TRUETYPE bool "Support a console that uses TrueType fonts" + select CMD_SELECT_FONT help TrueTrype fonts can provide outline-drawing capability rather than needing to provide a bitmap for each font and size that is needed. diff --git a/drivers/video/Makefile b/drivers/video/Makefile index cdb7d9a54d4..cb3f3736459 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -9,6 +9,12 @@ obj-$(CONFIG_BACKLIGHT_GPIO) += backlight_gpio.o obj-$(CONFIG_BACKLIGHT_PWM) += pwm_backlight.o obj-$(CONFIG_CONSOLE_NORMAL) += console_normal.o obj-$(CONFIG_CONSOLE_ROTATION) += console_rotate.o +ifdef CONFIG_CONSOLE_NORMAL +obj-y += console_core.o +else ifdef CONFIG_CONSOLE_ROTATION +obj-y += console_core.o +endif +obj-$(CONFIG_CONSOLE_ROTATION) += console_core.o obj-$(CONFIG_CONSOLE_TRUETYPE) += console_truetype.o fonts/ obj-$(CONFIG_DISPLAY) += display-uclass.o obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi-host-uclass.o diff --git a/drivers/video/console_core.c b/drivers/video/console_core.c new file mode 100644 index 00000000000..d4f79c656a9 --- /dev/null +++ b/drivers/video/console_core.c @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2015 Google, Inc + * (C) Copyright 2015 + * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com + * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com> + */ + +#include <video.h> +#include <video_console.h> +#include <dm.h> +#include <video_font.h> +#include "vidconsole_internal.h" + +/** + * console_set_font() - prepare vidconsole for chosen font. + * + * @dev vidconsole device + * @fontdata pointer to font data struct + */ +static int console_set_font(struct udevice *dev, struct video_fontdata *fontdata) +{ + struct console_simple_priv *priv = dev_get_priv(dev); + struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); + struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); + + debug("console_simple: setting %s font\n", fontdata->name); + debug("width: %d\n", fontdata->width); + debug("byte width: %d\n", fontdata->byte_width); + debug("height: %d\n", fontdata->height); + + priv->fontdata = fontdata; + vc_priv->x_charsize = fontdata->width; + vc_priv->y_charsize = fontdata->height; + if (vid_priv->rot % 2) { + vc_priv->cols = vid_priv->ysize / fontdata->width; + vc_priv->rows = vid_priv->xsize / fontdata->height; + vc_priv->xsize_frac = VID_TO_POS(vid_priv->ysize); + } else { + vc_priv->cols = vid_priv->xsize / fontdata->width; + vc_priv->rows = vid_priv->ysize / fontdata->height; + } + + return 0; +} + +int check_bpix_support(int bpix) +{ + if (bpix == VIDEO_BPP8 && IS_ENABLED(CONFIG_VIDEO_BPP8)) + return 0; + else if (bpix == VIDEO_BPP16 && IS_ENABLED(CONFIG_VIDEO_BPP16)) + return 0; + else if (bpix == VIDEO_BPP32 && IS_ENABLED(CONFIG_VIDEO_BPP32)) + return 0; + else + return -ENOSYS; +} + +inline void fill_pixel_and_goto_next(void **dstp, u32 value, int pbytes, int step) +{ + u8 *dst_byte = *dstp; + + if (pbytes == 4) { + u32 *dst = *dstp; + *dst = value; + } + if (pbytes == 2) { + u16 *dst = *dstp; + *dst = value; + } + if (pbytes == 1) { + u8 *dst = *dstp; + *dst = value; + } + *dstp = dst_byte + step; +} + +int fill_char_vertically(uchar *pfont, void **line, struct video_priv *vid_priv, + struct video_fontdata *fontdata, bool direction) +{ + int step, line_step, pbytes, bitcount, width_remainder, ret; + void *dst; + + ret = check_bpix_support(vid_priv->bpix); + if (ret) + return ret; + + pbytes = VNBYTES(vid_priv->bpix); + if (direction) { + step = -pbytes; + line_step = -vid_priv->line_length; + } else { + step = pbytes; + line_step = vid_priv->line_length; + } + + width_remainder = fontdata->width % 8; + for (int row = 0; row < fontdata->height; row++) { + uchar bits; + + bitcount = 8; + dst = *line; + for (int col = 0; col < fontdata->byte_width; col++) { + if (width_remainder) { + bool is_last_col = (fontdata->byte_width - col == 1); + + if (is_last_col) + bitcount = width_remainder; + } + bits = pfont[col]; + + for (int bit = 0; bit < bitcount; bit++) { + u32 value = (bits & 0x80) ? + vid_priv->colour_fg : + vid_priv->colour_bg; + + fill_pixel_and_goto_next(&dst, + value, + pbytes, + step + ); + bits <<= 1; + } + } + *line += line_step; + pfont += fontdata->byte_width; + } + return ret; +} + +int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_priv, + struct video_fontdata *fontdata, bool direction) +{ + int step, line_step, pbytes, bitcount = 8, width_remainder, ret; + void *dst; + u8 mask; + + ret = check_bpix_support(vid_priv->bpix); + if (ret) + return ret; + + pbytes = VNBYTES(vid_priv->bpix); + if (direction) { + step = -pbytes; + line_step = vid_priv->line_length; + } else { + step = pbytes; + line_step = -vid_priv->line_length; + } + + width_remainder = fontdata->width % 8; + for (int col = 0; col < fontdata->byte_width; col++) { + mask = 0x80; + if (width_remainder) { + bool is_last_col = (fontdata->byte_width - col == 1); + + if (is_last_col) + bitcount = width_remainder; + } + for (int bit = 0; bit < bitcount; bit++) { + dst = *line; + for (int row = 0; row < fontdata->height; row++) { + u32 value = (pfont[row * fontdata->byte_width + col] + & mask) ? vid_priv->colour_fg : vid_priv->colour_bg; + + fill_pixel_and_goto_next(&dst, + value, + pbytes, + step + ); + } + *line += line_step; + mask >>= 1; + } + } + return ret; +} + +int console_probe(struct udevice *dev) +{ + return console_set_font(dev, fonts); +} + +const char *console_simple_get_font_size(struct udevice *dev, uint *sizep) +{ + struct console_simple_priv *priv = dev_get_priv(dev); + + *sizep = priv->fontdata->width; + + return priv->fontdata->name; +} + +int console_simple_get_font(struct udevice *dev, int seq, struct vidfont_info *info) +{ + info->name = fonts[seq].name; + + return 0; +} + +int console_simple_select_font(struct udevice *dev, const char *name, uint size) +{ + struct video_fontdata *font; + + for (font = fonts; font->name; font++) { + if (!strcmp(name, font->name)) { + console_set_font(dev, font); + return 0; + } + }; + printf("no such font: %s, make sure it's name has <width>x<height> format\n", name); + return -ENOENT; +} diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c index 04f022491e5..413c7abee9e 100644 --- a/drivers/video/console_normal.c +++ b/drivers/video/console_normal.c @@ -1,10 +1,9 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2015 Google, Inc - * (C) Copyright 2001-2015 - * DENX Software Engineering -- wd@denx.de - * Compulab Ltd - http://compulab.co.il/ + * (C) Copyright 2015 * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com + * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com> */ #include <common.h> @@ -12,47 +11,30 @@ #include <video.h> #include <video_console.h> #include <video_font.h> /* Get font data, width and height */ +#include "vidconsole_internal.h" -static int console_normal_set_row(struct udevice *dev, uint row, int clr) +static int console_set_row(struct udevice *dev, uint row, int clr) { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); - void *line, *end; - int pixels = VIDEO_FONT_HEIGHT * vid_priv->xsize; + struct console_simple_priv *priv = dev_get_priv(dev); + struct video_fontdata *fontdata = priv->fontdata; + void *line, *dst, *end; + int pixels = fontdata->height * vid_priv->xsize; int ret; int i; + int pbytes; + + ret = check_bpix_support(vid_priv->bpix); + if (ret) + return ret; + + line = vid_priv->fb + row * fontdata->height * vid_priv->line_length; + dst = line; + pbytes = VNBYTES(vid_priv->bpix); + for (i = 0; i < pixels; i++) + fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes); + end = dst; - line = vid_priv->fb + row * VIDEO_FONT_HEIGHT * vid_priv->line_length; - switch (vid_priv->bpix) { - case VIDEO_BPP8: - if (IS_ENABLED(CONFIG_VIDEO_BPP8)) { - uint8_t *dst = line; - - for (i = 0; i < pixels; i++) - *dst++ = clr; - end = dst; - break; - } - case VIDEO_BPP16: - if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { - uint16_t *dst = line; - - for (i = 0; i < pixels; i++) - *dst++ = clr; - end = dst; - break; - } - case VIDEO_BPP32: - if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { - uint32_t *dst = line; - - for (i = 0; i < pixels; i++) - *dst++ = clr; - end = dst; - break; - } - default: - return -ENOSYS; - } ret = vidconsole_sync_copy(dev, line, end); if (ret) return ret; @@ -60,18 +42,20 @@ static int console_normal_set_row(struct udevice *dev, uint row, int clr) return 0; } -static int console_normal_move_rows(struct udevice *dev, uint rowdst, - uint rowsrc, uint count) +static int console_move_rows(struct udevice *dev, uint rowdst, + uint rowsrc, uint count) { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); + struct console_simple_priv *priv = dev_get_priv(dev); + struct video_fontdata *fontdata = priv->fontdata; void *dst; void *src; int size; int ret; - dst = vid_priv->fb + rowdst * VIDEO_FONT_HEIGHT * vid_priv->line_length; - src = vid_priv->fb + rowsrc * VIDEO_FONT_HEIGHT * vid_priv->line_length; - size = VIDEO_FONT_HEIGHT * vid_priv->line_length * count; + dst = vid_priv->fb + rowdst * fontdata->height * vid_priv->line_length; + src = vid_priv->fb + rowsrc * fontdata->height * vid_priv->line_length; + size = fontdata->height * vid_priv->line_length * count; ret = vidconsole_memmove(dev, dst, src, size); if (ret) return ret; @@ -79,100 +63,53 @@ static int console_normal_move_rows(struct udevice *dev, uint rowdst, return 0; } -static int console_normal_putc_xy(struct udevice *dev, uint x_frac, uint y, - char ch) +static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, char ch) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; struct video_priv *vid_priv = dev_get_uclass_priv(vid); - int i, row; - void *start; - void *line; - int ret; + struct console_simple_priv *priv = dev_get_priv(dev); + struct video_fontdata *fontdata = priv->fontdata; + int pbytes = VNBYTES(vid_priv->bpix); + int x, linenum, ret; + void *start, *line; + uchar *pfont = fontdata->video_fontdata + + (u8)ch * fontdata->char_pixel_bytes; - start = vid_priv->fb + y * vid_priv->line_length + - VID_TO_PIXEL(x_frac) * VNBYTES(vid_priv->bpix); + if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) + return -EAGAIN; + linenum = y; + x = VID_TO_PIXEL(x_frac); + start = vid_priv->fb + linenum * vid_priv->line_length + x * pbytes; line = start; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; - for (row = 0; row < VIDEO_FONT_HEIGHT; row++) { - unsigned int idx = (u8)ch * VIDEO_FONT_HEIGHT + row; - uchar bits = video_fontdata[idx]; - - switch (vid_priv->bpix) { - case VIDEO_BPP8: - if (IS_ENABLED(CONFIG_VIDEO_BPP8)) { - uint8_t *dst = line; - - for (i = 0; i < VIDEO_FONT_WIDTH; i++) { - *dst++ = (bits & 0x80) ? - vid_priv->colour_fg : - vid_priv->colour_bg; - bits <<= 1; - } - break; - } - case VIDEO_BPP16: - if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { - uint16_t *dst = line; - - for (i = 0; i < VIDEO_FONT_WIDTH; i++) { - *dst++ = (bits & 0x80) ? - vid_priv->colour_fg : - vid_priv->colour_bg; - bits <<= 1; - } - break; - } - case VIDEO_BPP32: - if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { - uint32_t *dst = line; - - for (i = 0; i < VIDEO_FONT_WIDTH; i++) { - *dst++ = (bits & 0x80) ? - vid_priv->colour_fg : - vid_priv->colour_bg; - bits <<= 1; - } - break; - } - default: - return -ENOSYS; - } - line += vid_priv->line_length; - } - ret = vidconsole_sync_copy(dev, start, line); + ret = fill_char_vertically(pfont, &line, vid_priv, fontdata, NORMAL_DIRECTION); if (ret) return ret; - return VID_TO_POS(VIDEO_FONT_WIDTH); -} - -static int console_normal_probe(struct udevice *dev) -{ - struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); - struct udevice *vid_dev = dev->parent; - struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev); - - vc_priv->x_charsize = VIDEO_FONT_WIDTH; - vc_priv->y_charsize = VIDEO_FONT_HEIGHT; - vc_priv->cols = vid_priv->xsize / VIDEO_FONT_WIDTH; - vc_priv->rows = vid_priv->ysize / VIDEO_FONT_HEIGHT; + ret = vidconsole_sync_copy(dev, start, line); + if (ret) + return ret; - return 0; + return VID_TO_POS(fontdata->width); } -struct vidconsole_ops console_normal_ops = { - .putc_xy = console_normal_putc_xy, - .move_rows = console_normal_move_rows, - .set_row = console_normal_set_row, +struct vidconsole_ops console_ops = { + .putc_xy = console_putc_xy, + .move_rows = console_move_rows, + .set_row = console_set_row, + .get_font_size = console_simple_get_font_size, + .get_font = console_simple_get_font, + .select_font = console_simple_select_font, }; U_BOOT_DRIVER(vidconsole_normal) = { - .name = "vidconsole0", - .id = UCLASS_VIDEO_CONSOLE, - .ops = &console_normal_ops, - .probe = console_normal_probe, + .name = "vidconsole0", + .id = UCLASS_VIDEO_CONSOLE, + .ops = &console_ops, + .probe = console_probe, + .priv_auto = sizeof(struct console_simple_priv), }; diff --git a/drivers/video/console_rotate.c b/drivers/video/console_rotate.c index 36c8d0609d8..65358a1c6e7 100644 --- a/drivers/video/console_rotate.c +++ b/drivers/video/console_rotate.c @@ -3,6 +3,7 @@ * Copyright (c) 2015 Google, Inc * (C) Copyright 2015 * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com + * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com> */ #include <common.h> @@ -10,47 +11,25 @@ #include <video.h> #include <video_console.h> #include <video_font.h> /* Get font data, width and height */ +#include "vidconsole_internal.h" static int console_set_row_1(struct udevice *dev, uint row, int clr) { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); + struct console_simple_priv *priv = dev_get_priv(dev); + struct video_fontdata *fontdata = priv->fontdata; int pbytes = VNBYTES(vid_priv->bpix); - void *start, *line; + void *start, *dst, *line; int i, j; int ret; start = vid_priv->fb + vid_priv->line_length - - (row + 1) * VIDEO_FONT_HEIGHT * pbytes; + (row + 1) * fontdata->height * pbytes; line = start; for (j = 0; j < vid_priv->ysize; j++) { - switch (vid_priv->bpix) { - case VIDEO_BPP8: - if (IS_ENABLED(CONFIG_VIDEO_BPP8)) { - uint8_t *dst = line; - - for (i = 0; i < VIDEO_FONT_HEIGHT; i++) - *dst++ = clr; - break; - } - case VIDEO_BPP16: - if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { - uint16_t *dst = line; - - for (i = 0; i < VIDEO_FONT_HEIGHT; i++) - *dst++ = clr; - break; - } - case VIDEO_BPP32: - if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { - uint32_t *dst = line; - - for (i = 0; i < VIDEO_FONT_HEIGHT; i++) - *dst++ = clr; - break; - } - default: - return -ENOSYS; - } + dst = line; + for (i = 0; i < fontdata->height; i++) + fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes); line += vid_priv->line_length; } ret = vidconsole_sync_copy(dev, start, line); @@ -61,22 +40,24 @@ static int console_set_row_1(struct udevice *dev, uint row, int clr) } static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc, - uint count) + uint count) { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); + struct console_simple_priv *priv = dev_get_priv(dev); + struct video_fontdata *fontdata = priv->fontdata; int pbytes = VNBYTES(vid_priv->bpix); void *dst; void *src; int j, ret; dst = vid_priv->fb + vid_priv->line_length - - (rowdst + count) * VIDEO_FONT_HEIGHT * pbytes; + (rowdst + count) * fontdata->height * pbytes; src = vid_priv->fb + vid_priv->line_length - - (rowsrc + count) * VIDEO_FONT_HEIGHT * pbytes; + (rowsrc + count) * fontdata->height * pbytes; for (j = 0; j < vid_priv->ysize; j++) { ret = vidconsole_memmove(dev, dst, src, - VIDEO_FONT_HEIGHT * pbytes * count); + fontdata->height * pbytes * count); if (ret) return ret; src += vid_priv->line_length; @@ -91,110 +72,51 @@ static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch) struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; struct video_priv *vid_priv = dev_get_uclass_priv(vid); - uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT; + struct console_simple_priv *priv = dev_get_priv(dev); + struct video_fontdata *fontdata = priv->fontdata; int pbytes = VNBYTES(vid_priv->bpix); - int i, col, x, linenum, ret; - int mask = 0x80; + int x, linenum, ret; void *start, *line; + uchar *pfont = fontdata->video_fontdata + + (u8)ch * fontdata->char_pixel_bytes; + if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) + return -EAGAIN; linenum = VID_TO_PIXEL(x_frac) + 1; x = y + 1; start = vid_priv->fb + linenum * vid_priv->line_length - x * pbytes; line = start; - if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) - return -EAGAIN; - for (col = 0; col < VIDEO_FONT_HEIGHT; col++) { - switch (vid_priv->bpix) { - case VIDEO_BPP8: - if (IS_ENABLED(CONFIG_VIDEO_BPP8)) { - uint8_t *dst = line; - - for (i = 0; i < VIDEO_FONT_HEIGHT; i++) { - *dst-- = (pfont[i] & mask) ? - vid_priv->colour_fg : - vid_priv->colour_bg; - } - break; - } - case VIDEO_BPP16: - if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { - uint16_t *dst = line; - - for (i = 0; i < VIDEO_FONT_HEIGHT; i++) { - *dst-- = (pfont[i] & mask) ? - vid_priv->colour_fg : - vid_priv->colour_bg; - } - break; - } - case VIDEO_BPP32: - if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { - uint32_t *dst = line; - - for (i = 0; i < VIDEO_FONT_HEIGHT; i++) { - *dst-- = (pfont[i] & mask) ? - vid_priv->colour_fg : - vid_priv->colour_bg; - } - break; - } - default: - return -ENOSYS; - } - line += vid_priv->line_length; - mask >>= 1; - } + ret = fill_char_horizontally(pfont, &line, vid_priv, fontdata, FLIPPED_DIRECTION); + if (ret) + return ret; + /* We draw backwards from 'start, so account for the first line */ ret = vidconsole_sync_copy(dev, start - vid_priv->line_length, line); if (ret) return ret; - return VID_TO_POS(VIDEO_FONT_WIDTH); + return VID_TO_POS(fontdata->width); } static int console_set_row_2(struct udevice *dev, uint row, int clr) { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); - void *start, *line, *end; - int pixels = VIDEO_FONT_HEIGHT * vid_priv->xsize; + struct console_simple_priv *priv = dev_get_priv(dev); + struct video_fontdata *fontdata = priv->fontdata; + void *start, *line, *dst, *end; + int pixels = fontdata->height * vid_priv->xsize; int i, ret; + int pbytes = VNBYTES(vid_priv->bpix); start = vid_priv->fb + vid_priv->ysize * vid_priv->line_length - - (row + 1) * VIDEO_FONT_HEIGHT * vid_priv->line_length; + (row + 1) * fontdata->height * vid_priv->line_length; line = start; - switch (vid_priv->bpix) { - case VIDEO_BPP8: - if (IS_ENABLED(CONFIG_VIDEO_BPP8)) { - uint8_t *dst = line; - - for (i = 0; i < pixels; i++) - *dst++ = clr; - end = dst; - break; - } - case VIDEO_BPP16: - if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { - uint16_t *dst = line; - - for (i = 0; i < pixels; i++) - *dst++ = clr; - end = dst; - break; - } - case VIDEO_BPP32: - if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { - uint32_t *dst = line; - - for (i = 0; i < pixels; i++) - *dst++ = clr; - end = dst; - break; - } - default: - return -ENOSYS; - } + dst = line; + for (i = 0; i < pixels; i++) + fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes); + end = dst; ret = vidconsole_sync_copy(dev, start, end); if (ret) return ret; @@ -206,17 +128,19 @@ static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc, uint count) { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); + struct console_simple_priv *priv = dev_get_priv(dev); + struct video_fontdata *fontdata = priv->fontdata; void *dst; void *src; void *end; end = vid_priv->fb + vid_priv->ysize * vid_priv->line_length; - dst = end - (rowdst + count) * VIDEO_FONT_HEIGHT * + dst = end - (rowdst + count) * fontdata->height * vid_priv->line_length; - src = end - (rowsrc + count) * VIDEO_FONT_HEIGHT * + src = end - (rowsrc + count) * fontdata->height * vid_priv->line_length; vidconsole_memmove(dev, dst, src, - VIDEO_FONT_HEIGHT * vid_priv->line_length * count); + fontdata->height * vid_priv->line_length * count); return 0; } @@ -226,9 +150,13 @@ static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch) struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; struct video_priv *vid_priv = dev_get_uclass_priv(vid); + struct console_simple_priv *priv = dev_get_priv(dev); + struct video_fontdata *fontdata = priv->fontdata; int pbytes = VNBYTES(vid_priv->bpix); - int i, row, x, linenum, ret; + int linenum, x, ret; void *start, *line; + uchar *pfont = fontdata->video_fontdata + + (u8)ch * fontdata->char_pixel_bytes; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; @@ -237,98 +165,33 @@ static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch) start = vid_priv->fb + linenum * vid_priv->line_length + x * pbytes; line = start; - for (row = 0; row < VIDEO_FONT_HEIGHT; row++) { - unsigned int idx = (u8)ch * VIDEO_FONT_HEIGHT + row; - uchar bits = video_fontdata[idx]; - - switch (vid_priv->bpix) { - case VIDEO_BPP8: - if (IS_ENABLED(CONFIG_VIDEO_BPP8)) { - uint8_t *dst = line; - - for (i = 0; i < VIDEO_FONT_WIDTH; i++) { - *dst-- = (bits & 0x80) ? - vid_priv->colour_fg : - vid_priv->colour_bg; - bits <<= 1; - } - break; - } - case VIDEO_BPP16: - if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { - uint16_t *dst = line; - - for (i = 0; i < VIDEO_FONT_WIDTH; i++) { - *dst-- = (bits & 0x80) ? - vid_priv->colour_fg : - vid_priv->colour_bg; - bits <<= 1; - } - break; - } - case VIDEO_BPP32: - if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { - uint32_t *dst = line; - - for (i = 0; i < VIDEO_FONT_WIDTH; i++) { - *dst-- = (bits & 0x80) ? - vid_priv->colour_fg : - vid_priv->colour_bg; - bits <<= 1; - } - break; - } - default: - return -ENOSYS; - } - line -= vid_priv->line_length; - } + ret = fill_char_vertically(pfont, &line, vid_priv, fontdata, FLIPPED_DIRECTION); + if (ret) + return ret; + /* Add 4 bytes to allow for the first pixel writen */ ret = vidconsole_sync_copy(dev, start + 4, line); if (ret) return ret; - return VID_TO_POS(VIDEO_FONT_WIDTH); + return VID_TO_POS(fontdata->width); } static int console_set_row_3(struct udevice *dev, uint row, int clr) { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); + struct console_simple_priv *priv = dev_get_priv(dev); + struct video_fontdata *fontdata = priv->fontdata; int pbytes = VNBYTES(vid_priv->bpix); - void *start, *line; + void *start, *dst, *line; int i, j, ret; - start = vid_priv->fb + row * VIDEO_FONT_HEIGHT * pbytes; + start = vid_priv->fb + row * fontdata->height * pbytes; line = start; for (j = 0; j < vid_priv->ysize; j++) { - switch (vid_priv->bpix) { - case VIDEO_BPP8: - if (IS_ENABLED(CONFIG_VIDEO_BPP8)) { - uint8_t *dst = line; - - for (i = 0; i < VIDEO_FONT_HEIGHT; i++) - *dst++ = clr; - break; - } - case VIDEO_BPP16: - if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { - uint16_t *dst = line; - - for (i = 0; i < VIDEO_FONT_HEIGHT; i++) - *dst++ = clr; - break; - } - case VIDEO_BPP32: - if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { - uint32_t *dst = line; - - for (i = 0; i < VIDEO_FONT_HEIGHT; i++) - *dst++ = clr; - break; - } - default: - return -ENOSYS; - } + dst = line; + for (i = 0; i < fontdata->height; i++) + fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes); line += vid_priv->line_length; } ret = vidconsole_sync_copy(dev, start, line); @@ -342,17 +205,19 @@ static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc, uint count) { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); + struct console_simple_priv *priv = dev_get_priv(dev); + struct video_fontdata *fontdata = priv->fontdata; int pbytes = VNBYTES(vid_priv->bpix); void *dst; void *src; int j, ret; - dst = vid_priv->fb + rowdst * VIDEO_FONT_HEIGHT * pbytes; - src = vid_priv->fb + rowsrc * VIDEO_FONT_HEIGHT * pbytes; + dst = vid_priv->fb + rowdst * fontdata->height * pbytes; + src = vid_priv->fb + rowsrc * fontdata->height * pbytes; for (j = 0; j < vid_priv->ysize; j++) { ret = vidconsole_memmove(dev, dst, src, - VIDEO_FONT_HEIGHT * pbytes * count); + fontdata->height * pbytes * count); if (ret) return ret; src += vid_priv->line_length; @@ -367,131 +232,79 @@ static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch) struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; struct video_priv *vid_priv = dev_get_uclass_priv(vid); - uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT; + struct console_simple_priv *priv = dev_get_priv(dev); + struct video_fontdata *fontdata = priv->fontdata; int pbytes = VNBYTES(vid_priv->bpix); - int i, col, x, ret; - int mask = 0x80; + int linenum, x, ret; void *start, *line; + uchar *pfont = fontdata->video_fontdata + + (u8)ch * fontdata->char_pixel_bytes; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; - x = vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1; - start = vid_priv->fb + x * vid_priv->line_length + y * pbytes; + x = y; + linenum = vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1; + start = vid_priv->fb + linenum * vid_priv->line_length + y * pbytes; line = start; - for (col = 0; col < VIDEO_FONT_HEIGHT; col++) { - switch (vid_priv->bpix) { - case VIDEO_BPP8: - if (IS_ENABLED(CONFIG_VIDEO_BPP8)) { - uint8_t *dst = line; - - for (i = 0; i < VIDEO_FONT_HEIGHT; i++) { - *dst++ = (pfont[i] & mask) ? - vid_priv->colour_fg : - vid_priv->colour_bg; - } - break; - } - case VIDEO_BPP16: - if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { - uint16_t *dst = line; - - for (i = 0; i < VIDEO_FONT_HEIGHT; i++) { - *dst++ = (pfont[i] & mask) ? - vid_priv->colour_fg : - vid_priv->colour_bg; - } - break; - } - case VIDEO_BPP32: - if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { - uint32_t *dst = line; - - for (i = 0; i < VIDEO_FONT_HEIGHT; i++) { - *dst++ = (pfont[i] & mask) ? - vid_priv->colour_fg : - vid_priv->colour_bg; - } - break; - } - default: - return -ENOSYS; - } - line -= vid_priv->line_length; - mask >>= 1; - } + + ret = fill_char_horizontally(pfont, &line, vid_priv, fontdata, NORMAL_DIRECTION); + if (ret) + return ret; /* Add a line to allow for the first pixels writen */ ret = vidconsole_sync_copy(dev, start + vid_priv->line_length, line); if (ret) return ret; - return VID_TO_POS(VIDEO_FONT_WIDTH); -} - - -static int console_probe_2(struct udevice *dev) -{ - struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); - struct udevice *vid_dev = dev->parent; - struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev); - - vc_priv->x_charsize = VIDEO_FONT_WIDTH; - vc_priv->y_charsize = VIDEO_FONT_HEIGHT; - vc_priv->cols = vid_priv->xsize / VIDEO_FONT_WIDTH; - vc_priv->rows = vid_priv->ysize / VIDEO_FONT_HEIGHT; - - return 0; -} - -static int console_probe_1_3(struct udevice *dev) -{ - struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); - struct udevice *vid_dev = dev->parent; - struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev); - - vc_priv->x_charsize = VIDEO_FONT_WIDTH; - vc_priv->y_charsize = VIDEO_FONT_HEIGHT; - vc_priv->cols = vid_priv->ysize / VIDEO_FONT_WIDTH; - vc_priv->rows = vid_priv->xsize / VIDEO_FONT_HEIGHT; - vc_priv->xsize_frac = VID_TO_POS(vid_priv->ysize); - - return 0; + return VID_TO_POS(fontdata->width); } struct vidconsole_ops console_ops_1 = { .putc_xy = console_putc_xy_1, .move_rows = console_move_rows_1, .set_row = console_set_row_1, + .get_font_size = console_simple_get_font_size, + .get_font = console_simple_get_font, + .select_font = console_simple_select_font, }; struct vidconsole_ops console_ops_2 = { .putc_xy = console_putc_xy_2, .move_rows = console_move_rows_2, .set_row = console_set_row_2, + .get_font_size = console_simple_get_font_size, + .get_font = console_simple_get_font, + .select_font = console_simple_select_font, }; struct vidconsole_ops console_ops_3 = { .putc_xy = console_putc_xy_3, .move_rows = console_move_rows_3, .set_row = console_set_row_3, + .get_font_size = console_simple_get_font_size, + .get_font = console_simple_get_font, + .select_font = console_simple_select_font, }; U_BOOT_DRIVER(vidconsole_1) = { .name = "vidconsole1", .id = UCLASS_VIDEO_CONSOLE, .ops = &console_ops_1, - .probe = console_probe_1_3, + .probe = console_probe, + .priv_auto = sizeof(struct console_simple_priv), }; U_BOOT_DRIVER(vidconsole_2) = { .name = "vidconsole2", .id = UCLASS_VIDEO_CONSOLE, .ops = &console_ops_2, - .probe = console_probe_2, + .probe = console_probe, + .priv_auto = sizeof(struct console_simple_priv), }; U_BOOT_DRIVER(vidconsole_3) = { .name = "vidconsole3", .id = UCLASS_VIDEO_CONSOLE, .ops = &console_ops_3, - .probe = console_probe_1_3, + .probe = console_probe, + .priv_auto = sizeof(struct console_simple_priv), }; diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 9cac9a6de4d..6b5390136a7 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -724,7 +724,7 @@ static int truetype_select_font(struct udevice *dev, const char *name, return 0; } -const char *vidconsole_get_font_size(struct udevice *dev, uint *sizep) +const char *console_truetype_get_font_size(struct udevice *dev, uint *sizep) { struct console_tt_priv *priv = dev_get_priv(dev); struct console_tt_metrics *met = priv->cur_met; @@ -773,6 +773,7 @@ struct vidconsole_ops console_truetype_ops = { .backspace = console_truetype_backspace, .entry_start = console_truetype_entry_start, .get_font = console_truetype_get_font, + .get_font_size = console_truetype_get_font_size, .select_font = truetype_select_font, }; diff --git a/drivers/video/coreboot.c b/drivers/video/coreboot.c index d2d87c75c89..c586475e41e 100644 --- a/drivers/video/coreboot.c +++ b/drivers/video/coreboot.c @@ -57,7 +57,7 @@ static int coreboot_video_probe(struct udevice *dev) goto err; } - ret = vesa_setup_video_priv(vesa, uc_priv, plat); + ret = vesa_setup_video_priv(vesa, vesa->phys_base_ptr, uc_priv, plat); if (ret) { ret = log_msg_ret("setup", ret); goto err; diff --git a/drivers/video/efi.c b/drivers/video/efi.c index b11e42c0ebf..28ac15ff61b 100644 --- a/drivers/video/efi.c +++ b/drivers/video/efi.c @@ -5,6 +5,8 @@ * EFI framebuffer driver based on GOP */ +#define LOG_CATEGORY LOGC_EFI + #include <common.h> #include <dm.h> #include <efi_api.h> @@ -50,7 +52,19 @@ static void efi_find_pixel_bits(u32 mask, u8 *pos, u8 *size) *size = len; } -static int get_mode_info(struct vesa_mode_info *vesa) +/** + * get_mode_info() - Ask EFI for the mode information + * + * Gets info from the graphics-output protocol + * + * @vesa: Place to put the mode information + * @fbp: Returns the address of the frame buffer + * @infop: Returns a pointer to the mode info + * Returns: 0 if OK, -ENOSYS if boot services are not available, -ENOTSUPP if + * the protocol is not supported by EFI + */ +static int get_mode_info(struct vesa_mode_info *vesa, u64 *fbp, + struct efi_gop_mode_info **infop) { efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; struct efi_boot_services *boot = efi_get_boot(); @@ -63,41 +77,70 @@ static int get_mode_info(struct vesa_mode_info *vesa) ret = boot->locate_protocol(&efi_gop_guid, NULL, (void **)&gop); if (ret) return log_msg_ret("prot", -ENOTSUPP); - mode = gop->mode; + log_debug("maxmode %u, mode %u, info %p, size %lx, fb %lx, fb_size %lx\n", + mode->max_mode, mode->mode, mode->info, mode->info_size, + (ulong)mode->fb_base, (ulong)mode->fb_size); + vesa->phys_base_ptr = mode->fb_base; + *fbp = mode->fb_base; vesa->x_resolution = mode->info->width; vesa->y_resolution = mode->info->height; + *infop = mode->info; return 0; } -static int save_vesa_mode(struct vesa_mode_info *vesa) +/** + * get_mode_from_entry() - Obtain fb info from the EFIET_GOP_MODE payload entry + * + * This gets the mode information provided by the stub to the payload and puts + * it into a vesa structure. It also returns the mode information. + * + * @vesa: Place to put the mode information + * @fbp: Returns the address of the frame buffer + * @infop: Returns a pointer to the mode info + * Returns: 0 if OK, -ve on error + */ +static int get_mode_from_entry(struct vesa_mode_info *vesa, u64 *fbp, + struct efi_gop_mode_info **infop) { - struct efi_entry_gopmode *mode; - const struct efi_framebuffer *fbinfo; + struct efi_gop_mode *mode; int size; int ret; - if (IS_ENABLED(CONFIG_EFI_APP)) { - ret = get_mode_info(vesa); - if (ret) { - printf("EFI graphics output protocol not found\n"); - return -ENXIO; - } - } else { - ret = efi_info_get(EFIET_GOP_MODE, (void **)&mode, &size); - if (ret == -ENOENT) { - printf("EFI graphics output protocol mode not found\n"); - return -ENXIO; - } - vesa->phys_base_ptr = mode->fb_base; - vesa->x_resolution = mode->info->width; - vesa->y_resolution = mode->info->height; + ret = efi_info_get(EFIET_GOP_MODE, (void **)&mode, &size); + if (ret) { + printf("EFI graphics output entry not found\n"); + return ret; } + vesa->phys_base_ptr = mode->fb_base; + *fbp = mode->fb_base; + vesa->x_resolution = mode->info->width; + vesa->y_resolution = mode->info->height; + *infop = mode->info; - if (mode->info->pixel_format < EFI_GOT_BITMASK) { - fbinfo = &efi_framebuffer_format_map[mode->info->pixel_format]; + return 0; +} + +static int save_vesa_mode(struct vesa_mode_info *vesa, u64 *fbp) +{ + const struct efi_framebuffer *fbinfo; + struct efi_gop_mode_info *info; + int ret; + + if (IS_ENABLED(CONFIG_EFI_APP)) + ret = get_mode_info(vesa, fbp, &info); + else + ret = get_mode_from_entry(vesa, fbp, &info); + if (ret) { + printf("EFI graphics output protocol not found (err=%dE)\n", + ret); + return ret; + } + + if (info->pixel_format < EFI_GOT_BITMASK) { + fbinfo = &efi_framebuffer_format_map[info->pixel_format]; vesa->red_mask_size = fbinfo->red.size; vesa->red_mask_pos = fbinfo->red.pos; vesa->green_mask_size = fbinfo->green.size; @@ -108,29 +151,28 @@ static int save_vesa_mode(struct vesa_mode_info *vesa) vesa->reserved_mask_pos = fbinfo->rsvd.pos; vesa->bits_per_pixel = 32; - vesa->bytes_per_scanline = mode->info->pixels_per_scanline * 4; - } else if (mode->info->pixel_format == EFI_GOT_BITMASK) { - efi_find_pixel_bits(mode->info->pixel_bitmask[0], + vesa->bytes_per_scanline = info->pixels_per_scanline * 4; + } else if (info->pixel_format == EFI_GOT_BITMASK) { + efi_find_pixel_bits(info->pixel_bitmask[0], &vesa->red_mask_pos, &vesa->red_mask_size); - efi_find_pixel_bits(mode->info->pixel_bitmask[1], + efi_find_pixel_bits(info->pixel_bitmask[1], &vesa->green_mask_pos, &vesa->green_mask_size); - efi_find_pixel_bits(mode->info->pixel_bitmask[2], + efi_find_pixel_bits(info->pixel_bitmask[2], &vesa->blue_mask_pos, &vesa->blue_mask_size); - efi_find_pixel_bits(mode->info->pixel_bitmask[3], + efi_find_pixel_bits(info->pixel_bitmask[3], &vesa->reserved_mask_pos, &vesa->reserved_mask_size); vesa->bits_per_pixel = vesa->red_mask_size + vesa->green_mask_size + vesa->blue_mask_size + vesa->reserved_mask_size; - vesa->bytes_per_scanline = (mode->info->pixels_per_scanline * + vesa->bytes_per_scanline = (info->pixels_per_scanline * vesa->bits_per_pixel) / 8; } else { - debug("efi set unknown framebuffer format: %d\n", - mode->info->pixel_format); + log_err("Unknown framebuffer format: %d\n", info->pixel_format); return -EINVAL; } @@ -142,19 +184,20 @@ static int efi_video_probe(struct udevice *dev) struct video_uc_plat *plat = dev_get_uclass_plat(dev); struct video_priv *uc_priv = dev_get_uclass_priv(dev); struct vesa_mode_info *vesa = &mode_info.vesa; + u64 fb; int ret; /* Initialize vesa_mode_info structure */ - ret = save_vesa_mode(vesa); + ret = save_vesa_mode(vesa, &fb); if (ret) goto err; - ret = vesa_setup_video_priv(vesa, uc_priv, plat); + ret = vesa_setup_video_priv(vesa, fb, uc_priv, plat); if (ret) goto err; - printf("Video: %dx%dx%d\n", uc_priv->xsize, uc_priv->ysize, - vesa->bits_per_pixel); + printf("Video: %dx%dx%d @ %lx\n", uc_priv->xsize, uc_priv->ysize, + vesa->bits_per_pixel, (ulong)fb); return 0; @@ -163,6 +206,30 @@ err: return ret; } +static int efi_video_bind(struct udevice *dev) +{ + if (IS_ENABLED(CONFIG_VIDEO_COPY)) { + struct video_uc_plat *plat = dev_get_uclass_plat(dev); + struct vesa_mode_info vesa; + int ret; + u64 fb; + + /* + * Initialise vesa_mode_info structure so we can figure out the + * required framebuffer size. If something goes wrong, just do + * without a copy framebuffer + */ + ret = save_vesa_mode(&vesa, &fb); + if (!ret) { + /* this is not reached if the EFI call failed */ + plat->copy_size = vesa.bytes_per_scanline * + vesa.y_resolution; + } + } + + return 0; +} + static const struct udevice_id efi_video_ids[] = { { .compatible = "efi-fb" }, { } @@ -172,5 +239,6 @@ U_BOOT_DRIVER(efi_video) = { .name = "efi_video", .id = UCLASS_VIDEO, .of_match = efi_video_ids, + .bind = efi_video_bind, .probe = efi_video_probe, }; diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 72a13d30527..1225de23332 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -575,6 +575,17 @@ int vidconsole_get_font(struct udevice *dev, int seq, return ops->get_font(dev, seq, info); } +int vidconsole_get_font_size(struct udevice *dev, const char **name, uint *sizep) +{ + struct vidconsole_ops *ops = vidconsole_get_ops(dev); + + if (!ops->get_font_size) + return -ENOSYS; + + *name = ops->get_font_size(dev, sizep); + return 0; +} + int vidconsole_select_font(struct udevice *dev, const char *name, uint size) { struct vidconsole_ops *ops = vidconsole_get_ops(dev); @@ -645,6 +656,18 @@ int vidconsole_memmove(struct udevice *dev, void *dst, const void *src, } #endif +int vidconsole_clear_and_reset(struct udevice *dev) +{ + int ret; + + ret = video_clear(dev_get_parent(dev)); + if (ret) + return ret; + vidconsole_position_cursor(dev, 0, 0); + + return 0; +} + void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row) { struct vidconsole_priv *priv = dev_get_uclass_priv(dev); diff --git a/drivers/video/vidconsole_internal.h b/drivers/video/vidconsole_internal.h new file mode 100644 index 00000000000..c41edd45249 --- /dev/null +++ b/drivers/video/vidconsole_internal.h @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2015 Google, Inc + * (C) Copyright 2015 + * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com + * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com> + */ + +#define FLIPPED_DIRECTION 1 +#define NORMAL_DIRECTION 0 + +/** + * struct console_simple_priv - Private data for this driver + * + * @video_fontdata font graphical representation data + */ +struct console_simple_priv { + struct video_fontdata *fontdata; +}; + +/** + * Checks if bits per pixel supported. + * + * @param bpix framebuffer bits per pixel. + * + * @returns 0, if supported, or else -ENOSYS. + */ +int check_bpix_support(int bpix); + +/** + * Fill 1 pixel in framebuffer, and go to next one. + * + * @param dstp a pointer to pointer to framebuffer. + * @param value value to write to framebuffer. + * @param pbytes framebuffer bytes per pixel. + * @param step framebuffer pointer increment. Usually is equal to pbytes, + * and may be negative to control filling direction. + */ +void fill_pixel_and_goto_next(void **dstp, u32 value, int pbytes, int step); + +/** + * Fills 1 character in framebuffer vertically. Vertically means we're filling char font data rows + * across the lines. + * + * @param pfont a pointer to character font data. + * @param line a pointer to pointer to framebuffer. It's a point for upper left char corner + * @param vid_priv driver private data. + * @fontdata font graphical representation data + * @param direction controls character orientation. Can be normal or flipped. + * When normal: When flipped: + *|-----------------------------------------------| + *| line stepping | | + *| | | stepping -> | + *| * | | * * * | + *| * * v | * | + *| * | * | + *| * | * * ^ | + *| * * * | * | | + *| | | | + *| stepping -> | line stepping | + *|---!!we're starting from upper left char corner| + *|-----------------------------------------------| + * + * @returns 0, if success, or else error code. + */ +int fill_char_vertically(uchar *pfont, void **line, struct video_priv *vid_priv, + struct video_fontdata *fontdata, bool direction); + +/** + * Fills 1 character in framebuffer horizontally. + * Horizontally means we're filling char font data columns across the lines. + * + * @param pfont a pointer to character font data. + * @param line a pointer to pointer to framebuffer. It's a point for upper left char corner + * @param vid_priv driver private data. + * @fontdata font graphical representation data + * @param direction controls character orientation. Can be normal or flipped. + * When normal: When flipped: + *|-----------------------------------------------| + *| * | line stepping | + *| ^ * * * * * | | | + *| | * * | v * * | + *| | | * * * * * | + *| line stepping | * | + *| | | + *| stepping -> | <- stepping | + *|---!!we're starting from upper left char corner| + *|-----------------------------------------------| + * + * @returns 0, if success, or else error code. + */ +int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_priv, + struct video_fontdata *fontdata, bool direction); + +/** + * console probe function. + * + * @param dev a pointer to device. + * + * @returns 0, if success, or else error code. + */ +int console_probe(struct udevice *dev); + +/** + * Internal function to be used in as ops. + * See details in video_console.h get_font_size function + **/ +const char *console_simple_get_font_size(struct udevice *dev, uint *sizep); + +/** + * Internal function to be used in as ops. + * See details in video_console.h get_font function + **/ +int console_simple_get_font(struct udevice *dev, int seq, struct vidfont_info *info); + +/** + * Internal function to be used in as ops. + * See details in video_console.h select_font function + **/ +int console_simple_select_font(struct udevice *dev, const char *name, uint size); diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index 6aaacff10df..da89f431441 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -78,24 +78,40 @@ void video_set_flush_dcache(struct udevice *dev, bool flush) priv->flush_dcache = flush; } +static ulong alloc_fb_(ulong align, ulong size, ulong *addrp) +{ + ulong base; + + align = align ? align : 1 << 20; + base = *addrp - size; + base &= ~(align - 1); + size = *addrp - base; + *addrp = base; + + return size; +} + static ulong alloc_fb(struct udevice *dev, ulong *addrp) { struct video_uc_plat *plat = dev_get_uclass_plat(dev); - ulong base, align, size; + ulong size; + + if (!plat->size) { + if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->copy_size) { + size = alloc_fb_(plat->align, plat->copy_size, addrp); + plat->copy_base = *addrp; + return size; + } - if (!plat->size) return 0; + } /* Allow drivers to allocate the frame buffer themselves */ if (plat->base) return 0; - align = plat->align ? plat->align : 1 << 20; - base = *addrp - plat->size; - base &= ~(align - 1); - plat->base = base; - size = *addrp - base; - *addrp = base; + size = alloc_fb_(plat->align, plat->size, addrp); + plat->base = *addrp; return size; } @@ -529,8 +545,8 @@ static int video_post_bind(struct udevice *dev) addr = uc_priv->video_ptr; size = alloc_fb(dev, &addr); if (addr < gd->video_bottom) { - /* Device tree node may need the 'u-boot,dm-pre-reloc' or - * 'u-boot,dm-pre-proper' tag + /* Device tree node may need the 'bootph-all' or + * 'bootph-some-ram' tag */ printf("Video device '%s' cannot allocate frame buffer memory -ensure the device is set up before relocation\n", dev->name); |