sandbox: Add LCD driver

Add a simple LCD driver which uses SDL to display the image. We update the
image regularly, while still providing for reasonable performance.

Adjust the common lcd code to support sandbox.

For command-line runs we do not want the LCD to be displayed, so add a
--show_lcd option to enable it.

Tested-by: Che-Liang Chiou <clchiou@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
master
Simon Glass 10 years ago
parent c34c0246a3
commit 7d95f2a329
  1. 9
      arch/sandbox/cpu/start.c
  2. 1
      arch/sandbox/include/asm/state.h
  3. 3
      arch/sandbox/include/asm/u-boot-sandbox.h
  4. 18
      board/sandbox/sandbox/sandbox.c
  5. 21
      common/lcd.c
  6. 13
      doc/device-tree-bindings/video/sandbox-fb.txt
  7. 4
      drivers/serial/sandbox.c
  8. 1
      drivers/video/Makefile
  9. 79
      drivers/video/sandbox_sdl.c
  10. 1
      include/fdtdec.h
  11. 3
      include/lcd.h
  12. 1
      lib/fdtdec.c

@ -175,6 +175,15 @@ static int sandbox_cmdline_cb_ignore_missing(struct sandbox_state *state,
SANDBOX_CMDLINE_OPT_SHORT(ignore_missing, 'n', 0,
"Ignore missing state on read");
static int sandbox_cmdline_cb_show_lcd(struct sandbox_state *state,
const char *arg)
{
state->show_lcd = true;
return 0;
}
SANDBOX_CMDLINE_OPT_SHORT(show_lcd, 'l', 0,
"Show the sandbox LCD display");
int main(int argc, char *argv[])
{
struct sandbox_state *state;

@ -41,6 +41,7 @@ struct sandbox_state {
bool read_state; /* Read sandbox state on startup */
bool write_state; /* Write sandbox state on exit */
bool ignore_missing_state_on_read; /* No error if state missing */
bool show_lcd; /* Show LCD on start-up */
/* Pointer to information for each SPI bus/cs */
struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS]

@ -25,4 +25,7 @@ int sandbox_main_loop_init(void);
int cleanup_before_linux(void);
/* drivers/video/sandbox_sdl.c */
int sandbox_lcd_sdl_early_init(void);
#endif /* _U_BOOT_SANDBOX_H_ */

@ -7,6 +7,7 @@
#include <cros_ec.h>
#include <dm.h>
#include <os.h>
#include <asm/u-boot-sandbox.h>
/*
* Pointer to initial global data area
@ -35,6 +36,23 @@ int dram_init(void)
return 0;
}
#ifdef CONFIG_BOARD_EARLY_INIT_F
int board_early_init_f(void)
{
#ifdef CONFIG_VIDEO_SANDBOX_SDL
int ret;
ret = sandbox_lcd_sdl_early_init();
if (ret) {
puts("Could not init sandbox LCD emulation\n");
return ret;
}
#endif
return 0;
}
#endif
int arch_early_init_r(void)
{
#ifdef CONFIG_CROS_EC

@ -28,6 +28,8 @@
#include <watchdog.h>
#include <asm/unaligned.h>
#include <splash.h>
#include <asm/io.h>
#include <asm/unaligned.h>
#if defined(CONFIG_CPU_PXA25X) || defined(CONFIG_CPU_PXA27X) || \
defined(CONFIG_CPU_MONAHANS)
@ -63,6 +65,10 @@
# endif
#endif
#ifdef CONFIG_SANDBOX
#include <asm/sdl.h>
#endif
#ifndef CONFIG_LCD_ALIGNMENT
#define CONFIG_LCD_ALIGNMENT PAGE_SIZE
#endif
@ -144,6 +150,13 @@ void lcd_sync(void)
if (lcd_flush_dcache)
flush_dcache_range((u32)lcd_base,
(u32)(lcd_base + lcd_get_size(&line_length)));
#elif defined(CONFIG_SANDBOX) && defined(CONFIG_VIDEO_SANDBOX_SDL)
static ulong last_sync;
if (get_timer(last_sync) > 10) {
sandbox_sdl_sync(lcd_base);
last_sync = get_timer(0);
}
#endif
}
@ -403,7 +416,7 @@ int drv_lcd_init(void)
struct stdio_dev lcddev;
int rc;
lcd_base = (void *) gd->fb_base;
lcd_base = map_sysmem(gd->fb_base, 0);
lcd_init(lcd_base); /* LCD initialization */
@ -494,8 +507,8 @@ static int lcd_init(void *lcdbase)
* by setting up gd->fb_base. Check for this condition and fixup
* 'lcd_base' address.
*/
if ((unsigned long)lcdbase != gd->fb_base)
lcd_base = (void *)gd->fb_base;
if (map_to_sysmem(lcdbase) != gd->fb_base)
lcd_base = map_sysmem(gd->fb_base, 0);
debug("[LCD] Using LCD frambuffer at %p\n", lcd_base);
@ -886,7 +899,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)
ushort *cmap_base = NULL;
ushort i, j;
uchar *fb;
bmp_image_t *bmp=(bmp_image_t *)bmp_image;
bmp_image_t *bmp = (bmp_image_t *)map_sysmem(bmp_image, 0);
uchar *bmap;
ushort padded_width;
unsigned long width, height, byte_width;

@ -0,0 +1,13 @@
Sandbox LCD
===========
This uses the displaymode.txt binding except that only xres and yres are
required properties.
Example:
lcd {
compatible = "sandbox,lcd-sdl";
xres = <800>;
yres = <600>;
};

@ -11,6 +11,7 @@
*/
#include <common.h>
#include <lcd.h>
#include <os.h>
#include <serial.h>
#include <linux/compiler.h>
@ -60,6 +61,9 @@ static int sandbox_serial_tstc(void)
ssize_t count;
os_usleep(100);
#ifdef CONFIG_LCD
lcd_sync();
#endif
if (next_index == serial_buf_read)
return 1; /* buffer full */

@ -33,6 +33,7 @@ obj-$(CONFIG_VIDEO_MX3) += mx3fb.o videomodes.o
obj-$(CONFIG_VIDEO_IPUV3) += mxc_ipuv3_fb.o ipu_common.o ipu_disp.o
obj-$(CONFIG_VIDEO_MXS) += mxsfb.o videomodes.o
obj-$(CONFIG_VIDEO_OMAP3) += omap3_dss.o
obj-$(CONFIG_VIDEO_SANDBOX_SDL) += sandbox_sdl.o
obj-$(CONFIG_VIDEO_SED13806) += sed13806.o
obj-$(CONFIG_VIDEO_SM501) += sm501.o
obj-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o videomodes.o

@ -0,0 +1,79 @@
/*
* Copyright (c) 2013 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <fdtdec.h>
#include <lcd.h>
#include <malloc.h>
#include <asm/sdl.h>
#include <asm/u-boot-sandbox.h>
DECLARE_GLOBAL_DATA_PTR;
enum {
/* Maximum LCD size we support */
LCD_MAX_WIDTH = 1366,
LCD_MAX_HEIGHT = 768,
LCD_MAX_LOG2_BPP = 4, /* 2^4 = 16 bpp */
};
vidinfo_t panel_info;
void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
{
}
void lcd_ctrl_init(void *lcdbase)
{
/*
* Allocate memory to keep BMP color conversion map. This is required
* for 8 bit BMPs only (hence 256 colors). If malloc fails - keep
* going, it is not even clear if displyaing the bitmap will be
* required on the way up.
*/
panel_info.cmap = malloc(256 * NBITS(panel_info.vl_bpix) / 8);
}
void lcd_enable(void)
{
if (sandbox_sdl_init_display(panel_info.vl_col, panel_info.vl_row,
panel_info.vl_bpix))
puts("LCD init failed\n");
}
int sandbox_lcd_sdl_early_init(void)
{
const void *blob = gd->fdt_blob;
int xres = LCD_MAX_WIDTH, yres = LCD_MAX_HEIGHT;
int node;
int ret = 0;
/*
* The code in common/lcd.c does not cope with not being able to
* set up a frame buffer. It will just happily keep writing to
* invalid memory. So here we make sure that at least some buffer
* is available even if it actually won't be displayed.
*/
node = fdtdec_next_compatible(blob, 0, COMPAT_SANDBOX_LCD_SDL);
if (node >= 0) {
xres = fdtdec_get_int(blob, node, "xres", LCD_MAX_WIDTH);
yres = fdtdec_get_int(blob, node, "yres", LCD_MAX_HEIGHT);
if (xres < 0 || xres > LCD_MAX_WIDTH) {
xres = LCD_MAX_WIDTH;
ret = -EINVAL;
}
if (yres < 0 || yres > LCD_MAX_HEIGHT) {
yres = LCD_MAX_HEIGHT;
ret = -EINVAL;
}
}
panel_info.vl_col = xres;
panel_info.vl_row = yres;
panel_info.vl_bpix = LCD_COLOR16;
return ret;
}

@ -89,6 +89,7 @@ enum fdt_compat_id {
COMPAT_INFINEON_SLB9645_TPM, /* Infineon SLB9645 TPM */
COMPAT_SAMSUNG_EXYNOS5_I2C, /* Exynos5 High Speed I2C Controller */
COMPAT_SANDBOX_HOST_EMULATION, /* Sandbox emulation of a function */
COMPAT_SANDBOX_LCD_SDL, /* Sandbox LCD emulation with SDL */
COMPAT_COUNT,
};

@ -313,6 +313,9 @@ int lcd_get_size(int *line_length);
int lcd_dt_simplefb_add_node(void *blob);
int lcd_dt_simplefb_enable_existing_node(void *blob);
/* Update the LCD / flush the cache */
void lcd_sync(void);
/************************************************************************/
/* ** BITMAP DISPLAY SUPPORT */
/************************************************************************/

@ -62,6 +62,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
COMPAT(INFINEON_SLB9645_TPM, "infineon,slb9645-tpm"),
COMPAT(SAMSUNG_EXYNOS5_I2C, "samsung,exynos5-hsi2c"),
COMPAT(SANDBOX_HOST_EMULATION, "sandbox,host-emulation"),
COMPAT(SANDBOX_LCD_SDL, "sandbox,lcd-sdl"),
};
const char *fdtdec_get_compatible(enum fdt_compat_id id)

Loading…
Cancel
Save