[U-Boot] [PATCH v2 25/31] sandbox: Add LCD driver

Simon Glass sjg at chromium.org
Thu Feb 27 21:26:19 CET 2014


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 at chromium.org>
Signed-off-by: Simon Glass <sjg at chromium.org>
---

Changes in v2: None

 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               | 18 ++++++
 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                   | 79 +++++++++++++++++++++++++++
 include/fdtdec.h                              |  1 +
 include/lcd.h                                 |  3 +
 lib/fdtdec.c                                  |  1 +
 12 files changed, 150 insertions(+), 4 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/start.c b/arch/sandbox/cpu/start.c
index 2d19fe7..4d5569e 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_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;
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index 304104e..895b3a4 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 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]
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 eb560ec..b4fd8ee 100644
--- a/board/sandbox/sandbox/sandbox.c
+++ b/board/sandbox/sandbox/sandbox.c
@@ -6,6 +6,7 @@
 #include <common.h>
 #include <cros_ec.h>
 #include <os.h>
+#include <asm/u-boot-sandbox.h>
 
 /*
  * Pointer to initial global data area
@@ -29,6 +30,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
diff --git a/common/lcd.c b/common/lcd.c
index aa81522..19b86b7 100644
--- a/common/lcd.c
+++ b/common/lcd.c
@@ -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;
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 a7f5469..c527029 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -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
diff --git a/drivers/video/sandbox_sdl.c b/drivers/video/sandbox_sdl.c
new file mode 100644
index 0000000..ba4578e
--- /dev/null
+++ b/drivers/video/sandbox_sdl.c
@@ -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;
+}
diff --git a/include/fdtdec.h b/include/fdtdec.h
index bcd2ee5..6e859ce 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -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,
 };
diff --git a/include/lcd.h b/include/lcd.h
index d06d6f1..5f84cd3 100644
--- a/include/lcd.h
+++ b/include/lcd.h
@@ -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						*/
 /************************************************************************/
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index e0b8927..f65ab4f 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -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)
-- 
1.9.0.279.gdc9e3eb



More information about the U-Boot mailing list