diff options
32 files changed, 655 insertions, 165 deletions
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c index 0722e4a891..cbf0120adc 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c @@ -147,7 +147,7 @@ static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc, /* Try bootm for legacy and FIT format image */ if (genimg_get_format((void *)uimage) != IMAGE_FORMAT_INVALID) do_bootm(cmdtp, 0, 4, bootm_argv); - else if CONFIG_IS_ENABLED(CMD_BOOTZ) + else if (CONFIG_IS_ENABLED(CMD_BOOTZ)) do_bootz(cmdtp, 0, 4, bootm_argv); } diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile index 11621256ae..3aa2a55676 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -3,6 +3,7 @@ # Copyright 2019 Google LLC obj-$(CONFIG_SPL_BUILD) += cpu_spl.o +obj-$(CONFIG_SPL_BUILD) += spl.o obj-$(CONFIG_SPL_BUILD) += systemagent.o obj-y += cpu_common.o @@ -11,7 +12,6 @@ obj-y += cpu.o obj-y += punit.o obj-y += fsp_bindings.o ifdef CONFIG_SPL_BUILD -obj-y += spl.o obj-y += fsp_m.o endif endif diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c index 435e50edad..d27324cb4e 100644 --- a/arch/x86/cpu/i386/cpu.c +++ b/arch/x86/cpu/i386/cpu.c @@ -363,6 +363,11 @@ static void setup_cpu_features(void) : : "i" (em_rst), "i" (mp_ne_set) : "eax"); } +void cpu_reinit_fpu(void) +{ + asm ("fninit\n"); +} + static void setup_identity(void) { /* identify CPU via cpuid and store the decoded info into gd->arch */ diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 3e5d56d075..bd3f44014c 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -43,6 +43,14 @@ int x86_cpu_reinit_f(void); */ int x86_cpu_init_tpl(void); +/** + * cpu_reinit_fpu() - Reinit the FPU if something is wrong with it + * + * The FSP-M code can leave registers in use in the FPU. This functions reinits + * it so that the FPU can be used safely + */ +void cpu_reinit_fpu(void); + int cpu_init_f(void); void setup_gdt(struct global_data *id, u64 *gdt_addr); /* diff --git a/arch/x86/lib/fsp/fsp_graphics.c b/arch/x86/lib/fsp/fsp_graphics.c index 6e23f3c95f..e8c1e07af1 100644 --- a/arch/x86/lib/fsp/fsp_graphics.c +++ b/arch/x86/lib/fsp/fsp_graphics.c @@ -117,6 +117,16 @@ err: return ret; } +static int fsp_video_bind(struct udevice *dev) +{ + struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); + + /* Set the maximum supported resolution */ + plat->size = 2560 * 1600 * 4; + + return 0; +} + static const struct udevice_id fsp_video_ids[] = { { .compatible = "fsp-fb" }, { } @@ -126,7 +136,9 @@ U_BOOT_DRIVER(fsp_video) = { .name = "fsp_video", .id = UCLASS_VIDEO, .of_match = fsp_video_ids, + .bind = fsp_video_bind, .probe = fsp_video_probe, + .flags = DM_FLAG_PRE_RELOC, }; static struct pci_device_id fsp_video_supported[] = { diff --git a/arch/x86/lib/fsp2/fsp_meminit.c b/arch/x86/lib/fsp2/fsp_meminit.c index 1a758147b0..faf9c29aef 100644 --- a/arch/x86/lib/fsp2/fsp_meminit.c +++ b/arch/x86/lib/fsp2/fsp_meminit.c @@ -85,6 +85,7 @@ int fsp_memory_init(bool s3wake, bool use_spi_flash) func = (fsp_memory_init_func)(hdr->img_base + hdr->fsp_mem_init); ret = func(&upd, &hob); bootstage_accum(BOOTSTAGE_ID_ACCUM_FSP_M); + cpu_reinit_fpu(); if (ret) return log_msg_ret("SDRAM init fail\n", ret); diff --git a/common/console.c b/common/console.c index 7b9816979a..07c483f820 100644 --- a/common/console.c +++ b/common/console.c @@ -229,18 +229,34 @@ static void console_putc(int file, const char c) } } -static void console_puts_noserial(int file, const char *s) +/** + * console_puts_select() - Output a string to all console devices + * + * @file: File number to output to (e,g, stdout, see stdio.h) + * @serial_only: true to output only to serial, false to output to everything + * else + * @s: String to output + */ +static void console_puts_select(int file, bool serial_only, const char *s) { int i; struct stdio_dev *dev; for (i = 0; i < cd_count[file]; i++) { + bool is_serial; + dev = console_devices[file][i]; - if (dev->puts != NULL && !console_dev_is_serial(dev)) + is_serial = console_dev_is_serial(dev); + if (dev->puts && serial_only == is_serial) dev->puts(dev, s); } } +void console_puts_select_stderr(bool serial_only, const char *s) +{ + console_puts_select(stderr, serial_only, s); +} + static void console_puts(int file, const char *s) { int i; @@ -275,9 +291,9 @@ static inline void console_putc(int file, const char c) stdio_devices[file]->putc(stdio_devices[file], c); } -static inline void console_puts_noserial(int file, const char *s) +void console_puts_select(int file, bool serial_only, const char *s) { - if (!console_dev_is_serial(stdio_devices[file])) + if (serial_only == console_dev_is_serial(stdio_devices[file])) stdio_devices[file]->puts(stdio_devices[file], s); } @@ -489,7 +505,7 @@ static void print_pre_console_buffer(int flushpoint) puts(buf_out); break; case PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL: - console_puts_noserial(stdout, buf_out); + console_puts_select(stdout, false, buf_out); break; } } @@ -776,7 +792,7 @@ int console_announce_r(void) display_options_get_banner(false, buf, sizeof(buf)); - console_puts_noserial(stdout, buf); + console_puts_select(stdout, false, buf); #endif return 0; diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig index 3d51ec9606..7e9a7a3cc3 100644 --- a/configs/chromebook_link_defconfig +++ b/configs/chromebook_link_defconfig @@ -62,10 +62,10 @@ CONFIG_SPI=y CONFIG_TPM_TIS_LPC=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y +CONFIG_VIDEO_COPY=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_11A=y CONFIG_VIDEO_IVYBRIDGE_IGD=y -CONFIG_CONSOLE_SCROLL_LINES=5 CONFIG_CMD_DHRYSTONE=y CONFIG_TPM=y # CONFIG_GZIP is not set diff --git a/configs/chromebook_samus_defconfig b/configs/chromebook_samus_defconfig index c18cba9cf4..bf03cdeead 100644 --- a/configs/chromebook_samus_defconfig +++ b/configs/chromebook_samus_defconfig @@ -67,8 +67,8 @@ CONFIG_SPI=y CONFIG_TPM_TIS_LPC=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y +CONFIG_VIDEO_COPY=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_11A=y -CONFIG_CONSOLE_SCROLL_LINES=5 CONFIG_TPM=y # CONFIG_GZIP is not set diff --git a/configs/minnowmax_defconfig b/configs/minnowmax_defconfig index 40ed9e4120..13d6edd08c 100644 --- a/configs/minnowmax_defconfig +++ b/configs/minnowmax_defconfig @@ -59,7 +59,7 @@ CONFIG_RTL8169=y CONFIG_SPI=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y +CONFIG_VIDEO_COPY=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y -CONFIG_FRAMEBUFFER_VESA_MODE_11B=y -CONFIG_CONSOLE_SCROLL_LINES=5 +CONFIG_FRAMEBUFFER_VESA_MODE_118=y # CONFIG_GZIP is not set diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index e0dffa36ea..9b74e404bb 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -220,6 +220,7 @@ CONFIG_DM_USB=y CONFIG_USB_EMUL=y CONFIG_USB_KEYBOARD=y CONFIG_DM_VIDEO=y +CONFIG_VIDEO_COPY=y CONFIG_CONSOLE_ROTATION=y CONFIG_CONSOLE_TRUETYPE=y CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 6a9bc49978..fa29d69e85 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -22,6 +22,8 @@ * Copyright 1997 -- 1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz> */ +#define LOG_CATEGORY UCLASS_PCI + #include <common.h> #include <bios_emul.h> #include <bootstage.h> @@ -344,7 +346,16 @@ int vbe_setup_video_priv(struct vesa_mode_info *vesa, default: return -EPROTONOSUPPORT; } - plat->base = vesa->phys_base_ptr; + + /* Use double buffering if enabled */ + if (IS_ENABLED(CONFIG_VIDEO_COPY)) { + if (!plat->base) + return log_msg_ret("copy", -ENFILE); + plat->copy_base = vesa->phys_base_ptr; + } else { + plat->base = vesa->phys_base_ptr; + } + log_debug("base = %lx, copy_base = %lx\n", plat->base, plat->copy_base); plat->size = vesa->bytes_per_scanline * vesa->y_resolution; return 0; @@ -372,6 +383,15 @@ int vbe_setup_video(struct udevice *dev, int (*int15_handler)(void)) ret = vbe_setup_video_priv(&mode_info.vesa, uc_priv, plat); if (ret) { + if (ret == -ENFILE) { + /* + * See video-uclass.c for how to set up reserved memory + * in your video driver + */ + log_err("CONFIG_VIDEO_COPY enabled but driver '%s' set up no reserved memory\n", + dev->driver->name); + } + debug("No video mode configured\n"); return ret; } diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 0cf13adc7d..89ad603d88 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -22,6 +22,37 @@ config BACKLIGHT This provides backlight uclass driver that enables basic panel backlight support. +config VIDEO_PCI_DEFAULT_FB_SIZE + hex "Default framebuffer size to use if no drivers request it" + depends on DM_VIDEO + default 0x1000000 if X86 && PCI + default 0 if !(X86 && PCI) + help + Generally, video drivers request the amount of memory they need for + the frame buffer when they are bound, by setting the size field in + struct video_uc_platdata. That memory is then reserved for use after + relocation. But PCI drivers cannot be bound before relocation unless + they are mentioned in the devicetree. + + With this value set appropriately, it is possible for PCI video + devices to have a framebuffer allocated by U-Boot. + + Note: the framebuffer needs to be large enough to store all pixels at + maximum resolution. For example, at 1920 x 1200 with 32 bits per + pixel, 2560 * 1600 * 32 / 8 = 0xfa0000 bytes are needed. + +config VIDEO_COPY + bool "Enable copying the frame buffer to a hardware copy" + depends on DM_VIDEO + help + On some machines (e.g. x86), reading from the frame buffer is very + slow because it is uncached. To improve performance, this feature + allows the frame buffer to be kept in cached memory (allocated by + U-Boot) and then copied to the hardware frame-buffer as needed. + + To use this, your video driver must set @copy_base in + struct video_uc_platdata. + config BACKLIGHT_PWM bool "Generic PWM based Backlight Driver" depends on BACKLIGHT && DM_PWM diff --git a/drivers/video/broadwell_igd.c b/drivers/video/broadwell_igd.c index 8e8fe9d9b3..df6a761d2d 100644 --- a/drivers/video/broadwell_igd.c +++ b/drivers/video/broadwell_igd.c @@ -664,6 +664,7 @@ static int broadwell_igd_probe(struct udevice *dev) struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); struct video_priv *uc_priv = dev_get_uclass_priv(dev); bool is_broadwell; + ulong fbbase; int ret; if (!ll_boot_init()) { @@ -690,7 +691,8 @@ static int broadwell_igd_probe(struct udevice *dev) return ret; /* Use write-combining for the graphics memory, 256MB */ - ret = mtrr_add_request(MTRR_TYPE_WRCOMB, plat->base, 256 << 20); + fbbase = IS_ENABLED(CONFIG_VIDEO_COPY) ? plat->copy_base : plat->base; + ret = mtrr_add_request(MTRR_TYPE_WRCOMB, fbbase, 256 << 20); if (!ret) ret = mtrr_commit(true); if (ret && ret != -ENOSYS) { @@ -752,6 +754,17 @@ static int broadwell_igd_ofdata_to_platdata(struct udevice *dev) return 0; } +static int broadwell_igd_bind(struct udevice *dev) +{ + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); + + /* Set the maximum supported resolution */ + uc_plat->size = 2560 * 1600 * 4; + log_debug("%s: Frame buffer size %x\n", __func__, uc_plat->size); + + return 0; +} + static const struct video_ops broadwell_igd_ops = { }; @@ -766,6 +779,7 @@ U_BOOT_DRIVER(broadwell_igd) = { .of_match = broadwell_igd_ids, .ops = &broadwell_igd_ops, .ofdata_to_platdata = broadwell_igd_ofdata_to_platdata, + .bind = broadwell_igd_bind, .probe = broadwell_igd_probe, .priv_auto_alloc_size = sizeof(struct broadwell_igd_priv), .platdata_auto_alloc_size = sizeof(struct broadwell_igd_plat), diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c index c3f7ef8add..04f022491e 100644 --- a/drivers/video/console_normal.c +++ b/drivers/video/console_normal.c @@ -16,8 +16,9 @@ static int console_normal_set_row(struct udevice *dev, uint row, int clr) { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); - void *line; + void *line, *end; int pixels = VIDEO_FONT_HEIGHT * vid_priv->xsize; + int ret; int i; line = vid_priv->fb + row * VIDEO_FONT_HEIGHT * vid_priv->line_length; @@ -28,6 +29,7 @@ static int console_normal_set_row(struct udevice *dev, uint row, int clr) for (i = 0; i < pixels; i++) *dst++ = clr; + end = dst; break; } case VIDEO_BPP16: @@ -36,6 +38,7 @@ static int console_normal_set_row(struct udevice *dev, uint row, int clr) for (i = 0; i < pixels; i++) *dst++ = clr; + end = dst; break; } case VIDEO_BPP32: @@ -44,11 +47,15 @@ static int console_normal_set_row(struct udevice *dev, uint row, int clr) 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; return 0; } @@ -59,10 +66,15 @@ static int console_normal_move_rows(struct udevice *dev, uint rowdst, struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); 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; - memmove(dst, src, VIDEO_FONT_HEIGHT * vid_priv->line_length * count); + size = VIDEO_FONT_HEIGHT * vid_priv->line_length * count; + ret = vidconsole_memmove(dev, dst, src, size); + if (ret) + return ret; return 0; } @@ -74,8 +86,13 @@ static int console_normal_putc_xy(struct udevice *dev, uint x_frac, uint y, struct udevice *vid = dev->parent; struct video_priv *vid_priv = dev_get_uclass_priv(vid); int i, row; - void *line = vid_priv->fb + y * vid_priv->line_length + + void *start; + void *line; + int ret; + + start = vid_priv->fb + y * vid_priv->line_length + VID_TO_PIXEL(x_frac) * VNBYTES(vid_priv->bpix); + line = start; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; @@ -126,6 +143,9 @@ static int console_normal_putc_xy(struct udevice *dev, uint x_frac, uint y, } line += vid_priv->line_length; } + ret = vidconsole_sync_copy(dev, start, line); + if (ret) + return ret; return VID_TO_POS(VIDEO_FONT_WIDTH); } diff --git a/drivers/video/console_rotate.c b/drivers/video/console_rotate.c index b485255598..36c8d0609d 100644 --- a/drivers/video/console_rotate.c +++ b/drivers/video/console_rotate.c @@ -15,11 +15,13 @@ static int console_set_row_1(struct udevice *dev, uint row, int clr) { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); int pbytes = VNBYTES(vid_priv->bpix); - void *line; + void *start, *line; int i, j; + int ret; - line = vid_priv->fb + vid_priv->line_length - + start = vid_priv->fb + vid_priv->line_length - (row + 1) * VIDEO_FONT_HEIGHT * pbytes; + line = start; for (j = 0; j < vid_priv->ysize; j++) { switch (vid_priv->bpix) { case VIDEO_BPP8: @@ -51,6 +53,9 @@ static int console_set_row_1(struct udevice *dev, uint row, int clr) } line += vid_priv->line_length; } + ret = vidconsole_sync_copy(dev, start, line); + if (ret) + return ret; return 0; } @@ -59,10 +64,10 @@ static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc, uint count) { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); + int pbytes = VNBYTES(vid_priv->bpix); void *dst; void *src; - int pbytes = VNBYTES(vid_priv->bpix); - int j; + int j, ret; dst = vid_priv->fb + vid_priv->line_length - (rowdst + count) * VIDEO_FONT_HEIGHT * pbytes; @@ -70,7 +75,10 @@ static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc, (rowsrc + count) * VIDEO_FONT_HEIGHT * pbytes; for (j = 0; j < vid_priv->ysize; j++) { - memmove(dst, src, VIDEO_FONT_HEIGHT * pbytes * count); + ret = vidconsole_memmove(dev, dst, src, + VIDEO_FONT_HEIGHT * pbytes * count); + if (ret) + return ret; src += vid_priv->line_length; dst += vid_priv->line_length; } @@ -83,14 +91,16 @@ 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; int pbytes = VNBYTES(vid_priv->bpix); - int i, col; + int i, col, x, linenum, ret; int mask = 0x80; - void *line; - uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT; + void *start, *line; - line = vid_priv->fb + (VID_TO_PIXEL(x_frac) + 1) * - vid_priv->line_length - (y + 1) * pbytes; + 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; @@ -135,6 +145,10 @@ static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch) line += vid_priv->line_length; mask >>= 1; } + /* 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); } @@ -143,12 +157,13 @@ static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch) 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 *line; + void *start, *line, *end; int pixels = VIDEO_FONT_HEIGHT * vid_priv->xsize; - int i; + int i, ret; - line = vid_priv->fb + vid_priv->ysize * vid_priv->line_length - + start = vid_priv->fb + vid_priv->ysize * vid_priv->line_length - (row + 1) * VIDEO_FONT_HEIGHT * vid_priv->line_length; + line = start; switch (vid_priv->bpix) { case VIDEO_BPP8: if (IS_ENABLED(CONFIG_VIDEO_BPP8)) { @@ -156,6 +171,7 @@ static int console_set_row_2(struct udevice *dev, uint row, int clr) for (i = 0; i < pixels; i++) *dst++ = clr; + end = dst; break; } case VIDEO_BPP16: @@ -164,6 +180,7 @@ static int console_set_row_2(struct udevice *dev, uint row, int clr) for (i = 0; i < pixels; i++) *dst++ = clr; + end = dst; break; } case VIDEO_BPP32: @@ -172,11 +189,15 @@ static int console_set_row_2(struct udevice *dev, uint row, int clr) for (i = 0; i < pixels; i++) *dst++ = clr; + end = dst; break; } default: return -ENOSYS; } + ret = vidconsole_sync_copy(dev, start, end); + if (ret) + return ret; return 0; } @@ -194,7 +215,8 @@ static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc, vid_priv->line_length; src = end - (rowsrc + count) * VIDEO_FONT_HEIGHT * vid_priv->line_length; - memmove(dst, src, VIDEO_FONT_HEIGHT * vid_priv->line_length * count); + vidconsole_memmove(dev, dst, src, + VIDEO_FONT_HEIGHT * vid_priv->line_length * count); return 0; } @@ -204,16 +226,16 @@ 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); - int i, row; - void *line; + int pbytes = VNBYTES(vid_priv->bpix); + int i, row, x, linenum, ret; + void *start, *line; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; - - line = vid_priv->fb + (vid_priv->ysize - y - 1) * - vid_priv->line_length + - (vid_priv->xsize - VID_TO_PIXEL(x_frac) - - VIDEO_FONT_WIDTH - 1) * VNBYTES(vid_priv->bpix); + linenum = vid_priv->ysize - y - 1; + x = vid_priv->xsize - VID_TO_PIXEL(x_frac) - 1; + 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; @@ -261,6 +283,10 @@ static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch) } line -= vid_priv->line_length; } + /* 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); } @@ -269,10 +295,11 @@ static int console_set_row_3(struct udevice *dev, uint row, int clr) { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); int pbytes = VNBYTES(vid_priv->bpix); - void *line; - int i, j; + void *start, *line; + int i, j, ret; - line = vid_priv->fb + row * VIDEO_FONT_HEIGHT * pbytes; + start = vid_priv->fb + row * VIDEO_FONT_HEIGHT * pbytes; + line = start; for (j = 0; j < vid_priv->ysize; j++) { switch (vid_priv->bpix) { case VIDEO_BPP8: @@ -304,6 +331,9 @@ static int console_set_row_3(struct udevice *dev, uint row, int clr) } line += vid_priv->line_length; } + ret = vidconsole_sync_copy(dev, start, line); + if (ret) + return ret; return 0; } @@ -312,16 +342,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); + int pbytes = VNBYTES(vid_priv->bpix); void *dst; void *src; - int pbytes = VNBYTES(vid_priv->bpix); - int j; + int j, ret; dst = vid_priv->fb + rowdst * VIDEO_FONT_HEIGHT * pbytes; src = vid_priv->fb + rowsrc * VIDEO_FONT_HEIGHT * pbytes; for (j = 0; j < vid_priv->ysize; j++) { - memmove(dst, src, VIDEO_FONT_HEIGHT * pbytes * count); + ret = vidconsole_memmove(dev, dst, src, + VIDEO_FONT_HEIGHT * pbytes * count); + if (ret) + return ret; src += vid_priv->line_length; dst += vid_priv->line_length; } @@ -334,17 +367,17 @@ 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; int pbytes = VNBYTES(vid_priv->bpix); - int i, col; + int i, col, x, ret; int mask = 0x80; - void *line = vid_priv->fb + - (vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1) * - vid_priv->line_length + y * pbytes; - uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT; + void *start, *line; 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; + line = start; for (col = 0; col < VIDEO_FONT_HEIGHT; col++) { switch (vid_priv->bpix) { case VIDEO_BPP8: @@ -386,6 +419,10 @@ static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch) line -= vid_priv->line_length; mask >>= 1; } + /* 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); } diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 5f7f03904b..22b2ea7191 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -127,9 +127,9 @@ 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); - void *line; + void *end, *line; int pixels = priv->font_size * vid_priv->line_length; - int i; + int i, ret; line = vid_priv->fb + row * priv->font_size * vid_priv->line_length; switch (vid_priv->bpix) { @@ -139,6 +139,7 @@ static int console_truetype_set_row(struct udevice *dev, uint row, int clr) for (i = 0; i < pixels; i++) *dst++ = clr; + end = dst; break; } #endif @@ -148,6 +149,7 @@ static int console_truetype_set_row(struct udevice *dev, uint row, int clr) for (i = 0; i < pixels; i++) *dst++ = clr; + end = dst; break; } #endif @@ -157,12 +159,16 @@ static int console_truetype_set_row(struct udevice *dev, uint row, int clr) for (i = 0; i < pixels; i++) *dst++ = clr; + end = dst; break; } #endif default: return -ENOSYS; } + ret = vidconsole_sync_copy(dev, line, end); + if (ret) + return ret; return 0; } @@ -174,11 +180,14 @@ static int console_truetype_move_rows(struct udevice *dev, uint rowdst, struct console_tt_priv *priv = dev_get_priv(dev); void *dst; void *src; - int i, diff; + 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; - memmove(dst, src, priv->font_size * vid_priv->line_length * count); + ret = vidconsole_memmove(dev, dst, src, priv->font_size * + vid_priv->line_length * count); + if (ret) + return ret; /* Scroll up our position history */ diff = (rowsrc - rowdst) * priv->font_size; @@ -203,8 +212,8 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, struct pos_info *pos; u8 *bits, *data; int advance; - void *line; - int row; + void *start, *end, *line; + int row, ret; /* First get some basic metrics about this character */ stbtt_GetCodepointHMetrics(font, ch, &advance, &lsb); @@ -253,11 +262,12 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, /* Figure out where to write the character in the frame buffer */ bits = data; - line = vid_priv->fb + y * vid_priv->line_length + + start = vid_priv->fb + y * vid_priv->line_length + VID_TO_PIXEL(x) * VNBYTES(vid_priv->bpix); linenum = priv->baseline + yoff; if (linenum > 0) - line += linenum * vid_priv->line_length; + start += linenum * vid_priv->line_length; + line = start; /* * Write a row at a time, converting the 8bpp image into the colour @@ -286,6 +296,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, *dst++ &= out; bits++; } + end = dst; break; } #endif @@ -307,6 +318,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, *dst++ &= out; bits++; } + end = dst; break; } #endif @@ -317,6 +329,9 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, line += vid_priv->line_length; } + ret = vidconsole_sync_copy(dev, start, line); + if (ret) + return ret; free(data); return width_frac; @@ -340,12 +355,13 @@ static int console_truetype_erase(struct udevice *dev, int xstart, int ystart, int xend, int yend, int clr) { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); - void *line; + void *start, *line; int pixels = xend - xstart; - int row, i; + int row, i, ret; - line = vid_priv->fb + ystart * vid_priv->line_length; - line += xstart * VNBYTES(vid_priv->bpix); + start = vid_priv->fb + ystart * vid_priv->line_length; + start += xstart * VNBYTES(vid_priv->bpix); + line = start; for (row = ystart; row < yend; row++) { switch (vid_priv->bpix) { #ifdef CONFIG_VIDEO_BPP8 @@ -380,6 +396,9 @@ static int console_truetype_erase(struct udevice *dev, int xstart, int ystart, } line += vid_priv->line_length; } + ret = vidconsole_sync_copy(dev, start, line); + if (ret) + return ret; return 0; } diff --git a/drivers/video/ivybridge_igd.c b/drivers/video/ivybridge_igd.c index 4c57e311d1..2587f53ac1 100644 --- a/drivers/video/ivybridge_igd.c +++ b/drivers/video/ivybridge_igd.c @@ -11,6 +11,7 @@ #include <log.h> #include <pci_rom.h> #include <vbe.h> +#include <video.h> #include <asm/intel_regs.h> #include <asm/io.h> #include <asm/mtrr.h> @@ -722,7 +723,6 @@ static int gma_func0_init(struct udevice *dev) { struct udevice *nbridge; void *gtt_bar; - ulong base; u32 reg32; int ret; int rev; @@ -742,11 +742,6 @@ static int gma_func0_init(struct udevice *dev) reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; dm_pci_write_config32(dev, PCI_COMMAND, reg32); - /* Use write-combining for the graphics memory, 256MB */ - base = dm_pci_read_bar32(dev, 2); - mtrr_add_request(MTRR_TYPE_WRCOMB, base, 256 << 20); - mtrr_commit(true); - gtt_bar = (void *)(ulong)dm_pci_read_bar32(dev, 0); debug("GT bar %p\n", gtt_bar); ret = gma_pm_init_pre_vbios(gtt_bar, rev); @@ -758,6 +753,8 @@ static int gma_func0_init(struct udevice *dev) static int bd82x6x_video_probe(struct udevice *dev) { + struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); + ulong fbbase; void *gtt_bar; int ret, rev; @@ -774,6 +771,22 @@ static int bd82x6x_video_probe(struct udevice *dev) if (ret) return ret; + /* Use write-combining for the graphics memory, 256MB */ + fbbase = IS_ENABLED(CONFIG_VIDEO_COPY) ? plat->copy_base : plat->base; + mtrr_add_request(MTRR_TYPE_WRCOMB, fbbase, 256 << 20); + mtrr_commit(true); + + return 0; +} + +static int bd82x6x_video_bind(struct udevice *dev) +{ + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); + + /* Set the maximum supported resolution */ + uc_plat->size = 2560 * 1600 * 4; + log_debug("%s: Frame buffer size %x\n", __func__, uc_plat->size); + return 0; } @@ -786,5 +799,6 @@ U_BOOT_DRIVER(bd82x6x_video) = { .name = "bd82x6x_video", .id = UCLASS_VIDEO, .of_match = bd82x6x_video_ids, + .bind = bd82x6x_video_bind, .probe = bd82x6x_video_probe, }; diff --git a/drivers/video/sandbox_sdl.c b/drivers/video/sandbox_sdl.c index 20248e6607..f529a350fb 100644 --- a/drivers/video/sandbox_sdl.c +++ b/drivers/video/sandbox_sdl.c @@ -23,6 +23,7 @@ enum { static int sandbox_sdl_probe(struct udevice *dev) { + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); struct sandbox_sdl_plat *plat = dev_get_platdata(dev); struct video_priv *uc_priv = dev_get_uclass_priv(dev); struct sandbox_state *state = state_get_current(); @@ -40,6 +41,8 @@ static int sandbox_sdl_probe(struct udevice *dev) uc_priv->rot = plat->rot; uc_priv->vidconsole_drv_name = plat->vidconsole_drv_name; uc_priv->font_size = plat->font_size; + if (IS_ENABLED(CONFIG_VIDEO_COPY)) + uc_plat->copy_base = uc_plat->base - uc_plat->size / 2; return 0; } @@ -53,8 +56,13 @@ static int sandbox_sdl_bind(struct udevice *dev) plat->xres = dev_read_u32_default(dev, "xres", LCD_MAX_WIDTH); plat->yres = dev_read_u32_default(dev, "yres", LCD_MAX_HEIGHT); plat->bpix = dev_read_u32_default(dev, "log2-depth", VIDEO_BPP16); + plat->rot = dev_read_u32_default(dev, "rotate", 0); uc_plat->size = plat->xres * plat->yres * (1 << plat->bpix) / 8; - debug("%s: Frame buffer size %x\n", __func__, uc_plat->size); + + /* Allow space for two buffers, the lower one being the copy buffer */ + log_debug("Frame buffer size %x\n", uc_plat->size); + if (IS_ENABLED(CONFIG_VIDEO_COPY)) + uc_plat->size *= 2; return ret; } diff --git a/drivers/video/vesa.c b/drivers/video/vesa.c index 6c03611e80..9656326bdb 100644 --- a/drivers/video/vesa.c +++ b/drivers/video/vesa.c @@ -5,12 +5,39 @@ #include <common.h> #include <dm.h> +#include <log.h> #include <pci.h> #include <vbe.h> +#include <video.h> +#include <asm/mtrr.h> static int vesa_video_probe(struct udevice *dev) { - return vbe_setup_video(dev, NULL); + struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); + ulong fbbase; + int ret; + + ret = vbe_setup_video(dev, NULL); + if (ret) + return log_ret(ret); + + /* Use write-combining for the graphics memory, 256MB */ + fbbase = IS_ENABLED(CONFIG_VIDEO_COPY) ? plat->copy_base : plat->base; + mtrr_add_request(MTRR_TYPE_WRCOMB, fbbase, 256 << 20); + mtrr_commit(true); + + return 0; +} + +static int vesa_video_bind(struct udevice *dev) +{ + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); + + /* Set the maximum supported resolution */ + uc_plat->size = 2560 * 1600 * 4; + log_debug("%s: Frame buffer size %x\n", __func__, uc_plat->size); + + return 0; } static const struct udevice_id vesa_video_ids[] = { @@ -22,6 +49,7 @@ U_BOOT_DRIVER(vesa_video) = { .name = "vesa_video", .id = UCLASS_VIDEO, .of_match = vesa_video_ids, + .bind = vesa_video_bind, .probe = vesa_video_probe, }; diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 3f20f70e9a..3a07f36ce2 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -9,12 +9,13 @@ #include <common.h> #include <command.h> +#include <console.h> #include <log.h> -#include <linux/ctype.h> #include <dm.h> #include <video.h> #include <video_console.h> #include <video_font.h> /* Bitmap font for code page 437 */ +#include <linux/ctype.h> /* * Structure to describe a console color @@ -556,16 +557,31 @@ int vidconsole_put_string(struct udevice *dev, const char *str) static void vidconsole_putc(struct stdio_dev *sdev, const char ch) { struct udevice *dev = sdev->priv; + int ret; - vidconsole_put_char(dev, ch); + ret = vidconsole_put_char(dev, ch); + if (ret) { +#ifdef DEBUG + console_puts_select_stderr(true, "[vc err: putc]"); +#endif + } video_sync(dev->parent, false); } static void vidconsole_puts(struct stdio_dev *sdev, const char *s) { struct udevice *dev = sdev->priv; + int ret; + + ret = vidconsole_put_string(dev, s); + if (ret) { +#ifdef DEBUG + char str[30]; - vidconsole_put_string(dev, s); + snprintf(str, sizeof(str), "[vc err: puts %d]", ret); + console_puts_select_stderr(true, str); +#endif + } video_sync(dev->parent, false); } @@ -613,6 +629,22 @@ UCLASS_DRIVER(vidconsole) = { .per_device_auto_alloc_size = sizeof(struct vidconsole_priv), }; +#ifdef CONFIG_VIDEO_COPY +int vidconsole_sync_copy(struct udevice *dev, void *from, void *to) +{ + struct udevice *vid = dev_get_parent(dev); + + return video_sync_copy(vid, from, to); +} + +int vidconsole_memmove(struct udevice *dev, void *dst, const void *src, + int size) +{ + memmove(dst, src, size); + 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) { diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index 1f2874554a..650891e49d 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -4,6 +4,7 @@ */ #include <common.h> +#include <console.h> #include <cpu_func.h> #include <dm.h> #include <log.h> @@ -45,6 +46,19 @@ */ DECLARE_GLOBAL_DATA_PTR; +/** + * struct video_uc_priv - Information for the video uclass + * + * @video_ptr: Current allocation position of the video framebuffer pointer. + * While binding devices after relocation, this points to the next + * available address to use for a device's framebuffer. It starts at + * gd->video_top and works downwards, running out of space when it hits + * gd->video_bottom. + */ +struct video_uc_priv { + ulong video_ptr; +}; + void video_set_flush_dcache(struct udevice *dev, bool flush) { struct video_priv *priv = dev_get_uclass_priv(dev); @@ -83,6 +97,11 @@ int video_reserve(ulong *addrp) debug("%s: Reserving %lx bytes at %lx for video device '%s'\n", __func__, size, *addrp, dev->name); } + + /* Allocate space for PCI video devices in case there were not bound */ + if (*addrp == gd->video_top) + *addrp -= CONFIG_VIDEO_PCI_DEFAULT_FB_SIZE; + gd->video_bottom = *addrp; gd->fb_base = *addrp; debug("Video frame buffers from %lx to %lx\n", gd->video_bottom, @@ -94,6 +113,7 @@ int video_reserve(ulong *addrp) int video_clear(struct udevice *dev) { struct video_priv *priv = dev_get_uclass_priv(dev); + int ret; switch (priv->bpix) { case VIDEO_BPP16: @@ -118,6 +138,9 @@ int video_clear(struct udevice *dev) memset(priv->fb, priv->colour_bg, priv->fb_size); break; } + ret = video_sync_copy(dev, priv->fb, priv->fb + priv->fb_size); + if (ret) + return ret; return 0; } @@ -201,6 +224,59 @@ int video_get_ysize(struct udevice *dev) return priv->ysize; } +#ifdef CONFIG_VIDEO_COPY +int video_sync_copy(struct udevice *dev, void *from, void *to) +{ + struct video_priv *priv = dev_get_uclass_priv(dev); + + if (priv->copy_fb) { + long offset, size; + + /* Find the offset of the first byte to copy */ + if ((ulong)to > (ulong)from) { + size = to - from; + offset = from - priv->fb; + } else { + size = from - to; + offset = to - priv->fb; + } + + /* + * Allow a bit of leeway for valid requests somewhere near the + * frame buffer + */ + if (offset < -priv->fb_size || offset > 2 * priv->fb_size) { +#ifdef DEBUG + char str[80]; + + snprintf(str, sizeof(str), + "[sync_copy fb=%p, from=%p, to=%p, offset=%lx]", + priv->fb, from, to, offset); + console_puts_select_stderr(true, str); +#endif + return -EFAULT; + } + + /* + * Silently crop the memcpy. This allows callers to avoid doing + * this themselves. It is common for the end pointer to go a + * few lines after the end of the frame buffer, since most of + * the update algorithms terminate a line after their last write + */ + if (offset + size > priv->fb_size) { + size = priv->fb_size - offset; + } else if (offset < 0) { + size += offset; + offset = 0; + } + + memcpy(priv->copy_fb + offset, priv->fb + offset, size); + } + + return 0; +} +#endif + /* Set up the colour map */ static int video_pre_probe(struct udevice *dev) { @@ -239,6 +315,9 @@ static int video_post_probe(struct udevice *dev) priv->fb_size = priv->line_length * priv->ysize; + if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->copy_base) + priv->copy_fb = map_sysmem(plat->copy_base, plat->size); + /* Set up colors */ video_set_default_colors(dev, false); @@ -290,12 +369,21 @@ static int video_post_probe(struct udevice *dev) /* Post-relocation, allocate memory for the frame buffer */ static int video_post_bind(struct udevice *dev) { - ulong addr = gd->video_top; + struct video_uc_priv *uc_priv; + ulong addr; ulong size; /* Before relocation there is nothing to do here */ if (!(gd->flags & GD_FLG_RELOC)) return 0; + + /* Set up the video pointer, if this is the first device */ + uc_priv = dev->uclass->priv; + if (!uc_priv->video_ptr) + uc_priv->video_ptr = gd->video_top; + + /* Allocate framebuffer space for this device */ + 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 @@ -307,7 +395,7 @@ static int video_post_bind(struct udevice *dev) } debug("%s: Claiming %lx bytes at %lx for video device '%s'\n", __func__, size, addr, dev->name); - gd->video_bottom = addr; + uc_priv->video_ptr = addr; return 0; } @@ -320,6 +408,7 @@ UCLASS_DRIVER(video) = { .pre_probe = video_pre_probe, .post_probe = video_post_probe, .pre_remove = video_pre_remove, + .priv_auto_alloc_size = sizeof(struct video_uc_priv), .per_device_auto_alloc_size = sizeof(struct video_priv), .per_device_platdata_auto_alloc_size = sizeof(struct video_uc_platdata), }; diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c index 7d7f37b445..5a4d12c68d 100644 --- a/drivers/video/video_bmp.c +++ b/drivers/video/video_bmp.c @@ -192,7 +192,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, struct video_priv *priv = dev_get_uclass_priv(dev); ushort *cmap_base = NULL; int i, j; - uchar *fb; + uchar *start, *fb; struct bmp_image *bmp = map_sysmem(bmp_image, 0); uchar *bmap; ushort padded_width; @@ -201,6 +201,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, unsigned colours, bpix, bmp_bpix; struct bmp_color_table_entry *palette; int hdr_size; + int ret; if (!bmp || !(bmp->header.signature[0] == 'B' && bmp->header.signature[1] == 'M')) { @@ -261,8 +262,11 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, height = priv->ysize - y; bmap = (uchar *)bmp + get_unaligned_le32(&bmp->header.data_offset); - fb = (uchar *)(priv->fb + - (y + height - 1) * priv->line_length + x * bpix / 8); + start = (uchar *)(priv->fb + + (y + height) * priv->line_length + x * bpix / 8); + + /* Move back to the final line to be drawn */ + fb = start - priv->line_length; switch (bmp_bpix) { case 1: @@ -369,6 +373,12 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, break; }; + /* Find the position of the top left of the image in the framebuffer */ + fb = (uchar *)(priv->fb + y * priv->line_length + x * bpix / 8); + ret = video_sync_copy(dev, start, fb); + if (ret) + return log_ret(ret); + video_sync(dev, false); return 0; diff --git a/include/bootstage.h b/include/bootstage.h index f507271375..00c85fb86a 100644 --- a/include/bootstage.h +++ b/include/bootstage.h @@ -338,7 +338,7 @@ int bootstage_stash(void *base, int size); * @param base Base address of memory buffer * @param size Size of memory buffer (-1 if unknown) * @return 0 if unstashed ok, -ENOENT if bootstage info not found, -ENOSPC if - * there is not space for read the stacked data, or other error if + * there is not space for read the stashed data, or other error if * something else went wrong */ int bootstage_unstash(const void *base, int size); diff --git a/include/console.h b/include/console.h index 74afe22b7e..4c6b8f2614 100644 --- a/include/console.h +++ b/include/console.h @@ -7,6 +7,8 @@ #ifndef __CONSOLE_H #define __CONSOLE_H +#include <stdbool.h> + extern char console_buffer[]; /* common/console.c */ @@ -72,6 +74,17 @@ int console_record_avail(void); */ int console_announce_r(void); +/** + * console_puts_select_stderr() - Output a string to selected console devices + * + * This writes to stderr only. It is useful for outputting errors + * + * @serial_only: true to output only to serial, false to output to everything + * else + * @s: String to output + */ +void console_puts_select_stderr(bool serial_only, const char *s); + /* * CONSOLE multiplexing. */ diff --git a/include/dm/test.h b/include/dm/test.h index f0f36624ce..d39686cde2 100644 --- a/include/dm/test.h +++ b/include/dm/test.h @@ -159,7 +159,19 @@ enum { /* Declare a new driver model test */ #define DM_TEST(_name, _flags) UNIT_TEST(_name, _flags, dm_test) -/* This platform data is needed in tests, so declare it here */ +/* + * struct sandbox_sdl_plat - Platform data for the SDL video driver + * + * This platform data is needed in tests, so declare it here + * + * @xres: Width of display in pixels + * @yres: Height of display in pixels + * @bpix: Log2 of bits per pixel (enum video_log2_bpp) + * @rot: Console rotation (0=normal orientation, 1=90 degrees clockwise, + * 2=upside down, 3=90 degree counterclockwise) + * @vidconsole_drv_name: Name of video console driver (set by tests) + * @font_size: Console font size to select (set by tests) + */ struct sandbox_sdl_plat { int xres; int yres; diff --git a/include/linux/kconfig.h b/include/linux/kconfig.h index 3a2da738c4..d109ed3119 100644 --- a/include/linux/kconfig.h +++ b/include/linux/kconfig.h @@ -23,54 +23,30 @@ #define ___config_enabled(__ignored, val, ...) val /* - * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm', + * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', * 0 otherwise. * */ #define IS_ENABLED(option) \ - (config_enabled(option) || config_enabled(option##_MODULE)) - -/* - * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0 - * otherwise. For boolean options, this is equivalent to - * IS_ENABLED(CONFIG_FOO). - */ -#define IS_BUILTIN(option) config_enabled(option) - -/* - * IS_MODULE(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'm', 0 - * otherwise. - */ -#define IS_MODULE(option) config_enabled(option##_MODULE) + (config_enabled(option)) /* * U-Boot add-on: Helper macros to reference to different macros * (CONFIG_ or CONFIG_SPL_ prefixed), depending on the build context. */ -#ifdef CONFIG_SPL_BUILD -#define _IS_SPL 1 -#endif - -#ifdef CONFIG_TPL_BUILD -#define _IS_TPL 1 -#endif #if defined(CONFIG_TPL_BUILD) -#define config_val(cfg) _config_val(_IS_TPL, cfg) -#define _config_val(x, cfg) __config_val(x, cfg) -#define __config_val(x, cfg) ___config_val(__ARG_PLACEHOLDER_##x, cfg) -#define ___config_val(arg1_or_junk, cfg) \ - ____config_val(arg1_or_junk CONFIG_TPL_##cfg, CONFIG_##cfg) -#define ____config_val(__ignored, val, ...) val +#define _CONFIG_PREFIX TPL_ +#elif defined(CONFIG_SPL_BUILD) +#define _CONFIG_PREFIX SPL_ #else -#define config_val(cfg) _config_val(_IS_SPL, cfg) -#define _config_val(x, cfg) __config_val(x, cfg) -#define __config_val(x, cfg) ___config_val(__ARG_PLACEHOLDER_##x, cfg) -#define ___config_val(arg1_or_junk, cfg) \ - ____config_val(arg1_or_junk CONFIG_SPL_##cfg, CONFIG_##cfg) -#define ____config_val(__ignored, val, ...) val +#define _CONFIG_PREFIX #endif +#define config_val(cfg) _config_val(_CONFIG_PREFIX, cfg) +#define _config_val(pfx, cfg) __config_val(pfx, cfg) +#define __config_val(pfx, cfg) CONFIG_ ## pfx ## cfg + /* * CONFIG_VAL(FOO) evaluates to the value of * CONFIG_FOO if CONFIG_SPL_BUILD is undefined, @@ -80,30 +56,55 @@ #define CONFIG_VAL(option) config_val(option) /* - * CONFIG_IS_ENABLED(FOO) evaluates to - * 1 if CONFIG_SPL_BUILD is undefined and CONFIG_FOO is set to 'y' or 'm', - * 1 if CONFIG_SPL_BUILD is defined and CONFIG_SPL_FOO is set to 'y' or 'm', - * 1 if CONFIG_TPL_BUILD is defined and CONFIG_TPL_FOO is set to 'y' or 'm', - * 0 otherwise. + * Count number of arguments to a variadic macro. Currently only need + * it for 1, 2 or 3 arguments. */ -#define CONFIG_IS_ENABLED(option) \ - (config_enabled(CONFIG_VAL(option)) || \ - config_enabled(CONFIG_VAL(option##_MODULE))) +#define __arg6(a1, a2, a3, a4, a5, a6, ...) a6 +#define __count_args(...) __arg6(dummy, ##__VA_ARGS__, 4, 3, 2, 1, 0) + +#define __concat(a, b) ___concat(a, b) +#define ___concat(a, b) a ## b + +#define __unwrap(...) __VA_ARGS__ +#define __unwrap1(case1, case0) __unwrap case1 +#define __unwrap0(case1, case0) __unwrap case0 + +#define __CONFIG_IS_ENABLED_1(option) __CONFIG_IS_ENABLED_3(option, (1), (0)) +#define __CONFIG_IS_ENABLED_2(option, case1) __CONFIG_IS_ENABLED_3(option, case1, ()) +#define __CONFIG_IS_ENABLED_3(option, case1, case0) \ + __concat(__unwrap, config_enabled(CONFIG_VAL(option))) (case1, case0) /* - * CONFIG_IS_BUILTIN(FOO) evaluates to + * CONFIG_IS_ENABLED(FOO) expands to * 1 if CONFIG_SPL_BUILD is undefined and CONFIG_FOO is set to 'y', * 1 if CONFIG_SPL_BUILD is defined and CONFIG_SPL_FOO is set to 'y', + * 1 if CONFIG_TPL_BUILD is defined and CONFIG_TPL_FOO is set to 'y', * 0 otherwise. + * + * CONFIG_IS_ENABLED(FOO, (abc)) expands to + * abc if CONFIG_SPL_BUILD is undefined and CONFIG_FOO is set to 'y', + * abc if CONFIG_SPL_BUILD is defined and CONFIG_SPL_FOO is set to 'y', + * abc if CONFIG_TPL_BUILD is defined and CONFIG_TPL_FOO is set to 'y', + * nothing otherwise. + * + * CONFIG_IS_ENABLED(FOO, (abc), (def)) expands to + * abc if CONFIG_SPL_BUILD is undefined and CONFIG_FOO is set to 'y', + * abc if CONFIG_SPL_BUILD is defined and CONFIG_SPL_FOO is set to 'y', + * abc if CONFIG_TPL_BUILD is defined and CONFIG_TPL_FOO is set to 'y', + * def otherwise. + * + * The optional second and third arguments must be parenthesized; that + * allows one to include a trailing comma, e.g. for use in + * + * CONFIG_IS_ENABLED(ACME, ({.compatible = "acme,frobnozzle"},)) + * + * which adds an entry to the array being defined if CONFIG_ACME (or + * CONFIG_SPL_ACME/CONFIG_TPL_ACME, depending on build context) is + * set, and nothing otherwise. */ -#define CONFIG_IS_BUILTIN(option) config_enabled(CONFIG_VAL(option)) -/* - * CONFIG_IS_MODULE(FOO) evaluates to - * 1 if CONFIG_SPL_BUILD is undefined and CONFIG_FOO is set to 'm', - * 1 if CONFIG_SPL_BUILD is defined and CONFIG_SPL_FOO is set to 'm', - * 0 otherwise. - */ -#define CONFIG_IS_MODULE(option) config_enabled(CONFIG_VAL(option##_MODULE)) +#define CONFIG_IS_ENABLED(option, ...) \ + __concat(__CONFIG_IS_ENABLED_, __count_args(option, ##__VA_ARGS__)) (option, ##__VA_ARGS__) + #endif /* __LINUX_KCONFIG_H */ diff --git a/include/spi.h b/include/spi.h index 9b4fb8dc0b..a37900b2fd 100644 --- a/include/spi.h +++ b/include/spi.h @@ -39,7 +39,6 @@ #define SPI_DEFAULT_WORDLEN 8 -#if CONFIG_IS_ENABLED(DM_SPI) /* TODO(sjg@chromium.org): Remove this and use max_hz from struct spi_slave */ struct dm_spi_bus { uint max_hz; @@ -65,8 +64,6 @@ struct dm_spi_slave_platdata { uint mode; }; -#endif /* CONFIG_DM_SPI */ - /** * enum spi_clock_phase - indicates the clock phase to use for SPI (CPHA) * @@ -317,6 +314,11 @@ void spi_flash_copy_mmap(void *data, void *offset, size_t len); */ int spi_cs_is_valid(unsigned int bus, unsigned int cs); +/* + * These names are used in several drivers and these declarations will be + * removed soon as part of the SPI DM migration. Drop them if driver model is + * enabled for SPI. + */ #if !CONFIG_IS_ENABLED(DM_SPI) /** * Activate a SPI chipselect. @@ -335,6 +337,7 @@ void spi_cs_activate(struct spi_slave *slave); * select to the device identified by "slave". */ void spi_cs_deactivate(struct spi_slave *slave); +#endif /** * Set transfer speed. @@ -343,7 +346,6 @@ void spi_cs_deactivate(struct spi_slave *slave); * @hz: The transfer speed */ void spi_set_speed(struct spi_slave *slave, uint hz); -#endif /** * Write 8 bits, then read 8 bits. @@ -367,8 +369,6 @@ static inline int spi_w8r8(struct spi_slave *slave, unsigned char byte) return ret < 0 ? ret : din[1]; } -#if CONFIG_IS_ENABLED(DM_SPI) - /** * struct spi_cs_info - Information about a bus chip select * @@ -717,6 +717,5 @@ int dm_spi_get_mmap(struct udevice *dev, ulong *map_basep, uint *map_sizep, /* Access the operations for a SPI device */ #define spi_get_ops(dev) ((struct dm_spi_ops *)(dev)->driver->ops) #define spi_emul_get_ops(dev) ((struct dm_spi_emul_ops *)(dev)->driver->ops) -#endif /* CONFIG_DM_SPI */ #endif /* _SPI_H_ */ diff --git a/include/video.h b/include/video.h index e7c58e86cb..1a0ffd8037 100644 --- a/include/video.h +++ b/include/video.h @@ -19,10 +19,25 @@ struct udevice; +/** + * struct video_uc_platdata - uclass platform data for a video device + * + * This holds information that the uclass needs to know about each device. It + * is accessed using dev_get_uclass_platdata(dev). See 'Theory of operation' at + * the top of video-uclass.c for details on how this information is set. + * + * @align: Frame-buffer alignment, indicating the memory boundary the frame + * buffer should start on. If 0, 1MB is assumed + * @size: Frame-buffer size, in bytes + * @base: Base address of frame buffer, 0 if not yet known + * @copy_base: Base address of a hardware copy of the frame buffer. See + * CONFIG_VIDEO_COPY. + */ struct video_uc_platdata { uint align; uint size; ulong base; + ulong copy_base; }; enum video_polarity { @@ -63,6 +78,8 @@ enum video_log2_bpp { * @font_size: Font size in pixels (0 to use a default value) * @fb: Frame buffer * @fb_size: Frame buffer size + * @copy_fb: Copy of the frame buffer to keep up to date; see struct + * video_uc_platdata * @line_length: Length of each frame buffer line, in bytes. This can be * set by the driver, but if not, the uclass will set it after * probing @@ -89,6 +106,7 @@ struct video_priv { */ void *fb; int fb_size; + void *copy_fb; int line_length; u32 colour_fg; u32 colour_bg; @@ -202,6 +220,29 @@ void video_set_flush_dcache(struct udevice *dev, bool flush); */ void video_set_default_colors(struct udevice *dev, bool invert); +#ifdef CONFIG_VIDEO_COPY +/** + * vidconsole_sync_copy() - Sync back to the copy framebuffer + * + * This ensures that the copy framebuffer has the same data as the framebuffer + * for a particular region. It should be called after the framebuffer is updated + * + * @from and @to can be in either order. The region between them is synced. + * + * @dev: Vidconsole device being updated + * @from: Start/end address within the framebuffer (->fb) + * @to: Other address within the frame buffer + * @return 0 if OK, -EFAULT if the start address is before the start of the + * frame buffer start + */ +int video_sync_copy(struct udevice *dev, void *from, void *to); +#else +static inline int video_sync_copy(struct udevice *dev, void *from, void *to) +{ + return 0; +} +#endif + #endif /* CONFIG_DM_VIDEO */ #ifndef CONFIG_DM_VIDEO diff --git a/include/video_console.h b/include/video_console.h index 0936ceaaf1..06b798ef10 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -8,6 +8,8 @@ #include <video.h> +struct video_priv; + #define VID_FRAC_DIV 256 #define VID_TO_PIXEL(x) ((x) / VID_FRAC_DIV) @@ -241,8 +243,6 @@ int vidconsole_put_string(struct udevice *dev, const char *str); void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row); -#ifdef CONFIG_DM_VIDEO - /** * vid_console_color() - convert a color code to a pixel's internal * representation @@ -256,6 +256,53 @@ void vidconsole_position_cursor(struct udevice *dev, unsigned col, */ u32 vid_console_color(struct video_priv *priv, unsigned int idx); +#ifdef CONFIG_VIDEO_COPY +/** + * vidconsole_sync_copy() - Sync back to the copy framebuffer + * + * This ensures that the copy framebuffer has the same data as the framebuffer + * for a particular region. It should be called after the framebuffer is updated + * + * @from and @to can be in either order. The region between them is synced. + * + * @dev: Vidconsole device being updated + * @from: Start/end address within the framebuffer (->fb) + * @to: Other address within the frame buffer + * @return 0 if OK, -EFAULT if the start address is before the start of the + * frame buffer start + */ +int vidconsole_sync_copy(struct udevice *dev, void *from, void *to); + +/** + * vidconsole_memmove() - Perform a memmove() within the frame buffer + * + * This handles a memmove(), e.g. for scrolling. It also updates the copy + * framebuffer. + * + * @dev: Vidconsole device being updated + * @dst: Destination address within the framebuffer (->fb) + * @src: Source address within the framebuffer (->fb) + * @size: Number of bytes to transfer + * @return 0 if OK, -EFAULT if the start address is before the start of the + * frame buffer start + */ +int vidconsole_memmove(struct udevice *dev, void *dst, const void *src, + int size); +#else +static inline int vidconsole_sync_copy(struct udevice *dev, void *from, + void *to) +{ + return 0; +} + +static inline int vidconsole_memmove(struct udevice *dev, void *dst, + const void *src, int size) +{ + memmove(dst, src, size); + + return 0; +} + #endif #endif diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 747583089b..e57548c1ec 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -873,9 +873,7 @@ CONFIG_IRAM_SIZE CONFIG_IRAM_STACK CONFIG_IRAM_TOP CONFIG_IRDA_BASE -CONFIG_IS_BUILTIN CONFIG_IS_ENABLED -CONFIG_IS_MODULE CONFIG_JFFS2_CMDLINE CONFIG_JFFS2_DEV CONFIG_JFFS2_LZO diff --git a/test/dm/video.c b/test/dm/video.c index 0664e3f22b..19f78b6239 100644 --- a/test/dm/video.c +++ b/test/dm/video.c @@ -51,12 +51,18 @@ DM_TEST(dm_test_video_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); * size of the compressed data. This provides a pretty good level of * certainty and the resulting tests need only check a single value. * + * If the copy framebuffer is enabled, this compares it to the main framebuffer + * too. + * + * @uts: Test state * @dev: Video device * @return compressed size of the frame buffer, or -ve on error */ -static int compress_frame_buffer(struct udevice *dev) +static int compress_frame_buffer(struct unit_test_state *uts, + struct udevice *dev) { struct video_priv *priv = dev_get_uclass_priv(dev); + struct video_priv *uc_priv = dev_get_uclass_priv(dev); uint destlen; void *dest; int ret; @@ -72,6 +78,13 @@ static int compress_frame_buffer(struct udevice *dev) if (ret) return ret; + /* Check here that the copy frame buffer is working correctly */ + if (IS_ENABLED(CONFIG_VIDEO_COPY)) { + ut_assertf(!memcmp(uc_priv->fb, uc_priv->copy_fb, + uc_priv->fb_size), + "Copy framebuffer does not match fb"); + } + return destlen; } @@ -110,25 +123,25 @@ static int dm_test_video_text(struct unit_test_state *uts) ut_assertok(select_vidconsole(uts, "vidconsole0")); ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); - ut_asserteq(46, compress_frame_buffer(dev)); + ut_asserteq(46, compress_frame_buffer(uts, dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_putc_xy(con, 0, 0, 'a'); - ut_asserteq(79, compress_frame_buffer(dev)); + ut_asserteq(79, compress_frame_buffer(uts, dev)); vidconsole_putc_xy(con, 0, 0, ' '); - ut_asserteq(46, compress_frame_buffer(dev)); + ut_asserteq(46, compress_frame_buffer(uts, dev)); for (i = 0; i < 20; i++) vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i); - ut_asserteq(273, compress_frame_buffer(dev)); + ut_asserteq(273, compress_frame_buffer(uts, dev)); vidconsole_set_row(con, 0, WHITE); - ut_asserteq(46, compress_frame_buffer(dev)); + ut_asserteq(46, compress_frame_buffer(uts, dev)); for (i = 0; i < 20; i++) vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i); - ut_asserteq(273, compress_frame_buffer(dev)); + ut_asserteq(273, compress_frame_buffer(uts, dev)); return 0; } @@ -144,7 +157,7 @@ static int dm_test_video_chars(struct unit_test_state *uts) ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(466, compress_frame_buffer(dev)); + ut_asserteq(466, compress_frame_buffer(uts, dev)); return 0; } @@ -164,20 +177,20 @@ static int dm_test_video_ansi(struct unit_test_state *uts) /* reference clear: */ video_clear(con->parent); video_sync(con->parent, false); - ut_asserteq(46, compress_frame_buffer(dev)); + ut_asserteq(46, compress_frame_buffer(uts, dev)); /* test clear escape sequence: [2J */ vidconsole_put_string(con, "A\tB\tC"ANSI_ESC"[2J"); - ut_asserteq(46, compress_frame_buffer(dev)); + ut_asserteq(46, compress_frame_buffer(uts, dev)); /* test set-cursor: [%d;%df */ vidconsole_put_string(con, "abc"ANSI_ESC"[2;2fab"ANSI_ESC"[4;4fcd"); - ut_asserteq(143, compress_frame_buffer(dev)); + ut_asserteq(143, compress_frame_buffer(uts, dev)); /* test colors (30-37 fg color, 40-47 bg color) */ vidconsole_put_string(con, ANSI_ESC"[30;41mfoo"); /* black on red */ vidconsole_put_string(con, ANSI_ESC"[33;44mbar"); /* yellow on blue */ - ut_asserteq(272, compress_frame_buffer(dev)); + ut_asserteq(272, compress_frame_buffer(uts, dev)); return 0; } @@ -188,7 +201,8 @@ DM_TEST(dm_test_video_ansi, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); * check_vidconsole_output() - Run a text console test * * @uts: Test state - * @rot: Console rotation (0, 90, 180, 270) + * @rot: Console rotation (0=normal orientation, 1=90 degrees clockwise, + * 2=upside down, 3=90 degree counterclockwise) * @wrap_size: Expected size of compressed frame buffer for the wrap test * @scroll_size: Same for the scroll test * @return 0 on success @@ -207,24 +221,24 @@ static int check_vidconsole_output(struct unit_test_state *uts, int rot, ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); - ut_asserteq(46, compress_frame_buffer(dev)); + ut_asserteq(46, compress_frame_buffer(uts, dev)); /* Check display wrap */ for (i = 0; i < 120; i++) vidconsole_put_char(con, 'A' + i % 50); - ut_asserteq(wrap_size, compress_frame_buffer(dev)); + ut_asserteq(wrap_size, compress_frame_buffer(uts, dev)); /* Check display scrolling */ for (i = 0; i < SCROLL_LINES; i++) { vidconsole_put_char(con, 'A' + i % 50); vidconsole_put_char(con, '\n'); } - ut_asserteq(scroll_size, compress_frame_buffer(dev)); + ut_asserteq(scroll_size, compress_frame_buffer(uts, dev)); /* If we scroll enough, the screen becomes blank again */ for (i = 0; i < SCROLL_LINES; i++) vidconsole_put_char(con, '\n'); - ut_asserteq(46, compress_frame_buffer(dev)); + ut_asserteq(46, compress_frame_buffer(uts, dev)); return 0; } @@ -251,7 +265,7 @@ DM_TEST(dm_test_video_rotation1, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); /* Test rotated text output through the console uclass */ static int dm_test_video_rotation2(struct unit_test_state *uts) { - ut_assertok(check_vidconsole_output(uts, 2, 785, 446)); + ut_assertok(check_vidconsole_output(uts, 2, 783, 445)); return 0; } @@ -298,7 +312,7 @@ static int dm_test_video_bmp(struct unit_test_state *uts) ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr)); ut_assertok(video_bmp_display(dev, addr, 0, 0, false)); - ut_asserteq(1368, compress_frame_buffer(dev)); + ut_asserteq(1368, compress_frame_buffer(uts, dev)); return 0; } @@ -314,7 +328,7 @@ static int dm_test_video_bmp_comp(struct unit_test_state *uts) ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr)); ut_assertok(video_bmp_display(dev, addr, 0, 0, false)); - ut_asserteq(1368, compress_frame_buffer(dev)); + ut_asserteq(1368, compress_frame_buffer(uts, dev)); return 0; } @@ -329,7 +343,7 @@ static int dm_test_video_truetype(struct unit_test_state *uts) ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(12237, compress_frame_buffer(dev)); + ut_asserteq(12237, compress_frame_buffer(uts, dev)); return 0; } @@ -350,7 +364,7 @@ static int dm_test_video_truetype_scroll(struct unit_test_state *uts) ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(35030, compress_frame_buffer(dev)); + ut_asserteq(35030, compress_frame_buffer(uts, dev)); return 0; } @@ -371,7 +385,7 @@ static int dm_test_video_truetype_bs(struct unit_test_state *uts) ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(29018, compress_frame_buffer(dev)); + ut_asserteq(29018, compress_frame_buffer(uts, dev)); return 0; } |