- Add two- and three-argument versions of CONFIG_IS_ENABLED in
  linux/kconfig.h
- Adds a new feature which supports copying modified parts of
  the frame buffer to the uncached hardware buffer
- Enable the copy framebuffer on various x86 targets
This commit is contained in:
Tom Rini 2020-07-09 09:54:22 -04:00
commit 506d52308a
32 changed files with 657 additions and 167 deletions

View File

@ -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);
}

View File

@ -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

View File

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

View File

@ -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);
/*

View File

@ -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[] = {

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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),

View File

@ -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);
}

View File

@ -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);
int pbytes = VNBYTES(vid_priv->bpix);
int i, col;
int mask = 0x80;
void *line;
uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
int pbytes = VNBYTES(vid_priv->bpix);
int i, col, x, linenum, ret;
int mask = 0x80;
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);
int pbytes = VNBYTES(vid_priv->bpix);
int i, col;
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;
int pbytes = VNBYTES(vid_priv->bpix);
int i, col, x, ret;
int mask = 0x80;
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);
}

View File

@ -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;
}

View File

@ -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,
};

View File

@ -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;
}

View File

@ -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,
};

View File

@ -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;
vidconsole_put_string(dev, s);
ret = vidconsole_put_string(dev, s);
if (ret) {
#ifdef DEBUG
char str[30];
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)
{

View File

@ -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),
};

View File

@ -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;

View File

@ -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);

View File

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

View File

@ -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;

View File

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

View File

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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}