[U-Boot] [PATCH 32/32] sandbox: Add LCD driver

Simon Glass sjg at chromium.org
Sun Nov 10 18:27:18 CET 2013


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
--hide_lcd option to disable it.

Signed-off-by: Simon Glass <sjg at chromium.org>
Signed-off-by: Simon Glass <sjg at chromium.org>
Tested-by: Che-Liang Chiou <clchiou at chromium.org>
---
 arch/sandbox/cpu/sdl.c                        |  4 +-
 arch/sandbox/cpu/start.c                      |  9 ++++
 arch/sandbox/include/asm/state.h              |  1 +
 arch/sandbox/include/asm/u-boot-sandbox.h     |  3 ++
 board/sandbox/sandbox/sandbox.c               | 19 +++++++-
 common/lcd.c                                  | 21 ++++++--
 doc/device-tree-bindings/video/sandbox-fb.txt | 13 +++++
 drivers/serial/sandbox.c                      |  4 ++
 drivers/video/Makefile                        |  1 +
 drivers/video/sandbox_sdl.c                   | 70 +++++++++++++++++++++++++++
 include/fdtdec.h                              |  1 +
 include/lcd.h                                 |  3 ++
 lib/fdtdec.c                                  |  1 +
 13 files changed, 144 insertions(+), 6 deletions(-)
 create mode 100644 doc/device-tree-bindings/video/sandbox-fb.txt
 create mode 100644 drivers/video/sandbox_sdl.c

diff --git a/arch/sandbox/cpu/sdl.c b/arch/sandbox/cpu/sdl.c
index 909e835..917936f 100644
--- a/arch/sandbox/cpu/sdl.c
+++ b/arch/sandbox/cpu/sdl.c
@@ -55,7 +55,9 @@ static int sandbox_sdl_ensure_init(void)
 
 int sandbox_sdl_init_display(int width, int height, int log2_bpp)
 {
-	if (!width)
+	struct sandbox_state *state = state_get_current();
+
+	if (!width || state->hide_lcd)
 		return 0;
 	if (sandbox_sdl_ensure_init())
 		return -1;
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 2d19fe7..6189ded 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.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_hide_lcd(struct sandbox_state *state,
+				       const char *arg)
+{
+	state->hide_lcd = true;
+	return 0;
+}
+SANDBOX_CMDLINE_OPT_SHORT(hide_lcd, 'l', 0,
+			  "Don't show the sandbox LCD display");
+
 int main(int argc, char *argv[])
 {
 	struct sandbox_state *state;
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index 304104e..9263aca 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -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 hide_lcd;			/* Hide LCD on start-up */
 
 	/* Pointer to information for each SPI bus/cs */
 	struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS]
diff --git a/arch/sandbox/include/asm/u-boot-sandbox.h b/arch/sandbox/include/asm/u-boot-sandbox.h
index 5707c27..d2f1b65 100644
--- a/arch/sandbox/include/asm/u-boot-sandbox.h
+++ b/arch/sandbox/include/asm/u-boot-sandbox.h
@@ -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_ */
diff --git a/board/sandbox/sandbox/sandbox.c b/board/sandbox/sandbox/sandbox.c
index 65dcce8..f3ab575 100644
--- a/board/sandbox/sandbox/sandbox.c
+++ b/board/sandbox/sandbox/sandbox.c
@@ -4,8 +4,8 @@
  */
 
 #include <common.h>
-
 #include <os.h>
+#include <asm/u-boot-sandbox.h>
 
 /*
  * Pointer to initial global data area
@@ -33,3 +33,20 @@ int dram_init(void)
 	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
 	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
diff --git a/common/lcd.c b/common/lcd.c
index 5dd7948..bbbede1 100644
--- a/common/lcd.c
+++ b/common/lcd.c
@@ -28,6 +28,8 @@
 #include <watchdog.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
 }
 
@@ -398,7 +411,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 */
 
@@ -489,8 +502,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);
 
@@ -882,7 +895,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;
diff --git a/doc/device-tree-bindings/video/sandbox-fb.txt b/doc/device-tree-bindings/video/sandbox-fb.txt
new file mode 100644
index 0000000..eb91b30
--- /dev/null
+++ b/doc/device-tree-bindings/video/sandbox-fb.txt
@@ -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>;
+	};
diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c
index ffff5e1..c27b5b8 100644
--- a/drivers/serial/sandbox.c
+++ b/drivers/serial/sandbox.c
@@ -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 */
 
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index fed1c9c..d4a20fa 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -32,6 +32,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
diff --git a/drivers/video/sandbox_sdl.c b/drivers/video/sandbox_sdl.c
new file mode 100644
index 0000000..c5f325a
--- /dev/null
+++ b/drivers/video/sandbox_sdl.c
@@ -0,0 +1,70 @@
+/*
+ * 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  = {
+	.vl_col = LCD_XRES,
+	.vl_row = LCD_YRES,
+	.vl_bpix = LCD_COLOR16,
+};
+
+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, yres;
+	int node;
+
+	node = fdtdec_next_compatible(blob, 0, COMPAT_SANDBOX_LCD_SDL);
+	if (node < 0)
+		return 0;
+	xres = fdtdec_get_int(blob, node, "xres", -1);
+	yres = fdtdec_get_int(blob, node, "yres", -1);
+	if (xres == -1 || yres == -1)
+		return -1;
+
+	panel_info.vl_col = xres;
+	panel_info.vl_row = yres;
+	panel_info.vl_bpix = 4;
+
+	return 0;
+}
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 64c34a4..0099ffd 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -88,6 +88,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,
 };
diff --git a/include/lcd.h b/include/lcd.h
index 40e8d2a..9508e1c 100644
--- a/include/lcd.h
+++ b/include/lcd.h
@@ -311,6 +311,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						*/
 /************************************************************************/
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index b2f8b1c..134f8f0 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -61,6 +61,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)
-- 
1.8.4.1



More information about the U-Boot mailing list