[U-Boot] [PATCH V3 0/7] Add splash screen for CM-T35

This patchset adds splash screen support for CM-T35. It includes the ability to initialize the display subsystem either using predefines (selected via env variable "displaytype"), or user supplied configuration options, also stored in an environment variables and pointed to by displaytype. The splash image data is currently read from NAND.
As a preparation for the above functionality this patchset adds: - new DSS #defines - an option for board-specific splash screen preparation, which can be invoked in lcd_logo() right before displaying the splash screen (typical use case: load the image data from non-memory mapped storage in time for it to be displayed). - struct panel_config is extended to support setting the gfx_format dynamically - protection from data aborts due to unaligned bmp headers is added to lcd_logo's splashscreen section (I'm also looking into refining this protection later on).
Changes in V3: - No unnecessary #defines in arch-omap3/dss.h [Wolfgang Denk] - Reworded patch 2 comment [Wolfgang Denk] - Used a #define for cmap addr [Wolfgang Denk]
Changes in V2: - DSS #defines are defined shiften where possible [Jeroen Hofstee] - GFXFORMAT_RGB16 now passed to omap3_dss_panel_config() in a new field of panel_cfg. Updated existing panel_config structs to set this field to the value that was originally hardcoded into omap3_dss_panel_config(). [Jeroen Hofstee] - Used LCD_BPP for vl_bpix. [Jeroen Hofstee] - Added a comment to explain the choice of GFXFORMAT_RGB16. [Jeroen Hofstee] - Added an address check (and fix) to the address of splashimage in order to avoid alignment problems with bmp header. A similar check appears in board_splash_screen_prepare() for cm_t35. [Albert ARIBAUD] - Do not manually set gfx burst size to GFXBURSTSIZE16, as it is apparently not necessary. GFXBURSTSIZE* #defines were kept in patch 1 anyway in the hope they will be useful for someone.
Nikita Kiryanov (7): omap3: add useful dss defines omap3: allow dynamic selection of gfx_format lcd: prevent unaligned memory access when displaying splash screen lcd: add option for board specific splash screen preparation cm-t35: add support for dvi displays cm-t35: add support for user defined lcd parameters cm-t35: add support for loading splash image from NAND
README | 8 + arch/arm/include/asm/arch-omap3/dss.h | 31 +++ board/cm_t35/Makefile | 1 + board/cm_t35/cm_t35.c | 68 ++++++ board/cm_t35/display.c | 428 +++++++++++++++++++++++++++++++++ board/htkw/mcx/mcx.c | 1 + board/teejet/mt_ventoux/mt_ventoux.c | 2 + board/ti/beagle/beagle.h | 6 +- common/lcd.c | 23 ++ drivers/video/omap3_dss.c | 2 +- include/configs/cm_t35.h | 11 + include/lcd.h | 1 + 12 files changed, 579 insertions(+), 3 deletions(-) create mode 100644 board/cm_t35/display.c

Add useful omap3 dss defines for: polarity, TFT data lines, lcd display type, gfx burst size, and gfx format
Cc: Anatolij Gustschin agust@denx.de Cc: Jeroen Hofstee jeroen@myspectrum.nl Cc: Tom Rini trini@ti.com Cc: Wolfgang Denk wd@denx.de Signed-off-by: Nikita Kiryanov nikita@compulab.co.il Signed-off-by: Igor Grinberg grinberg@compulab.co.il --- Changes in V3: - Removed unused #define (burst size) [Wolfgang Denk]
Changes in V2: - GFX format #define values are shifted [Jeroen Hofstee]
arch/arm/include/asm/arch-omap3/dss.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/arch/arm/include/asm/arch-omap3/dss.h b/arch/arm/include/asm/arch-omap3/dss.h index ffaffbb..0cbef84 100644 --- a/arch/arm/include/asm/arch-omap3/dss.h +++ b/arch/arm/include/asm/arch-omap3/dss.h @@ -167,6 +167,36 @@ struct venc_regs { #define VENC_OUT_SEL (1 << 6) #define DIG_LPP_SHIFT 16
+/* LCD display type */ +#define PASSIVE_DISPLAY 0 +#define ACTIVE_DISPLAY 1 + +/* TFTDATALINES */ +#define LCD_INTERFACE_12_BIT 0 +#define LCD_INTERFACE_16_BIT 1 +#define LCD_INTERFACE_18_BIT 2 +#define LCD_INTERFACE_24_BIT 3 + +/* Polarity */ +#define DSS_IVS (1 << 12) +#define DSS_IHS (1 << 13) +#define DSS_IPC (1 << 14) +#define DSS_IEO (1 << 15) + +/* GFX format */ +#define GFXFORMAT_BITMAP1 (0x0 << 1) +#define GFXFORMAT_BITMAP2 (0x1 << 1) +#define GFXFORMAT_BITMAP4 (0x2 << 1) +#define GFXFORMAT_BITMAP8 (0x3 << 1) +#define GFXFORMAT_RGB12 (0x4 << 1) +#define GFXFORMAT_ARGB16 (0x5 << 1) +#define GFXFORMAT_RGB16 (0x6 << 1) +#define GFXFORMAT_RGB24_UNPACKED (0x8 << 1) +#define GFXFORMAT_RGB24_PACKED (0x9 << 1) +#define GFXFORMAT_ARGB32 (0xC << 1) +#define GFXFORMAT_RGBA32 (0xD << 1) +#define GFXFORMAT_RGBx32 (0xE << 1) + /* Panel Configuration */ struct panel_config { u32 timing_h;

Currently, omap3_dss_panel_config() sets gfx_format to a value that is hardcoded in the code. This forces anyone who wants to use a different gfx_format to make adjustments after calling omap3_dss_panel_config(). This could be avoided if the value of gfx_format were parameterized as input for omap3_dss_panel_config().
Make gfx_format a field in struct panel_config, and update existing structs to set this field to the value that was originally hard coded.
Cc: Wolfgang Denk wd@denx.de Cc: Jeroen Hofstee jeroen@myspectrum.nl Cc: Tom Rini trini@ti.com Cc: Anatolij Gustschin agust@denx.de Signed-off-by: Nikita Kiryanov nikita@compulab.co.il Signed-off-by: Igor Grinberg grinberg@compulab.co.il --- Changes in V3: - Commit message rephrased [Wolfgang Denk]
Changes in V2: None. Patch introduced in V2.
arch/arm/include/asm/arch-omap3/dss.h | 1 + board/htkw/mcx/mcx.c | 1 + board/teejet/mt_ventoux/mt_ventoux.c | 2 ++ board/ti/beagle/beagle.h | 6 ++++-- drivers/video/omap3_dss.c | 2 +- 5 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/arch/arm/include/asm/arch-omap3/dss.h b/arch/arm/include/asm/arch-omap3/dss.h index 0cbef84..ae0babf 100644 --- a/arch/arm/include/asm/arch-omap3/dss.h +++ b/arch/arm/include/asm/arch-omap3/dss.h @@ -208,6 +208,7 @@ struct panel_config { u32 data_lines; u32 load_mode; u32 panel_color; + u32 gfx_format; void *frame_buffer; };
diff --git a/board/htkw/mcx/mcx.c b/board/htkw/mcx/mcx.c index 9fe6408..5eda6c4 100644 --- a/board/htkw/mcx/mcx.c +++ b/board/htkw/mcx/mcx.c @@ -130,6 +130,7 @@ static struct panel_config lcd_cfg = { .load_mode = 0x02, /* Frame Mode */ .panel_color = 0, .lcd_size = PANEL_LCD_SIZE(800, 480), + .gfx_format = GFXFORMAT_RGB24_UNPACKED, };
int board_video_init(void) diff --git a/board/teejet/mt_ventoux/mt_ventoux.c b/board/teejet/mt_ventoux/mt_ventoux.c index c516c75..78d81d6 100644 --- a/board/teejet/mt_ventoux/mt_ventoux.c +++ b/board/teejet/mt_ventoux/mt_ventoux.c @@ -81,6 +81,7 @@ static struct panel_config lcd_cfg[] = { .data_lines = 0x03, /* 24 Bit RGB */ .load_mode = 0x02, /* Frame Mode */ .panel_color = 0, + .gfx_format = GFXFORMAT_RGB24_UNPACKED, }, { .timing_h = PANEL_TIMING_H(20, 192, 4), @@ -91,6 +92,7 @@ static struct panel_config lcd_cfg[] = { .data_lines = 0x03, /* 24 Bit RGB */ .load_mode = 0x02, /* Frame Mode */ .panel_color = 0, + .gfx_format = GFXFORMAT_RGB24_UNPACKED, } }; #endif diff --git a/board/ti/beagle/beagle.h b/board/ti/beagle/beagle.h index c0a94a9..6d71bbc 100644 --- a/board/ti/beagle/beagle.h +++ b/board/ti/beagle/beagle.h @@ -544,7 +544,8 @@ static const struct panel_config dvid_cfg = { .panel_type = 0x01, /* TFT */ .data_lines = 0x03, /* 24 Bit RGB */ .load_mode = 0x02, /* Frame Mode */ - .panel_color = DVI_BEAGLE_ORANGE_COL /* ORANGE */ + .panel_color = DVI_BEAGLE_ORANGE_COL, /* ORANGE */ + .gfx_format = GFXFORMAT_RGB24_UNPACKED, };
static const struct panel_config dvid_cfg_xm = { @@ -556,6 +557,7 @@ static const struct panel_config dvid_cfg_xm = { .panel_type = 0x01, /* TFT */ .data_lines = 0x03, /* 24 Bit RGB */ .load_mode = 0x02, /* Frame Mode */ - .panel_color = DVI_BEAGLE_ORANGE_COL /* ORANGE */ + .panel_color = DVI_BEAGLE_ORANGE_COL, /* ORANGE */ + .gfx_format = GFXFORMAT_RGB24_UNPACKED, }; #endif diff --git a/drivers/video/omap3_dss.c b/drivers/video/omap3_dss.c index b1424bf..6efba12 100644 --- a/drivers/video/omap3_dss.c +++ b/drivers/video/omap3_dss.c @@ -121,7 +121,7 @@ void omap3_dss_panel_config(const struct panel_config *panel_cfg) if (!panel_cfg->frame_buffer) return;
- writel(8 << GFX_FORMAT_SHIFT | GFX_ENABLE, &dispc->gfx_attributes); + writel(panel_cfg->gfx_format | GFX_ENABLE, &dispc->gfx_attributes); writel(1, &dispc->gfx_row_inc); writel(1, &dispc->gfx_pixel_inc); writel(panel_cfg->lcd_size, &dispc->gfx_size);

When the bmp file is loaded to an address specified by the environment variable "splashimage", its header members might be unaligned. This happens because the bmp header starts with two byte size fields followd by mostly 32 bit fields. When the address in splashimage is not equal to aligned address plus/minus 2, the 32 bit members will be placed in unaligned addresses and the result would be a data abort on targets that cannot handle unaligned memory accesses.
Check that the address is safe to use, and fix it if it's not.
Cc: Anatolij Gustschin agust@denx.de Cc: Albert ARIBAUD albert.u.boot@aribaud.net Cc: Jeroen Hofstee jeroen@myspectrum.nl Signed-off-by: Nikita Kiryanov nikita@compulab.co.il Signed-off-by: Igor Grinberg grinberg@compulab.co.il --- Changes in V2: None. Patch introduced in V2.
common/lcd.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/common/lcd.c b/common/lcd.c index 66d4f94..104125d 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -1046,6 +1046,14 @@ static void *lcd_logo(void) do_splash = 0;
addr = simple_strtoul (s, NULL, 16); + /* + * In order for the fields of bmp header to be properly aligned + * in memory, splash image addr must be aligned to "aligned + * address plus 2". Fix addr if necessary. + */ + if (addr % 4 != 2) + addr += (addr % 4) ?: 2; + #ifdef CONFIG_SPLASH_SCREEN_ALIGN s = getenv("splashpos"); if (s != NULL) {

Following the discussion in the "Create an API for safely accessing BMP header fields" patch series, this patch should be dropped.
On 01/31/2013 09:39 AM, Nikita Kiryanov wrote:
When the bmp file is loaded to an address specified by the environment variable "splashimage", its header members might be unaligned. This happens because the bmp header starts with two byte size fields followd by mostly 32 bit fields. When the address in splashimage is not equal to aligned address plus/minus 2, the 32 bit members will be placed in unaligned addresses and the result would be a data abort on targets that cannot handle unaligned memory accesses.
Check that the address is safe to use, and fix it if it's not.
Cc: Anatolij Gustschin agust@denx.de Cc: Albert ARIBAUD albert.u.boot@aribaud.net Cc: Jeroen Hofstee jeroen@myspectrum.nl Signed-off-by: Nikita Kiryanov nikita@compulab.co.il Signed-off-by: Igor Grinberg grinberg@compulab.co.il
Changes in V2: None. Patch introduced in V2.
common/lcd.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/common/lcd.c b/common/lcd.c index 66d4f94..104125d 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -1046,6 +1046,14 @@ static void *lcd_logo(void) do_splash = 0;
addr = simple_strtoul (s, NULL, 16);
/*
* In order for the fields of bmp header to be properly aligned
* in memory, splash image addr must be aligned to "aligned
* address plus 2". Fix addr if necessary.
*/
if (addr % 4 != 2)
addr += (addr % 4) ?: 2;
- #ifdef CONFIG_SPLASH_SCREEN_ALIGN s = getenv("splashpos"); if (s != NULL) {

Currently there is no logical place to put the code that prepares the splash image data. The splash image data should be ready in memory before bmp_display() is called, and after the environment is ready (since lcd.c looks for the splash image in an address specified by the environment variable "splashimage").
Our window of opportunity in board_init_r() is therefore: between env_relocate() and bmp_display(), and from the available options only the lcd related functions in drv_lcd_init() seem appropriate for such lcd oriented code.
Add the option to prepare the splash image data in lcd_logo() right before it is sent to be displayed.
Cc: Anatolij Gustschin agust@denx.de Cc: Jeroen Hofstee jeroen@myspectrum.nl Signed-off-by: Nikita Kiryanov nikita@compulab.co.il Signed-off-by: Igor Grinberg grinberg@compulab.co.il --- README | 8 ++++++++ common/lcd.c | 15 +++++++++++++++ include/lcd.h | 1 + 3 files changed, 24 insertions(+)
diff --git a/README b/README index a336476..89694d7 100644 --- a/README +++ b/README @@ -1550,6 +1550,14 @@ CBFS (Coreboot Filesystem) support => vertically centered image at x = dspWidth - bmpWidth - 9
+ CONFIG_SPLASH_SCREEN_PREPARE + + If this option is set then the board_splash_screen_prepare() + function, which must be defined in your code, is called as part + of the splash screen display sequence. It gives the board an + opportunity to prepare the splash image data before it is + processed and sent to the frame buffer by U-Boot. + - Gzip compressed BMP image support: CONFIG_VIDEO_BMP_GZIP
If this option is set, additionally to standard BMP diff --git a/common/lcd.c b/common/lcd.c index 104125d..bb8a7d2 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -1034,6 +1034,18 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) } #endif
+#ifdef CONFIG_SPLASH_SCREEN_PREPARE +static inline int splash_screen_prepare(void) +{ + return board_splash_screen_prepare(); +} +#else +static inline int splash_screen_prepare(void) +{ + return 0; +} +#endif + static void *lcd_logo(void) { #ifdef CONFIG_SPLASH_SCREEN @@ -1045,6 +1057,9 @@ static void *lcd_logo(void) int x = 0, y = 0; do_splash = 0;
+ if (splash_screen_prepare()) + return (void *)gd->fb_base; + addr = simple_strtoul (s, NULL, 16); /* * In order for the fields of bmp header to be properly aligned diff --git a/include/lcd.h b/include/lcd.h index c24164a..4ac4ddd 100644 --- a/include/lcd.h +++ b/include/lcd.h @@ -47,6 +47,7 @@ extern struct vidinfo panel_info;
extern void lcd_ctrl_init (void *lcdbase); extern void lcd_enable (void); +extern int board_splash_screen_prepare(void);
/* setcolreg used in 8bpp/16bpp; initcolregs used in monochrome */ extern void lcd_setcolreg (ushort regno,

Add support for dvi displays with user selectable dvi presets.
Cc: Wolfgang Denk wd@denx.de Cc: Jeroen Hofstee jeroen@myspectrum.nl Cc: Anatolij Gustschin agust@denx.de Signed-off-by: Nikita Kiryanov nikita@compulab.co.il Signed-off-by: Igor Grinberg grinberg@compulab.co.il --- Changes in V3: - Added a #define for CMAP [Wolfgang Denk]
Changes in V2: - Used LCD_BPP for vl_bpix [Jeroen Hofstee] - GFXFORMAT_RGB16 now passed to omap3_dss_panel_config() as part of panel_cfg predefines. [Jeroen Hofstee] - Added a comment to explain the choice of GFXFORMAT_RGB16. [Jeroen Hofstee] - Do not set gfx burst size to GFXBURSTSIZE16, as it is apparently not necessary.
board/cm_t35/Makefile | 1 + board/cm_t35/cm_t35.c | 3 + board/cm_t35/display.c | 220 ++++++++++++++++++++++++++++++++++++++++++++++ include/configs/cm_t35.h | 7 ++ 4 files changed, 231 insertions(+) create mode 100644 board/cm_t35/display.c
diff --git a/board/cm_t35/Makefile b/board/cm_t35/Makefile index 894fa09..bde56e6 100644 --- a/board/cm_t35/Makefile +++ b/board/cm_t35/Makefile @@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).o
COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += eeprom.o +COBJS-$(CONFIG_LCD) += display.o
COBJS := cm_t35.o leds.o $(COBJS-y)
diff --git a/board/cm_t35/cm_t35.c b/board/cm_t35/cm_t35.c index edbb941..8f3d735 100644 --- a/board/cm_t35/cm_t35.c +++ b/board/cm_t35/cm_t35.c @@ -216,6 +216,9 @@ static void cm_t3x_set_common_muxconf(void) /* SB-T35 Ethernet */ MUX_VAL(CP(GPMC_NCS4), (IEN | PTU | EN | M0)); /*GPMC_nCS4*/
+ /* DVI enable */ + MUX_VAL(CP(GPMC_NCS3), (IDIS | PTU | DIS | M4));/*GPMC_nCS3*/ + /* CM-T3x Ethernet */ MUX_VAL(CP(GPMC_NCS5), (IDIS | PTU | DIS | M0)); /*GPMC_nCS5*/ MUX_VAL(CP(GPMC_CLK), (IEN | PTD | DIS | M4)); /*GPIO_59*/ diff --git a/board/cm_t35/display.c b/board/cm_t35/display.c new file mode 100644 index 0000000..43f0628 --- /dev/null +++ b/board/cm_t35/display.c @@ -0,0 +1,220 @@ +/* + * (C) Copyright 2012 CompuLab, Ltd. <www.compulab.co.il> + * + * Authors: Nikita Kiryanov nikita@compulab.co.il + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc. + */ +#include <common.h> +#include <asm/gpio.h> +#include <asm/io.h> +#include <stdio_dev.h> +#include <asm/arch/dss.h> +#include <lcd.h> +#include <asm/arch-omap3/dss.h> + +DECLARE_GLOBAL_DATA_PTR; + +enum display_type { + NONE, + DVI, +}; + +#define CMAP_ADDR 0x80100000 + +/* + * The frame buffer is allocated before we have the chance to parse user input. + * To make sure enough memory is allocated for all resolutions, we define + * vl_{col | row} to the maximal resolution supported by OMAP3. + */ +vidinfo_t panel_info = { + .vl_col = 1400, + .vl_row = 1050, + .vl_bpix = LCD_BPP, + .cmap = (ushort *)CMAP_ADDR, +}; + +static struct panel_config panel_cfg; +static enum display_type lcd_def; + +/* + * A note on DVI presets; + * U-Boot can convert 8 bit BMP data to 16 bit BMP data, and OMAP DSS can + * convert 16 bit data into 24 bit data. Thus, GFXFORMAT_RGB16 allows us to + * support two BMP types with one setting. + */ +static const struct panel_config preset_dvi_640X480 = { + .lcd_size = PANEL_LCD_SIZE(640, 480), + .timing_h = DSS_HBP(48) | DSS_HFP(16) | DSS_HSW(96), + .timing_v = DSS_VBP(33) | DSS_VFP(10) | DSS_VSW(2), + .divisor = 12 | (1 << 16), + .data_lines = LCD_INTERFACE_24_BIT, + .panel_type = ACTIVE_DISPLAY, + .load_mode = 2, + .gfx_format = GFXFORMAT_RGB16, +}; + +static const struct panel_config preset_dvi_800X600 = { + .lcd_size = PANEL_LCD_SIZE(800, 600), + .timing_h = DSS_HBP(88) | DSS_HFP(40) | DSS_HSW(128), + .timing_v = DSS_VBP(23) | DSS_VFP(1) | DSS_VSW(4), + .divisor = 8 | (1 << 16), + .data_lines = LCD_INTERFACE_24_BIT, + .panel_type = ACTIVE_DISPLAY, + .load_mode = 2, + .gfx_format = GFXFORMAT_RGB16, +}; + +static const struct panel_config preset_dvi_1024X768 = { + .lcd_size = PANEL_LCD_SIZE(1024, 768), + .timing_h = DSS_HBP(160) | DSS_HFP(24) | DSS_HSW(136), + .timing_v = DSS_VBP(29) | DSS_VFP(3) | DSS_VSW(6), + .divisor = 5 | (1 << 16), + .data_lines = LCD_INTERFACE_24_BIT, + .panel_type = ACTIVE_DISPLAY, + .load_mode = 2, + .gfx_format = GFXFORMAT_RGB16, +}; + +static const struct panel_config preset_dvi_1152X864 = { + .lcd_size = PANEL_LCD_SIZE(1152, 864), + .timing_h = DSS_HBP(256) | DSS_HFP(64) | DSS_HSW(128), + .timing_v = DSS_VBP(32) | DSS_VFP(1) | DSS_VSW(3), + .divisor = 3 | (1 << 16), + .data_lines = LCD_INTERFACE_24_BIT, + .panel_type = ACTIVE_DISPLAY, + .load_mode = 2, + .gfx_format = GFXFORMAT_RGB16, +}; + +static const struct panel_config preset_dvi_1280X960 = { + .lcd_size = PANEL_LCD_SIZE(1280, 960), + .timing_h = DSS_HBP(312) | DSS_HFP(96) | DSS_HSW(112), + .timing_v = DSS_VBP(36) | DSS_VFP(1) | DSS_VSW(3), + .divisor = 3 | (1 << 16), + .data_lines = LCD_INTERFACE_24_BIT, + .panel_type = ACTIVE_DISPLAY, + .load_mode = 2, + .gfx_format = GFXFORMAT_RGB16, +}; + +static const struct panel_config preset_dvi_1280X1024 = { + .lcd_size = PANEL_LCD_SIZE(1280, 1024), + .timing_h = DSS_HBP(248) | DSS_HFP(48) | DSS_HSW(112), + .timing_v = DSS_VBP(38) | DSS_VFP(1) | DSS_VSW(3), + .divisor = 3 | (1 << 16), + .data_lines = LCD_INTERFACE_24_BIT, + .panel_type = ACTIVE_DISPLAY, + .load_mode = 2, + .gfx_format = GFXFORMAT_RGB16, +}; + +/* + * set_resolution_params() + * + * Due to usage of multiple display related APIs resolution data is located in + * more than one place. This function updates them all. + */ +static void set_resolution_params(int x, int y) +{ + panel_cfg.lcd_size = PANEL_LCD_SIZE(x, y); + panel_info.vl_col = x; + panel_info.vl_row = y; + lcd_line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8; +} + +static void set_preset(const struct panel_config preset, int x_res, int y_res) +{ + panel_cfg = preset; + set_resolution_params(x_res, y_res); +} + +static enum display_type set_dvi_preset(const struct panel_config preset, + int x_res, int y_res) +{ + set_preset(preset, x_res, y_res); + return DVI; +} + +/* + * env_parse_displaytype() - parse display type. + * + * Parses the environment variable "displaytype", which contains the + * name of the display type or preset, in which case it applies its + * configurations. + * + * Returns the type of display that was specified. + */ +static enum display_type env_parse_displaytype(char *displaytype) +{ + if (!strncmp(displaytype, "dvi640x480", 10)) + return set_dvi_preset(preset_dvi_640X480, 640, 480); + else if (!strncmp(displaytype, "dvi800x600", 10)) + return set_dvi_preset(preset_dvi_800X600, 800, 600); + else if (!strncmp(displaytype, "dvi1024x768", 11)) + return set_dvi_preset(preset_dvi_1024X768, 1024, 768); + else if (!strncmp(displaytype, "dvi1152x864", 11)) + return set_dvi_preset(preset_dvi_1152X864, 1152, 864); + else if (!strncmp(displaytype, "dvi1280x960", 11)) + return set_dvi_preset(preset_dvi_1280X960, 1280, 960); + else if (!strncmp(displaytype, "dvi1280x1024", 12)) + return set_dvi_preset(preset_dvi_1280X1024, 1280, 1024); + + return NONE; +} + +int lcd_line_length; +int lcd_color_fg; +int lcd_color_bg; +void *lcd_base; +short console_col; +short console_row; +void *lcd_console_address; + +void lcd_ctrl_init(void *lcdbase) +{ + struct prcm *prcm = (struct prcm *)PRCM_BASE; + char *displaytype = getenv("displaytype"); + + if (displaytype == NULL) + return; + + lcd_def = env_parse_displaytype(displaytype); + if (lcd_def == NONE) + return; + + panel_cfg.frame_buffer = lcdbase; + omap3_dss_panel_config(&panel_cfg); + /* + * Pixel clock is defined with many divisions and only few + * multiplications of the system clock. Since DSS FCLK divisor is set + * to 16 by default, we need to set it to a smaller value, like 3 + * (chosen via trial and error). + */ + clrsetbits_le32(&prcm->clksel_dss, 0xF, 3); +} + +void lcd_enable(void) +{ + if (lcd_def == DVI) { + gpio_direction_output(54, 0); /* Turn on DVI */ + omap3_dss_enable(); + } +} + +void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) {} diff --git a/include/configs/cm_t35.h b/include/configs/cm_t35.h index 7d07215..46d35ba 100644 --- a/include/configs/cm_t35.h +++ b/include/configs/cm_t35.h @@ -338,4 +338,11 @@ #define CONFIG_OMAP3_GPIO_6 /* GPIO186 is in GPIO bank 6 */ #endif
+/* Display Configuration */ +#define CONFIG_OMAP3_GPIO_2 +#define CONFIG_VIDEO_OMAP3 +#define LCD_BPP LCD_COLOR16 + +#define CONFIG_LCD + #endif /* __CONFIG_H */

Add support for user defined lcd parameters for cm-t35 splash screen.
Cc: Jeroen Hofstee jeroen@myspectrum.nl Cc: Anatolij Gustschin agust@denx.de Signed-off-by: Nikita Kiryanov nikita@compulab.co.il Signed-off-by: Igor Grinberg grinberg@compulab.co.il --- Changes in V2: - Set gfx_format to GFXFORMAT_RGB16 after parsing custom lcd settings.
board/cm_t35/display.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 211 insertions(+), 3 deletions(-)
diff --git a/board/cm_t35/display.c b/board/cm_t35/display.c index 43f0628..2f78bad 100644 --- a/board/cm_t35/display.c +++ b/board/cm_t35/display.c @@ -3,6 +3,8 @@ * * Authors: Nikita Kiryanov nikita@compulab.co.il * + * Parsing code based on linux/drivers/video/pxafb.c + * * See file CREDITS for list of people who contributed to this * project. * @@ -33,6 +35,7 @@ DECLARE_GLOBAL_DATA_PTR; enum display_type { NONE, DVI, + DVI_CUSTOM, };
#define CMAP_ADDR 0x80100000 @@ -152,6 +155,206 @@ static enum display_type set_dvi_preset(const struct panel_config preset, }
/* + * parse_mode() - parse the mode parameter of custom lcd settings + * + * @mode: <res_x>x<res_y> + * + * Returns -1 on error, 0 on success. + */ +static int parse_mode(const char *mode) +{ + unsigned int modelen = strlen(mode); + int res_specified = 0; + unsigned int xres = 0, yres = 0; + int yres_specified = 0; + int i; + + for (i = modelen - 1; i >= 0; i--) { + switch (mode[i]) { + case 'x': + if (!yres_specified) { + yres = simple_strtoul(&mode[i + 1], NULL, 0); + yres_specified = 1; + } else { + goto done_parsing; + } + + break; + case '0' ... '9': + break; + default: + goto done_parsing; + } + } + + if (i < 0 && yres_specified) { + xres = simple_strtoul(mode, NULL, 0); + res_specified = 1; + } + +done_parsing: + if (res_specified) { + set_resolution_params(xres, yres); + } else { + printf("LCD: invalid mode: %s\n", mode); + return -1; + } + + return 0; +} + +#define PIXEL_CLK_NUMERATOR (26 * 432 / 39) +/* + * parse_pixclock() - Parse the pixclock parameter of custom lcd settings + * + * @pixclock: the desired pixel clock + * + * Returns -1 on error, 0 on success. + * + * Handling the pixel_clock: + * + * Pixel clock is defined in the OMAP35x TRM as follows: + * pixel_clock = + * (SYS_CLK * 2 * PRCM.CM_CLKSEL2_PLL[18:8]) / + * (DSS.DISPC_DIVISOR[23:16] * DSS.DISPC_DIVISOR[6:0] * + * PRCM.CM_CLKSEL_DSS[4:0] * (PRCM.CM_CLKSEL2_PLL[6:0] + 1)) + * + * In practice, this means that in order to set the + * divisor for the desired pixel clock one needs to + * solve the following equation: + * + * 26 * 432 / (39 * <pixel_clock>) = DSS.DISPC_DIVISOR[6:0] + * + * NOTE: the explicit equation above is reduced. Do not + * try to infer anything from these numbers. + */ +static int parse_pixclock(char *pixclock) +{ + int divisor, pixclock_val; + char *pixclk_start = pixclock; + + pixclock_val = simple_strtoul(pixclock, &pixclock, 10); + divisor = DIV_ROUND_UP(PIXEL_CLK_NUMERATOR, pixclock_val); + /* 0 and 1 are illegal values for PCD */ + if (divisor <= 1) + divisor = 2; + + panel_cfg.divisor = divisor | (1 << 16); + if (pixclock[0] != '\0') { + printf("LCD: invalid value for pixclock:%s\n", pixclk_start); + return -1; + } + + return 0; +} + +/* + * parse_setting() - parse a single setting of custom lcd parameters + * + * @setting: The custom lcd setting <name>:<value> + * + * Returns -1 on failure, 0 on success. + */ +static int parse_setting(char *setting) +{ + int num_val; + char *setting_start = setting; + + if (!strncmp(setting, "mode:", 5)) { + return parse_mode(setting + 5); + } else if (!strncmp(setting, "pixclock:", 9)) { + return parse_pixclock(setting + 9); + } else if (!strncmp(setting, "left:", 5)) { + num_val = simple_strtoul(setting + 5, &setting, 0); + panel_cfg.timing_h |= DSS_HBP(num_val); + } else if (!strncmp(setting, "right:", 6)) { + num_val = simple_strtoul(setting + 6, &setting, 0); + panel_cfg.timing_h |= DSS_HFP(num_val); + } else if (!strncmp(setting, "upper:", 6)) { + num_val = simple_strtoul(setting + 6, &setting, 0); + panel_cfg.timing_v |= DSS_VBP(num_val); + } else if (!strncmp(setting, "lower:", 6)) { + num_val = simple_strtoul(setting + 6, &setting, 0); + panel_cfg.timing_v |= DSS_VFP(num_val); + } else if (!strncmp(setting, "hsynclen:", 9)) { + num_val = simple_strtoul(setting + 9, &setting, 0); + panel_cfg.timing_h |= DSS_HSW(num_val); + } else if (!strncmp(setting, "vsynclen:", 9)) { + num_val = simple_strtoul(setting + 9, &setting, 0); + panel_cfg.timing_v |= DSS_VSW(num_val); + } else if (!strncmp(setting, "hsync:", 6)) { + if (simple_strtoul(setting + 6, &setting, 0) == 0) + panel_cfg.pol_freq |= DSS_IHS; + else + panel_cfg.pol_freq &= ~DSS_IHS; + } else if (!strncmp(setting, "vsync:", 6)) { + if (simple_strtoul(setting + 6, &setting, 0) == 0) + panel_cfg.pol_freq |= DSS_IVS; + else + panel_cfg.pol_freq &= ~DSS_IVS; + } else if (!strncmp(setting, "outputen:", 9)) { + if (simple_strtoul(setting + 9, &setting, 0) == 0) + panel_cfg.pol_freq |= DSS_IEO; + else + panel_cfg.pol_freq &= ~DSS_IEO; + } else if (!strncmp(setting, "pixclockpol:", 12)) { + if (simple_strtoul(setting + 12, &setting, 0) == 0) + panel_cfg.pol_freq |= DSS_IPC; + else + panel_cfg.pol_freq &= ~DSS_IPC; + } else if (!strncmp(setting, "active", 6)) { + panel_cfg.panel_type = ACTIVE_DISPLAY; + return 0; /* Avoid sanity check below */ + } else if (!strncmp(setting, "passive", 7)) { + panel_cfg.panel_type = PASSIVE_DISPLAY; + return 0; /* Avoid sanity check below */ + } else if (!strncmp(setting, "display:", 8)) { + if (!strncmp(setting + 8, "dvi", 3)) { + lcd_def = DVI_CUSTOM; + return 0; /* Avoid sanity check below */ + } + } else { + printf("LCD: unknown option %s\n", setting_start); + return -1; + } + + if (setting[0] != '\0') { + printf("LCD: invalid value for %s\n", setting_start); + return -1; + } + + return 0; +} + +/* + * env_parse_customlcd() - parse custom lcd params from an environment variable. + * + * @custom_lcd_params: The environment variable containing the lcd params. + * + * Returns -1 on failure, 0 on success. + */ +static int parse_customlcd(char *custom_lcd_params) +{ + char params_cpy[160]; + char *setting; + + strncpy(params_cpy, custom_lcd_params, 160); + setting = strtok(params_cpy, ","); + while (setting) { + if (parse_setting(setting) < 0) + return -1; + + setting = strtok(NULL, ","); + } + + /* Currently we don't support changing this via custom lcd params */ + panel_cfg.data_lines = LCD_INTERFACE_24_BIT; + panel_cfg.gfx_format = GFXFORMAT_RGB16; /* See dvi predefines note */ + + return 0; +} + +/* * env_parse_displaytype() - parse display type. * * Parses the environment variable "displaytype", which contains the @@ -189,14 +392,19 @@ void *lcd_console_address; void lcd_ctrl_init(void *lcdbase) { struct prcm *prcm = (struct prcm *)PRCM_BASE; + char *custom_lcd; char *displaytype = getenv("displaytype");
if (displaytype == NULL) return;
lcd_def = env_parse_displaytype(displaytype); - if (lcd_def == NONE) - return; + /* If we did not recognize the preset, check if it's an env variable */ + if (lcd_def == NONE) { + custom_lcd = getenv(displaytype); + if (custom_lcd == NULL || parse_customlcd(custom_lcd) < 0) + return; + }
panel_cfg.frame_buffer = lcdbase; omap3_dss_panel_config(&panel_cfg); @@ -211,7 +419,7 @@ void lcd_ctrl_init(void *lcdbase)
void lcd_enable(void) { - if (lcd_def == DVI) { + if (lcd_def == DVI || lcd_def == DVI_CUSTOM) { gpio_direction_output(54, 0); /* Turn on DVI */ omap3_dss_enable(); }

Add support for loading splash image from NAND
Cc: Anatolij Gustschin agust@denx.de Cc: Jeroen Hofstee jeroen@myspectrum.nl Signed-off-by: Nikita Kiryanov nikita@compulab.co.il Signed-off-by: Igor Grinberg grinberg@compulab.co.il --- Changes in V2: - Added fix to bmp_load_addr to comply with what happens in lcd.c following patch number 3.
board/cm_t35/cm_t35.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++ include/configs/cm_t35.h | 4 +++ 2 files changed, 69 insertions(+)
diff --git a/board/cm_t35/cm_t35.c b/board/cm_t35/cm_t35.c index 8f3d735..5fd71f9 100644 --- a/board/cm_t35/cm_t35.c +++ b/board/cm_t35/cm_t35.c @@ -33,7 +33,9 @@ #include <net.h> #include <i2c.h> #include <usb.h> +#include <nand.h> #include <twl4030.h> +#include <bmp_layout.h> #include <linux/compiler.h>
#include <asm/io.h> @@ -75,6 +77,69 @@ static u32 gpmc_nand_config[GPMC_MAX_REG] = { 0, };
+#ifdef CONFIG_LCD +#ifdef CONFIG_CMD_NAND +static int splash_load_from_nand(u32 bmp_load_addr) +{ + struct bmp_header *bmp_hdr; + int res, splash_screen_nand_offset = 0x100000; + size_t bmp_size, bmp_header_size = sizeof(struct bmp_header); + + if (bmp_load_addr + bmp_header_size >= gd->start_addr_sp) + goto splash_address_too_high; + + res = nand_read_skip_bad(&nand_info[nand_curr_device], + splash_screen_nand_offset, &bmp_header_size, + (u_char *)bmp_load_addr); + if (res < 0) + return res; + + bmp_hdr = (struct bmp_header *)bmp_load_addr; + bmp_size = le32_to_cpu(bmp_hdr->file_size); + + if (bmp_load_addr + bmp_size >= gd->start_addr_sp) + goto splash_address_too_high; + + return nand_read_skip_bad(&nand_info[nand_curr_device], + splash_screen_nand_offset, &bmp_size, + (u_char *)bmp_load_addr); + +splash_address_too_high: + printf("Error: splashimage address too high. Data overwrites U-Boot " + "and/or placed beyond DRAM boundaries.\n"); + + return -1; +} +#else +static inline int splash_load_from_nand(void) +{ + return -1; +} +#endif /* CONFIG_CMD_NAND */ + +int board_splash_screen_prepare(void) +{ + char *env_splashimage_value; + u32 bmp_load_addr; + + env_splashimage_value = getenv("splashimage"); + if (env_splashimage_value == NULL) + return -1; + + bmp_load_addr = simple_strtoul(env_splashimage_value, 0, 16); + if (bmp_load_addr == 0) { + printf("Error: bad splashimage address specified\n"); + return -1; + } + + /* Fix bmp_load_addr to the alignment that lcd.c expects */ + if (bmp_load_addr % 4 != 2) + bmp_load_addr += (bmp_load_addr % 4) ?: 2; + + return splash_load_from_nand(bmp_load_addr); +} +#endif /* CONFIG_LCD */ + /* * Routine: board_init * Description: hardware init. diff --git a/include/configs/cm_t35.h b/include/configs/cm_t35.h index 46d35ba..53c4e3c 100644 --- a/include/configs/cm_t35.h +++ b/include/configs/cm_t35.h @@ -344,5 +344,9 @@ #define LCD_BPP LCD_COLOR16
#define CONFIG_LCD +#define CONFIG_SPLASH_SCREEN +#define CONFIG_CMD_BMP +#define CONFIG_BMP_16BPP +#define CONFIG_SPLASH_SCREEN_PREPARE
#endif /* __CONFIG_H */

Following the discussion in "Create an API for safely accessing BMP header fields", this patch should be reverted to V1:
http://patchwork.ozlabs.org/patch/207950/
On 01/31/2013 09:40 AM, Nikita Kiryanov wrote:
Add support for loading splash image from NAND
Cc: Anatolij Gustschin agust@denx.de Cc: Jeroen Hofstee jeroen@myspectrum.nl Signed-off-by: Nikita Kiryanov nikita@compulab.co.il Signed-off-by: Igor Grinberg grinberg@compulab.co.il
Changes in V2:
- Added fix to bmp_load_addr to comply with what happens in lcd.c
following patch number 3.
board/cm_t35/cm_t35.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++ include/configs/cm_t35.h | 4 +++ 2 files changed, 69 insertions(+)
diff --git a/board/cm_t35/cm_t35.c b/board/cm_t35/cm_t35.c index 8f3d735..5fd71f9 100644 --- a/board/cm_t35/cm_t35.c +++ b/board/cm_t35/cm_t35.c @@ -33,7 +33,9 @@ #include <net.h> #include <i2c.h> #include <usb.h> +#include <nand.h> #include <twl4030.h> +#include <bmp_layout.h> #include <linux/compiler.h>
#include <asm/io.h> @@ -75,6 +77,69 @@ static u32 gpmc_nand_config[GPMC_MAX_REG] = { 0, };
+#ifdef CONFIG_LCD +#ifdef CONFIG_CMD_NAND +static int splash_load_from_nand(u32 bmp_load_addr) +{
- struct bmp_header *bmp_hdr;
- int res, splash_screen_nand_offset = 0x100000;
- size_t bmp_size, bmp_header_size = sizeof(struct bmp_header);
- if (bmp_load_addr + bmp_header_size >= gd->start_addr_sp)
goto splash_address_too_high;
- res = nand_read_skip_bad(&nand_info[nand_curr_device],
splash_screen_nand_offset, &bmp_header_size,
(u_char *)bmp_load_addr);
- if (res < 0)
return res;
- bmp_hdr = (struct bmp_header *)bmp_load_addr;
- bmp_size = le32_to_cpu(bmp_hdr->file_size);
- if (bmp_load_addr + bmp_size >= gd->start_addr_sp)
goto splash_address_too_high;
- return nand_read_skip_bad(&nand_info[nand_curr_device],
splash_screen_nand_offset, &bmp_size,
(u_char *)bmp_load_addr);
+splash_address_too_high:
- printf("Error: splashimage address too high. Data overwrites U-Boot "
"and/or placed beyond DRAM boundaries.\n");
- return -1;
+} +#else +static inline int splash_load_from_nand(void) +{
- return -1;
+} +#endif /* CONFIG_CMD_NAND */
+int board_splash_screen_prepare(void) +{
- char *env_splashimage_value;
- u32 bmp_load_addr;
- env_splashimage_value = getenv("splashimage");
- if (env_splashimage_value == NULL)
return -1;
- bmp_load_addr = simple_strtoul(env_splashimage_value, 0, 16);
- if (bmp_load_addr == 0) {
printf("Error: bad splashimage address specified\n");
return -1;
- }
- /* Fix bmp_load_addr to the alignment that lcd.c expects */
- if (bmp_load_addr % 4 != 2)
bmp_load_addr += (bmp_load_addr % 4) ?: 2;
- return splash_load_from_nand(bmp_load_addr);
+} +#endif /* CONFIG_LCD */
- /*
- Routine: board_init
- Description: hardware init.
diff --git a/include/configs/cm_t35.h b/include/configs/cm_t35.h index 46d35ba..53c4e3c 100644 --- a/include/configs/cm_t35.h +++ b/include/configs/cm_t35.h @@ -344,5 +344,9 @@ #define LCD_BPP LCD_COLOR16
#define CONFIG_LCD +#define CONFIG_SPLASH_SCREEN +#define CONFIG_CMD_BMP +#define CONFIG_BMP_16BPP +#define CONFIG_SPLASH_SCREEN_PREPARE
#endif /* __CONFIG_H */

Gentle ping.
On 01/31/2013 09:39 AM, Nikita Kiryanov wrote:
This patchset adds splash screen support for CM-T35. It includes the ability to initialize the display subsystem either using predefines (selected via env variable "displaytype"), or user supplied configuration options, also stored in an environment variables and pointed to by displaytype. The splash image data is currently read from NAND.
As a preparation for the above functionality this patchset adds:
- new DSS #defines
- an option for board-specific splash screen preparation, which can be invoked
in lcd_logo() right before displaying the splash screen (typical use case: load the image data from non-memory mapped storage in time for it to be displayed).
- struct panel_config is extended to support setting the gfx_format dynamically
- protection from data aborts due to unaligned bmp headers is added to
lcd_logo's splashscreen section (I'm also looking into refining this protection later on).
Changes in V3:
- No unnecessary #defines in arch-omap3/dss.h [Wolfgang Denk]
- Reworded patch 2 comment [Wolfgang Denk]
- Used a #define for cmap addr [Wolfgang Denk]
Changes in V2:
- DSS #defines are defined shiften where possible [Jeroen Hofstee]
- GFXFORMAT_RGB16 now passed to omap3_dss_panel_config() in a new field of
panel_cfg. Updated existing panel_config structs to set this field to the value that was originally hardcoded into omap3_dss_panel_config(). [Jeroen Hofstee]
- Used LCD_BPP for vl_bpix. [Jeroen Hofstee]
- Added a comment to explain the choice of GFXFORMAT_RGB16. [Jeroen Hofstee]
- Added an address check (and fix) to the address of splashimage in order to
avoid alignment problems with bmp header. A similar check appears in board_splash_screen_prepare() for cm_t35. [Albert ARIBAUD]
- Do not manually set gfx burst size to GFXBURSTSIZE16, as it is apparently not
necessary. GFXBURSTSIZE* #defines were kept in patch 1 anyway in the hope they will be useful for someone.
Nikita Kiryanov (7): omap3: add useful dss defines omap3: allow dynamic selection of gfx_format lcd: prevent unaligned memory access when displaying splash screen lcd: add option for board specific splash screen preparation cm-t35: add support for dvi displays cm-t35: add support for user defined lcd parameters cm-t35: add support for loading splash image from NAND
README | 8 + arch/arm/include/asm/arch-omap3/dss.h | 31 +++ board/cm_t35/Makefile | 1 + board/cm_t35/cm_t35.c | 68 ++++++ board/cm_t35/display.c | 428 +++++++++++++++++++++++++++++++++ board/htkw/mcx/mcx.c | 1 + board/teejet/mt_ventoux/mt_ventoux.c | 2 + board/ti/beagle/beagle.h | 6 +- common/lcd.c | 23 ++ drivers/video/omap3_dss.c | 2 +- include/configs/cm_t35.h | 11 + include/lcd.h | 1 + 12 files changed, 579 insertions(+), 3 deletions(-) create mode 100644 board/cm_t35/display.c
participants (1)
-
Nikita Kiryanov