Merge "apq8084: Add support for volume up/down keys, reboot and usb"
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index ab52899..c9f763e 100755
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -624,6 +624,7 @@
 	struct dt_entry dt_entry;
 	unsigned dt_table_offset;
 	uint32_t dt_actual;
+	uint32_t dt_hdr_size;
 #endif
 	if (!boot_into_recovery) {
 		memset(ffbm_mode_string, '\0', sizeof(ffbm_mode_string));
@@ -773,15 +774,14 @@
 
 		#if DEVICE_TREE
 		if(hdr->dt_size) {
-			table = (struct dt_table*) dt_buf;
 			dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual + ramdisk_actual + second_actual);
+			table = (struct dt_table*) dt_table_offset;
 
-			memmove((void *) dt_buf, (char *)dt_table_offset, page_size);
-
-			if (dev_tree_validate(table, hdr->page_size) != 0) {
+			if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
 				dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
 				return -1;
 			}
+
 			/* Find index of device tree within device tree table */
 			if(dev_tree_get_entry_info(table, &dt_entry) != 0){
 				dprintf(CRITICAL, "ERROR: Device Tree Blob cannot be found\n");
@@ -852,18 +852,28 @@
 
 		#if DEVICE_TREE
 		if(hdr->dt_size != 0) {
-			/* Read the device tree table into buffer */
+			/* Read the first page of device tree table into buffer */
 			if(mmc_read(ptn + offset,(unsigned int *) dt_buf, page_size)) {
 				dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
 				return -1;
 			}
 			table = (struct dt_table*) dt_buf;
 
-			if (dev_tree_validate(table, hdr->page_size) != 0) {
+			if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
 				dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
 				return -1;
 			}
 
+			table = (struct dt_table*) memalign(CACHE_LINE, dt_hdr_size);
+			if (!table)
+				return -1;
+
+			/* Read the entire device tree table into buffer */
+			if(mmc_read(ptn + offset,(unsigned int *) table, dt_hdr_size)) {
+				dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
+				return -1;
+			}
+
 			/* Find index of device tree within device tree table */
 			if(dev_tree_get_entry_info(table, &dt_entry) != 0){
 				dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
@@ -935,6 +945,7 @@
 	struct dt_table *table;
 	struct dt_entry dt_entry;
 	uint32_t dt_actual;
+	uint32_t dt_hdr_size;
 #endif
 
 	if (target_is_emmc_boot()) {
@@ -1126,11 +1137,22 @@
 
 			table = (struct dt_table*) dt_buf;
 
-			if (dev_tree_validate(table, hdr->page_size) != 0) {
+			if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
 				dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
 				return -1;
 			}
 
+			table = (struct dt_table*) memalign(CACHE_LINE, dt_hdr_size);
+			if (!table)
+				return -1;
+
+			/* Read the entire device tree table into buffer */
+			if(flash_read(ptn, offset, (void *)table, dt_hdr_size)) {
+				dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
+				return -1;
+			}
+
+
 			/* Find index of device tree within device tree table */
 			if(dev_tree_get_entry_info(table, &dt_entry) != 0){
 				dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
@@ -1335,6 +1357,7 @@
 	uint32_t n;
 	struct dt_table *table;
 	struct dt_entry dt_entry;
+	uint32_t dt_hdr_size;
 
 	struct boot_img_hdr *hdr = (struct boot_img_hdr *) (boot_image_start);
 
@@ -1358,7 +1381,7 @@
 		/* offset now point to start of dt.img */
 		table = (struct dt_table*)(boot_image_start + dt_image_offset);
 
-		if (dev_tree_validate(table, hdr->page_size) != 0) {
+		if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
 			dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
 			return -1;
 		}
@@ -1910,33 +1933,123 @@
 	fastboot_okay("");
 }
 
-void splash_screen ()
+static struct fbimage logo_header = {0};
+struct fbimage* splash_screen_flash();
+
+int splash_screen_check_header(struct fbimage *logo)
+{
+	if (memcmp(logo->header.magic, LOGO_IMG_MAGIC, 8))
+		return -1;
+	if (logo->header.width == 0 || logo->header.height == 0)
+		return -1;
+	return 0;
+}
+
+struct fbimage* splash_screen_flash()
 {
 	struct ptentry *ptn;
 	struct ptable *ptable;
 	struct fbcon_config *fb_display = NULL;
+	struct fbimage *logo = &logo_header;
 
-	if (!target_is_emmc_boot())
-	{
-		ptable = flash_get_ptable();
-		if (ptable == NULL) {
-			dprintf(CRITICAL, "ERROR: Partition table not found\n");
-			return;
+
+	ptable = flash_get_ptable();
+	if (ptable == NULL) {
+	dprintf(CRITICAL, "ERROR: Partition table not found\n");
+	return NULL;
+	}
+	ptn = ptable_find(ptable, "splash");
+	if (ptn == NULL) {
+		dprintf(CRITICAL, "ERROR: splash Partition not found\n");
+		return NULL;
+	}
+
+	if (flash_read(ptn, 0,(unsigned int *) logo, sizeof(logo->header))) {
+		dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
+		return NULL;
+	}
+
+	if (splash_screen_check_header(logo)) {
+		dprintf(CRITICAL, "ERROR: Boot image header invalid\n");
+		return NULL;
+	}
+
+	fb_display = fbcon_display();
+	if (fb_display) {
+		uint8_t *base = (uint8_t *) fb_display->base;
+		if (logo->header.width != fb_display->width || logo->header.height != fb_display->height) {
+				base += LOGO_IMG_OFFSET;
 		}
 
-		ptn = ptable_find(ptable, "splash");
-		if (ptn == NULL) {
-			dprintf(CRITICAL, "ERROR: No splash partition found\n");
-		} else {
-			fb_display = fbcon_display();
-			if (fb_display) {
-				if (flash_read(ptn, 0, fb_display->base,
-					(fb_display->width * fb_display->height * fb_display->bpp/8))) {
-					fbcon_clear();
-					dprintf(CRITICAL, "ERROR: Cannot read splash image\n");
-				}
-			}
+		if (flash_read(ptn + sizeof(logo->header), 0,
+			base,
+			((((logo->header.width * logo->header.height * fb_display->bpp/8) + 511) >> 9) << 9))) {
+			fbcon_clear();
+			dprintf(CRITICAL, "ERROR: Cannot read splash image\n");
+			return NULL;
 		}
+		logo->image = base;
+	}
+
+	return logo;
+}
+
+struct fbimage* splash_screen_mmc()
+{
+	int index = INVALID_PTN;
+	unsigned long long ptn = 0;
+	struct fbcon_config *fb_display = NULL;
+	struct fbimage *logo = &logo_header;
+
+	index = partition_get_index("splash");
+	if (index == 0) {
+		dprintf(CRITICAL, "ERROR: splash Partition table not found\n");
+		return NULL;
+	}
+
+	ptn = partition_get_offset(index);
+	if (ptn == 0) {
+		dprintf(CRITICAL, "ERROR: splash Partition invalid\n");
+		return NULL;
+	}
+
+	if (mmc_read(ptn, (unsigned int *) logo, sizeof(logo->header))) {
+		dprintf(CRITICAL, "ERROR: Cannot read splash image header\n");
+		return NULL;
+	}
+
+	if (splash_screen_check_header(logo)) {
+		dprintf(CRITICAL, "ERROR: Splash image header invalid\n");
+		return NULL;
+	}
+
+	fb_display = fbcon_display();
+	if (fb_display) {
+		uint8_t *base = (uint8_t *) fb_display->base;
+		if (logo->header.width != fb_display->width || logo->header.height != fb_display->height)
+				base += LOGO_IMG_OFFSET;
+
+		if (mmc_read(ptn + sizeof(logo->header),
+			base,
+			((((logo->header.width * logo->header.height * fb_display->bpp/8) + 511) >> 9) << 9))) {
+			fbcon_clear();
+			dprintf(CRITICAL, "ERROR: Cannot read splash image\n");
+			return NULL;
+		}
+
+		logo->image = base;
+	}
+
+	return logo;
+}
+
+
+struct fbimage* fetch_image_from_partition()
+{
+	if (target_is_emmc_boot()) {
+		return splash_screen_mmc();
+	} else {
+		return splash_screen_flash();
 	}
 }
 
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
diff --git a/platform/fsm9900/include/platform/clock.h b/platform/fsm9900/include/platform/clock.h
index e19920d..eb55033 100644
--- a/platform/fsm9900/include/platform/clock.h
+++ b/platform/fsm9900/include/platform/clock.h
@@ -32,7 +32,7 @@
 #include <clock.h>
 #include <clock_lib2.h>
 
-#define UART_DM_CLK_RX_TX_BIT_RATE 0xFF
+#define UART_DM_CLK_RX_TX_BIT_RATE 0xcc
 
 void platform_clock_init(void);
 
diff --git a/platform/fsm9900/include/platform/iomap.h b/platform/fsm9900/include/platform/iomap.h
index 4cc017b..1efb9a6 100644
--- a/platform/fsm9900/include/platform/iomap.h
+++ b/platform/fsm9900/include/platform/iomap.h
@@ -35,7 +35,7 @@
 #define SDRAM_START_ADDR            0x00000000
 #define SDRAM_SEC_BANK_START_ADDR   0x10000000
 
-#define MSM_SHARED_BASE             0x0FA00000
+#define MSM_SHARED_BASE             0x1C100000
 
 #define RPM_MSG_RAM_BASE            0xFC42B000
 #define SYSTEM_IMEM_BASE            0xFE800000
diff --git a/platform/fsm9900/rules.mk b/platform/fsm9900/rules.mk
index e115234..23b1040 100644
--- a/platform/fsm9900/rules.mk
+++ b/platform/fsm9900/rules.mk
@@ -10,7 +10,7 @@
 
 DEFINES += PERIPH_BLK_BLSP=1
 DEFINES += WITH_CPU_EARLY_INIT=0 WITH_CPU_WARM_BOOT=0 \
-	   MMC_SLOT=$(MMC_SLOT) SSD_ENABLE
+	   MMC_SLOT=$(MMC_SLOT)
 
 INCLUDES += -I$(LOCAL_DIR)/include -I$(LK_TOP_DIR)/platform/msm_shared/include
 
diff --git a/platform/msm_shared/dev_tree.c b/platform/msm_shared/dev_tree.c
index 4e1d44f..7ff5a82 100644
--- a/platform/msm_shared/dev_tree.c
+++ b/platform/msm_shared/dev_tree.c
@@ -197,9 +197,10 @@
 }
 
 /* Returns 0 if the device tree is valid. */
-int dev_tree_validate(struct dt_table *table, unsigned int page_size)
+int dev_tree_validate(struct dt_table *table, unsigned int page_size, uint32_t *dt_hdr_size)
 {
 	int dt_entry_size;
+	uint32_t hdr_size;
 
 	/* Validate the device tree table header */
 	if(table->magic != DEV_TREE_MAGIC) {
@@ -217,8 +218,11 @@
 		return -1;
 	}
 
-	/* Restriction that the device tree entry table should be less than a page*/
-	ASSERT(((table->num_entries * dt_entry_size)+ DEV_TREE_HEADER_SIZE) < page_size);
+	hdr_size = table->num_entries * dt_entry_size + DEV_TREE_HEADER_SIZE;
+	/* Roundup to page_size. */
+	hdr_size = ROUNDUP(hdr_size, page_size);
+
+	*dt_hdr_size = hdr_size;
 
 	return 0;
 }
diff --git a/platform/msm_shared/include/dev_tree.h b/platform/msm_shared/include/dev_tree.h
index 2a8ee01..b88a47d 100644
--- a/platform/msm_shared/include/dev_tree.h
+++ b/platform/msm_shared/include/dev_tree.h
@@ -66,7 +66,7 @@
 	DT_OP_FAILURE = -1,
 };
 
-int dev_tree_validate(struct dt_table *table, unsigned int page_size);
+int dev_tree_validate(struct dt_table *table, unsigned int page_size, uint32_t *dt_hdr_size);
 int dev_tree_get_entry_info(struct dt_table *table, struct dt_entry *dt_entry_info);
 int update_device_tree(void *, const char *, void *, unsigned);
 int dev_tree_add_mem_info(void *fdt, uint32_t offset, uint32_t size, uint32_t addr);
diff --git a/project/fsm9900.mk b/project/fsm9900.mk
index 8945556..ae8706f 100644
--- a/project/fsm9900.mk
+++ b/project/fsm9900.mk
@@ -10,7 +10,7 @@
 EMMC_BOOT := 1
 ENABLE_SDHCI_SUPPORT := 0
 
-#DEFINES += WITH_DEBUG_DCC=1
+DEFINES += WITH_DEBUG_DCC=1
 DEFINES += WITH_DEBUG_UART=1
 #DEFINES += WITH_DEBUG_FBCON=1
 DEFINES += DEVICE_TREE=1
diff --git a/target/fsm9900/init.c b/target/fsm9900/init.c
index 8bfc791..eed402c 100644
--- a/target/fsm9900/init.c
+++ b/target/fsm9900/init.c
@@ -410,12 +410,27 @@
 /* Check if MSM needs VBUS mimic for USB */
 static int target_needs_vbus_mimic()
 {
-	return 0;
+	return 1;
 }
 
 /* Do target specific usb initialization */
 void target_usb_init(void)
 {
+	uint32_t val;
+
+	if (target_needs_vbus_mimic()) {
+		/* Select and enable external configuration with USB PHY */
+		ulpi_write(ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT, ULPI_MISC_A_SET);
+
+		/* Enable sess_vld */
+		val = readl(USB_GENCONFIG_2) | GEN2_SESS_VLD_CTRL_EN;
+		writel(val, USB_GENCONFIG_2);
+
+		/* Enable external vbus configuration in the LINK */
+		val = readl(USB_USBCMD);
+		val |= SESS_VLD_CTRL;
+		writel(val, USB_USBCMD);
+	}
 }
 
 /* Returns 1 if target supports continuous splash screen. */
diff --git a/target/msm8226/init.c b/target/msm8226/init.c
index 864b559..d33aa95 100644
--- a/target/msm8226/init.c
+++ b/target/msm8226/init.c
@@ -245,6 +245,8 @@
 
 	target_keystatus();
 
+	target_sdc_init();
+
 	/* Display splash screen if enabled */
 #if DISPLAY_SPLASH_SCREEN
 	dprintf(SPEW, "Display Init: Start\n");
@@ -252,8 +254,6 @@
 	dprintf(SPEW, "Display Init: Done\n");
 #endif
 
-	target_sdc_init();
-
 	if (target_use_signed_kernel())
 		target_crypto_init_params();
 }
diff --git a/target/msm8974/target_display.c b/target/msm8974/target_display.c
index 10aefc7..3c0cadd 100644
--- a/target/msm8974/target_display.c
+++ b/target/msm8974/target_display.c
@@ -66,8 +66,7 @@
 	struct board_pmic_data *pmic_info;
 
 	if (platform_id == MSM8974AC)
-		if ((hardware_id == HW_PLATFORM_SURF)
-		    || (hardware_id == HW_PLATFORM_MTP)
+		if ((hardware_id == HW_PLATFORM_MTP)
 		    || (hardware_id == HW_PLATFORM_LIQUID))
 			slave_id = 3;
 
@@ -132,8 +131,7 @@
 	};
 
 	if (platform_id == MSM8974AC)
-		if ((hardware_id == HW_PLATFORM_SURF)
-		    || (hardware_id == HW_PLATFORM_MTP)
+		if ((hardware_id == HW_PLATFORM_MTP)
 		    || (hardware_id == HW_PLATFORM_LIQUID))
 			rst_gpio = 20;