summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
authorTorbjorn Svensson <torbjorn.x.svensson@stericsson.com>2010-12-07 15:33:29 +0100
committerMichael BRANDT <michael.brandt@stericsson.com>2010-12-13 15:41:15 +0100
commita7d22caa0320025442cb8c275bd70d034f5eb308 (patch)
treed416178a8e4450038514069f793961dfe84219f1 /board
parent307a253778d0918a8e0f10c2ea9a350450e37677 (diff)
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 <torbjorn.x.svensson@stericsson.com> Reviewed-by: QATOOLS Reviewed-by: Jimmy RUBIN <jimmy.rubin@stericsson.com> Reviewed-by: Michael BRANDT <michael.brandt@stericsson.com>
Diffstat (limited to 'board')
-rw-r--r--board/st/u8500/Makefile4
-rw-r--r--board/st/u8500/mcde.h1
-rw-r--r--board/st/u8500/mcde_display.c112
-rw-r--r--board/st/u8500/mcde_display.h4
-rw-r--r--board/st/u8500/mcde_display_image.c299
-rw-r--r--board/st/u8500/u8500.c8
6 files changed, 311 insertions, 117 deletions
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 <torbjorn.x.svensson@stericsson.com>
+* for ST-Ericsson.
+*
+* License terms: GNU General Public License (GPL), version 2.
+*/
+
+#include <common.h>
+#include <command.h>
+#include <linux/err.h>
+#include <part.h>
+#include <mmc.h>
+#include <bmp_layout.h>
+#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;