fbcon: Read the splash image from splash partition

Read the splash image from splash partition if available
and display it to the screen.

Change-Id: Ia360a59b4bf3e4b213974b8733cb65c7cfbf1c32
diff --git a/dev/fbcon/fbcon.c b/dev/fbcon/fbcon.c
index 608f4c0..a1b8184 100644
--- a/dev/fbcon/fbcon.c
+++ b/dev/fbcon/fbcon.c
@@ -2,7 +2,7 @@
  * Copyright (c) 2008, Google Inc.
  * All rights reserved.
  *
- * Copyright (c) 2009-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -208,52 +208,106 @@
     return config;
 }
 
-void display_image_on_screen(void)
+
+extern struct fbimage* fetch_image_from_partition();
+void fbcon_putImage(struct fbimage *fbimg, bool flag);
+
+void display_image_on_screen()
+{
+	struct fbimage default_fbimg, *fbimg;
+	bool flag = true;
+
+	fbcon_clear();
+	fbimg = fetch_image_from_partition();
+
+	if(!fbimg) {
+		flag = false;
+		fbimg = &default_fbimg;
+		fbimg->header.width = SPLASH_IMAGE_HEIGHT;
+		fbimg->header.height = SPLASH_IMAGE_WIDTH;
+		fbimg->image = (unsigned char *)imageBuffer_rgb888;
+	}
+
+	fbcon_putImage(fbimg, flag);
+}
+
+void fbcon_putImage(struct fbimage *fbimg, bool flag)
 {
     unsigned i = 0;
     unsigned total_x;
     unsigned total_y;
     unsigned bytes_per_bpp;
     unsigned image_base;
+    unsigned width, pitch, height;
+    unsigned char *logo_base;
+    struct logo_img_header *header;
 
-    if (!config) {
-       dprintf(CRITICAL,"NULL configuration, image cannot be displayed\n");
-       return;
-    }
 
-    fbcon_clear();
+	if (!config) {
+		dprintf(CRITICAL,"NULL configuration, image cannot be displayed\n");
+		return;
+	}
 
-    total_x = config->width;
-    total_y = config->height;
-    bytes_per_bpp = ((config->bpp) / 8);
-    image_base = ((((total_y/2) - (SPLASH_IMAGE_WIDTH / 2) - 1) *
-		    (config->width)) + (total_x/2 - (SPLASH_IMAGE_HEIGHT / 2)));
+	if(fbimg) {
+		header = &fbimg->header;
+		width = pitch = header->width;
+		height = header->height;
+		logo_base = (unsigned char *)fbimg->image;
+	}
+
+	total_x = config->width;
+	total_y = config->height;
+	bytes_per_bpp = ((config->bpp) / 8);
 
 #if DISPLAY_TYPE_MIPI
-    if (bytes_per_bpp == 3)
-    {
-        for (i = 0; i < SPLASH_IMAGE_WIDTH; i++)
-        {
-            memcpy (config->base + ((image_base + (i * (config->width))) * bytes_per_bpp),
-		    imageBuffer_rgb888 + (i * SPLASH_IMAGE_HEIGHT * bytes_per_bpp),
-		    SPLASH_IMAGE_HEIGHT * bytes_per_bpp);
+	if (bytes_per_bpp == 3)
+	{
+		if(flag) {
+			if (header->width == config->width && header->height == config->height)
+				return;
+			else {
+				logo_base = (unsigned char *)config->base + LOGO_IMG_OFFSET;
+				if (header->width > config->width) {
+					width = config->width;
+					pitch = header->width;
+					logo_base += (header->width - config->width) / 2 * bytes_per_bpp;
+				} else {
+					width = pitch = header->width;
+				}
+
+				if (header->height > config->height) {
+					height = config->height;
+					logo_base += (header->height - config->height) / 2 * pitch * bytes_per_bpp;
+				} else {
+					height = header->height;
+				}
+			}
+		}
+
+		image_base = ((((total_y/2) - (height / 2) ) *
+				(config->width)) + (total_x/2 - (width / 2)));
+		for (i = 0; i < height; i++) {
+			memcpy (config->base + ((image_base + (i * (config->width))) * bytes_per_bpp),
+				logo_base + (i * pitch * bytes_per_bpp), width * bytes_per_bpp);
+		}
 	}
-    }
-    fbcon_flush();
+
+	fbcon_flush();
+
 #if DISPLAY_MIPI_PANEL_NOVATEK_BLUE
-    if(is_cmd_mode_enabled())
+	if(is_cmd_mode_enabled())
         mipi_dsi_cmd_mode_trigger();
 #endif
 
 #else
     if (bytes_per_bpp == 2)
     {
-        for (i = 0; i < SPLASH_IMAGE_WIDTH; i++)
+        for (i = 0; i < header->width; i++)
         {
             memcpy (config->base + ((image_base + (i * (config->width))) * bytes_per_bpp),
-		    imageBuffer + (i * SPLASH_IMAGE_HEIGHT * bytes_per_bpp),
-		    SPLASH_IMAGE_HEIGHT * bytes_per_bpp);
-	}
+		   fbimg->Image + (i * header->height * bytes_per_bpp),
+		   header->height * bytes_per_bpp);
+        }
     }
     fbcon_flush();
 #endif
diff --git a/include/dev/fbcon.h b/include/dev/fbcon.h
index 7ab5ca1..a817675 100644
--- a/include/dev/fbcon.h
+++ b/include/dev/fbcon.h
@@ -31,6 +31,25 @@
 #ifndef __DEV_FBCON_H
 #define __DEV_FBCON_H
 
+#include <stdint.h>
+#define LOGO_IMG_OFFSET (12*1024*1024)
+#define LOGO_IMG_MAGIC "SPLASH!!"
+#define LOGO_IMG_MAGIC_SIZE sizeof(LOGO_IMG_MAGIC) - 1
+
+
+struct logo_img_header {
+    unsigned char magic[LOGO_IMG_MAGIC_SIZE]; // "SPLASH!!"
+    uint32_t width; // logo's width, little endian
+    uint32_t height; // logo's height, little endian
+    uint32_t offset;
+    unsigned char reserved[512-20];
+};
+
+struct fbimage {
+	struct logo_img_header  header;
+	void *image;
+};
+
 #define FB_FORMAT_RGB565 0
 #define FB_FORMAT_RGB666 1
 #define FB_FORMAT_RGB666_LOOSE 2