From a7d22caa0320025442cb8c275bd70d034f5eb308 Mon Sep 17 00:00:00 2001 From: Torbjorn Svensson Date: Tue, 7 Dec 2010 15:33:29 +0100 Subject: U8500: Changes to use a bmp file as splash image This change makes it possible to use a bitmap file (.bmp) as the splash image. This also removes the need to specify width and height of the splash image. RLE compression, 1 and 4 bit formats are not supported. ST-Ericsson ID: AP281072 Change-Id: I7c9ae953ad0440b665bb03ed1b9bbf43bab04e91 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/9406 Tested-by: Torbjorn SVENSSON Reviewed-by: QATOOLS Reviewed-by: Jimmy RUBIN Reviewed-by: Michael BRANDT --- board/st/u8500/Makefile | 4 +- board/st/u8500/mcde.h | 1 + board/st/u8500/mcde_display.c | 112 +------------- board/st/u8500/mcde_display.h | 4 +- board/st/u8500/mcde_display_image.c | 299 ++++++++++++++++++++++++++++++++++++ board/st/u8500/u8500.c | 8 +- 6 files changed, 311 insertions(+), 117 deletions(-) create mode 100644 board/st/u8500/mcde_display_image.c (limited to 'board') diff --git a/board/st/u8500/Makefile b/board/st/u8500/Makefile index 713f57d0e..55de856b4 100644 --- a/board/st/u8500/Makefile +++ b/board/st/u8500/Makefile @@ -20,14 +20,16 @@ # MA 02111-1307 USA # + include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).a -COBJS := u8500.o u8500_i2c.o mmc_host.o mmc_utils.o mcde_display.o mcde_hw.o ab8500vibra.o cmd_cdump.o +COBJS := u8500.o u8500_i2c.o mmc_host.o mmc_utils.o ab8500vibra.o cmd_cdump.o SOBJS := mmc_fifo.o COBJS-$(CONFIG_ITP_LOAD) += itp.o cspsa_fp.o +COBJS-$(CONFIG_VIDEO_LOGO) += mcde_display.o mcde_hw.o mcde_display_image.o COBJS += $(COBJS-y) diff --git a/board/st/u8500/mcde.h b/board/st/u8500/mcde.h index b5d03762e..237e7deb3 100644 --- a/board/st/u8500/mcde.h +++ b/board/st/u8500/mcde.h @@ -110,6 +110,7 @@ int mcde_dsi_dcs_write(struct mcde_port *port, u8 cmd, u8* data, int len); /* MCDE */ +int mcde_turn_on_display(void); int mcde_init(u8 num_data_lanes); void mcde_exit(void); diff --git a/board/st/u8500/mcde_display.c b/board/st/u8500/mcde_display.c index 73847bf26..76ded82e6 100644 --- a/board/st/u8500/mcde_display.c +++ b/board/st/u8500/mcde_display.c @@ -92,7 +92,7 @@ static int mcde_enable_gpio(void) #define DCS_CMD_EXIT_SLEEP_MODE 0x11 #define DCS_CMD_SET_DISPLAY_ON 0x29 -static int mcde_turn_on_display(void) +int mcde_turn_on_display(void) { int ret = 0; dbg_printk("Turn on display!\n"); @@ -272,8 +272,7 @@ static int mcde_display_power_init(void) return 0; } - -int mcde_startup(void) +int mcde_splash_image(void) { u8 num_dsilinks; int ret; @@ -296,18 +295,16 @@ int mcde_startup(void) printf("%s:Failed to acquire MCDE channel\n", __func__); goto get_chnl_failed; } - - ret = mcde_turn_on_display(); - if (ret) - goto display_power_mode_failed; mcde_chnl_set_update_area(chnl, 0, 0, main_display.native_x_res, main_display.native_y_res); mcde_chnl_set_pixel_format(chnl, main_display.port_pixel_format); mcde_chnl_apply(chnl); + /* Everything setup ok, display image */ + ret = mcde_display_image(chnl); + return ret; -display_power_mode_failed: get_chnl_failed: display_power_failed: enable_gpio_failed: @@ -315,102 +312,3 @@ enable_gpio_failed: return ret; } -int mcde_display_image(void) -{ - struct mcde_ovly_state *ovly; - u32 xpos = 0; - u32 ypos = 0; - int ret; - struct mmc *emmc_dev; - u32 address = CONFIG_SYS_VIDEO_FB_ADRS; - -#ifdef CONFIG_SYS_VIDEO_USE_GIMP_HEADER - u32 i = 0; - u8 pixels[3]; - u16 pixel; - u16 *sp; -#endif - - ovly = mcde_ovly_get(chnl); - if (IS_ERR(ovly)) { - ret = PTR_ERR(ovly); - printf("Failed to get channel\n"); - return -ret; - } - - emmc_dev = find_mmc_device(CONFIG_EMMC_DEV_NUM); - if (emmc_dev == NULL) { - printf("mcde_display_image: emmc not found.\n"); - return 1; - } - - if (toc_load_toc_entry(&emmc_dev->block_dev, MCDE_TOC_SPLASH_NAME, 0, - 0, address)) { - printf("mcde_display_image: no splash image found.\n"); - return 1; - } - -#ifdef CONFIG_SYS_VIDEO_USE_GIMP_HEADER - /* Add the image data */ - sp = (u16 *)CONFIG_SYS_VIDEO_FB_ADRS; - for (i = 0; i < ((MCDE_VIDEO_LOGO_WIDTH*MCDE_VIDEO_LOGO_HEIGHT)); i++) { - HEADER_PIXEL(header_data, pixels); - pixels[0] >>= 3; /* Keep 5 bits red */ - pixels[1] >>= 2; /* 6 bits green */ - pixels[2] >>= 3; /* and 5 bits blue */ - pixel = (pixels[0] << 11) | (pixels[1] << 5) | pixels[2]; - *sp++ = pixel; - } - mcde_ovly_set_source_buf(ovly, CONFIG_SYS_VIDEO_FB_ADRS); -#else - mcde_ovly_set_source_buf(ovly, (u32)address); -#endif - mcde_ovly_set_source_info(ovly, (MCDE_VIDEO_LOGO_WIDTH*2), - main_display.default_pixel_format); - mcde_ovly_set_source_area(ovly, 0, 0, MCDE_VIDEO_LOGO_WIDTH, - MCDE_VIDEO_LOGO_HEIGHT); - if (MCDE_VIDEO_LOGO_WIDTH == main_display.native_x_res) - xpos = 0; - else - xpos = (main_display.native_x_res - MCDE_VIDEO_LOGO_WIDTH) / 2; - - if (MCDE_VIDEO_LOGO_HEIGHT == main_display.native_y_res) - ypos = 0; - else - ypos = (main_display.native_y_res - MCDE_VIDEO_LOGO_HEIGHT) / 2; - - mcde_ovly_set_dest_pos(ovly, xpos, ypos, 0); - mcde_ovly_apply(ovly); - mcde_chnl_update(chnl); - /* Wait for refresh to be finished */ - mdelay(CONFIG_SYS_MCDE_REFRESH_TIME); - mcde_exit(); - return 0; -} - -/* - * command line commands - */ - - -int mcde_power_up(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ - return mcde_startup(); -} - -int mcde_disply_bitmap(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ - return mcde_display_image(); -} - -U_BOOT_CMD( - mcde_power_up, 1, 1, mcde_power_up, - "Power up display", - "" -); - -U_BOOT_CMD( - mcde_display, 1, 1, mcde_disply_bitmap, - "Display bitmap", - "" -); diff --git a/board/st/u8500/mcde_display.h b/board/st/u8500/mcde_display.h index 6941c044c..ff0e8f847 100644 --- a/board/st/u8500/mcde_display.h +++ b/board/st/u8500/mcde_display.h @@ -30,8 +30,8 @@ struct mcde_display_device { u16 native_y_res; }; -int mcde_startup(void); -int mcde_display_image(void); +int mcde_splash_image(void); +int mcde_display_image(struct mcde_chnl_state *chnl); #endif /* !defined(__MCDE_UTILS_H) */ diff --git a/board/st/u8500/mcde_display_image.c b/board/st/u8500/mcde_display_image.c new file mode 100644 index 000000000..483b09cc1 --- /dev/null +++ b/board/st/u8500/mcde_display_image.c @@ -0,0 +1,299 @@ +/* +* Copyright (C) ST-Ericsson SA 2010 +* +* Author: Torbjorn Svensson +* for ST-Ericsson. +* +* License terms: GNU General Public License (GPL), version 2. +*/ + +#include +#include +#include +#include +#include +#include +#include "mcde.h" +#include "mcde_display.h" + +#define DEBUG_THIS_FILE 0 +#define dbg_printk(format, arg...) \ + if (DEBUG_THIS_FILE) \ + printf("mcde: " format, ##arg) + +/* bmp compression constants */ +#define BI_RGB 0 +#define BI_RLE8 1 /* RLE 8-bit/pixel */ +#define BI_RLE4 2 /* RLE 4-bit/pixel */ +#define BI_BITFIELDS 3 + +extern struct mcde_display_device main_display; + +static uint32_t read_unaligned32(uint32_t *val) +{ + uint32_t ret; + memcpy(&ret, val, sizeof(int32_t)); + return ret; +} + +static void copy_indexed(u16 *bmp_dst, u8 *bmp_start, + int dst_pitch, int src_pitch, + u32 width, u32 height, u8 *palette) +{ + /* + * Copy image from flash area to overlay area and + * convert format from 8-bit indexed to rgb565. + */ + int i; + int j; + int o; + int pad; + u16 val16; + u32 w; + u8 r; + u8 g; + u8 b; + u8 *bmp_src; + + pad = (dst_pitch - 2 * width) / 2; + + /* expanding 8 bit indexes to 16 bit rgb */ + for (i = height - 1, o = 0; i >= 0; i--) { + bmp_src = (u8 *)(bmp_start + i * src_pitch); + for (j = 0; j < width; j++) { + w = bmp_src[j]; /* get index */ + w <<= 2; /* make offset */ + w += (u32)palette; /* make address */ + r = *((u8 *)w++); + g = *((u8 *)w++); + b = *((u8 *)w); + val16 = r >> 3; + val16 |= (g >> 2) << 5; + val16 |= (b >> 3) << 11; + bmp_dst[o++] = val16; + } + o += pad; + } +} + +static void copy_rgb565(u8 *bmp_dst, u8 *bmp_start, + int dst_pitch, int src_pitch, + u32 width, u32 height) +{ + int i; + u8 *bmp_src; + + /* point after source data */ + bmp_src = (u8 *)(bmp_start + (height * src_pitch)); + for (i = 0; i < height; i++) { + bmp_src -= src_pitch; + memcpy(bmp_dst, bmp_src, src_pitch); + bmp_dst += dst_pitch; + } +} + +static void copy_rgb(u16 *bmp_dst, u8 *bmp_start, + int dst_pitch, int src_pitch, + u32 width, u32 height, u32 bitspp) +{ + /* + * Copy image from flash area to overlay area and + * convert format from (a)rgb888(8) to rgb565. + */ + int i; + int j; + int o; + int pad; + u16 val16; + u8 r; + u8 g; + u8 b; + u8 *bmp_src; + u32 src_inc = bitspp / 8; + + pad = (dst_pitch - 2 * width) / 2; + + /* convert to 16 bit */ + for (i = height - 1, o = 0; i >= 0; i--) { + bmp_src = (u8 *)(bmp_start + i * src_pitch); + for (j = 0; j < (width * src_inc); j += src_inc) { + r = bmp_src[j]; + g = bmp_src[j + 1]; + b = bmp_src[j + 2]; + val16 = r >> 3; + val16 |= (g >> 2) << 5; + val16 |= (b >> 3) << 11; + bmp_dst[o++] = val16; + } + o += pad; + } +} + +int mcde_display_image(struct mcde_chnl_state *chnl) +{ + int err = 0; + struct mmc *emmc_dev; + u32 address = (CONFIG_SYS_VIDEO_FB_ADRS + 2 * + CONFIG_SYS_DISPLAY_NATIVE_X_RES * + CONFIG_SYS_DISPLAY_NATIVE_Y_RES); /* after frame buffer */ + u8 *bmp_start; + struct bmp_header *bmp_header; + u32 bmp_offset; + u32 dib_bytesz; + u32 dib_width; + u32 dib_height; + u32 dib_compression; + u16 dib_bitspp; + int src_pitch; + int dst_pitch; + u32 dib_header_size; + u8 *palette; + u32 palette_size; + u8 *bmp_src; + u8 *bmp_dst; + u8 *ovly_mem = (u8 *)CONFIG_SYS_VIDEO_FB_ADRS; /* frame buffer */ + struct mcde_ovly_state *ovly; + u32 xpos = 0; + u32 ypos = 0; + + dbg_printk("%s: Enter\n", __func__); + + emmc_dev = find_mmc_device(CONFIG_EMMC_DEV_NUM); + if (emmc_dev == NULL) { + printf("mcde_display_image: emmc not found.\n"); + return -ENODEV; + } + + if (toc_load_toc_entry(&emmc_dev->block_dev, MCDE_TOC_SPLASH_NAME, 0, + 0, address)) { + printf("mcde_display_image: no splash image found.\n"); + return -ENOENT; + } + + /* get bmp_image */ + bmp_start = (u8 *)address; + dbg_printk("%s: bmp start = 0x%p\n", __func__, (void *)bmp_start); + + /* check BMP magic */ + bmp_header = (struct bmp_header *)bmp_start; + if (bmp_header->signature[0] != 'B' || + bmp_header->signature[1] != 'M') { + printf("%s: unsupported filetype, must be BMP\n", __func__); + return -EILSEQ; + } + + /* get offset to bitmap-data from the BMP header */ + bmp_offset = read_unaligned32(&bmp_header->data_offset); + dbg_printk("bmp filesz = %d\n", + read_unaligned32(&bmp_header->file_size)); + dbg_printk("bmp offset = %d\n", bmp_offset); + + dib_width = read_unaligned32((uint32_t *)&bmp_header->width); + dib_height = read_unaligned32((uint32_t *)&bmp_header->height); + dib_bytesz = read_unaligned32(&bmp_header->image_size); + dib_bitspp = bmp_header->bit_count; + dib_header_size = read_unaligned32(&bmp_header->size); + dbg_printk("dib header_sz = %d\n", dib_header_size); + dbg_printk("dib width = %d\n", dib_width); + dbg_printk("dib height = %d\n", dib_height); + dbg_printk("dib nplanes = %d\n", bmp_header->planes); + dbg_printk("dib bitspp = %d\n", dib_bitspp); + dib_compression = read_unaligned32(&bmp_header->compression); + dbg_printk("dib compress_type = %d\n", dib_compression); + dbg_printk("dib dib_bytesz = %d\n", dib_bytesz); + + /* calculate palette address */ + palette = ((u8 *)&bmp_header->size + dib_header_size); + palette_size = ((bmp_start + bmp_offset) - palette); + dbg_printk("palette size = %d\n", palette_size); + /* if same as image start: no palette */ + if (palette_size == 0) + palette = NULL; + dbg_printk("palette = 0x%08x\n", (u32)palette); + + /* check validity */ + if ((dib_width > main_display.native_x_res) || + (dib_height > main_display.native_y_res)) { + printf("%s: image to large, must be [%d,%d] or smaller\n", + __func__, main_display.native_x_res, + main_display.native_y_res); + err++; + } + if (bmp_header->planes != 1) { + printf("%s: unsupported nplanes, must be 1\n", __func__); + err++; + } + + src_pitch = dib_width * dib_bitspp / 8; + src_pitch = (src_pitch + 3) >> 2; /* pad to 32-bit boundary */ + src_pitch <<= 2; + dbg_printk("src_pitch=%d\n", src_pitch); + + if (dib_compression != BI_RGB && dib_compression != BI_BITFIELDS) + err++; + + if (err != 0) + return -EINVAL; + + /* set new pitch */ + dst_pitch = dib_width * 16 / 8; /* dest is 16 bpp */ + dst_pitch = (dst_pitch + 7) >> 3; /* pad to 64-bit boundary */ + dst_pitch <<= 3; + dbg_printk("dst_pitch=%d\n", dst_pitch); + + /* image is stored upside-down in the file */ + bmp_dst = ovly_mem; + bmp_src = (u8 *)(bmp_start + bmp_offset); + dbg_printk("bmp copy dst=0x%08x, src=0x%08x, len=%d\n", + (uint32_t)bmp_dst, (uint32_t)bmp_src, dib_bytesz); + + switch (dib_bitspp) { + case 8: + copy_indexed((u16 *)bmp_dst, bmp_src, dst_pitch, src_pitch, + dib_width, dib_height, palette); + break; + case 16: + copy_rgb565(bmp_dst, bmp_src, dst_pitch, src_pitch, + dib_width, dib_height); + break; + case 24: + case 32: + copy_rgb((u16 *)bmp_dst, bmp_src, dst_pitch, src_pitch, + dib_width, dib_height, dib_bitspp); + break; + default: + printf("%s: unsupported bitspp=%d\n", __func__, dib_bitspp); + return -EINVAL; + } + dbg_printk("%s: image OK\n", __func__); + + ovly = mcde_ovly_get(chnl); + if (IS_ERR(ovly)) { + err = PTR_ERR(ovly); + printf("%s: Failed to get channel\n", __func__); + return -err; + } + dbg_printk("ovly=%p ovly_mem=%p\n", (void *)ovly, (void *)ovly_mem); + mcde_ovly_set_source_buf(ovly, (u32)ovly_mem); + mcde_ovly_set_source_info(ovly, dst_pitch, + main_display.default_pixel_format); + mcde_ovly_set_source_area(ovly, 0, 0, dib_width, dib_height); + + if (dib_width == main_display.native_x_res) + xpos = 0; + else + xpos = (main_display.native_x_res - dib_width) / 2; + + if (dib_height == main_display.native_y_res) + ypos = 0; + else + ypos = (main_display.native_y_res - dib_height) / 2; + + mcde_ovly_set_dest_pos(ovly, xpos, ypos, 0); + + mcde_ovly_apply(ovly); + mcde_chnl_update(chnl); + + return mcde_turn_on_display(); +} + diff --git a/board/st/u8500/u8500.c b/board/st/u8500/u8500.c index a23056c55..307b25fa4 100644 --- a/board/st/u8500/u8500.c +++ b/board/st/u8500/u8500.c @@ -137,8 +137,6 @@ static int mcde_error; */ static volatile int data_init_flag = -1; /* -1 to get it into .data section */ -static void config_gpio(void); - /* Get hold of gd pointer */ DECLARE_GLOBAL_DATA_PTR; @@ -233,14 +231,10 @@ static int dss_init(void) printf("Only HREF+ or V2 is supported\n"); goto mcde_error; } - if (mcde_startup()) { + if (mcde_splash_image()) { printf("startup failed\n"); goto mcde_error; } - if (mcde_display_image()) { - printf("display_image failed\n"); - goto mcde_error; - } printf("ready\n"); return 0; -- cgit v1.2.3