Merge "platform: msm_shared: RPMB Write performance enhancement"
diff --git a/dev/gcdb/display/fastboot_oem_display.h b/dev/gcdb/display/fastboot_oem_display.h
index 7492d2f..9dd8b5c 100644
--- a/dev/gcdb/display/fastboot_oem_display.h
+++ b/dev/gcdb/display/fastboot_oem_display.h
@@ -30,9 +30,14 @@
 #ifndef _FASTBOOT_OEM_DISPLAY_H_
 #define _FASTBOOT_OEM_DISPLAY_H_
 
-/*---------------------------------------------------------------------------*/
-/* Lookup table for skip panels                                              */
-/*---------------------------------------------------------------------------*/
+#define SIM_OVERRIDE_LEN 10
+
+enum {
+    SIM_NONE,
+    SIM_MODE,
+    SIM_SWTE,
+    SIM_HWTE,
+};
 
 struct panel_lookup_list {
 	char name[MAX_PANEL_ID_LEN];
@@ -40,6 +45,15 @@
 	bool is_split_dsi;
 };
 
+struct sim_lookup_list {
+	uint32_t sim_mode;
+	char override_string[SIM_OVERRIDE_LEN];
+};
+
+/*---------------------------------------------------------------------------*/
+/* Lookup table for skip panels                                              */
+/*---------------------------------------------------------------------------*/
+
 struct panel_lookup_list lookup_skip_panels[] = {
 	{"adv7533_1080p_video", "qcom,mdss_dsi_adv7533_1080p60_video", false},
 	{"adv7533_720p_video", "qcom,mdss_dsi_adv7533_720p60_video", false},
@@ -89,4 +103,10 @@
 	{"truly_wvga_video", "qcom,mdss_dsi_truly_wvga_video", false},
 };
 
+struct sim_lookup_list lookup_sim[] = {
+	{SIM_MODE, "sim"},
+	{SIM_SWTE, "sim-swte"},
+	{SIM_HWTE, "sim-hwte"},
+};
+
 #endif /*_FASTBOOT_OEM_DISPLAY_H_ */
diff --git a/dev/gcdb/display/gcdb_display.c b/dev/gcdb/display/gcdb_display.c
index bfb1153..d4fe865 100644
--- a/dev/gcdb/display/gcdb_display.c
+++ b/dev/gcdb/display/gcdb_display.c
@@ -408,6 +408,45 @@
 	return panelstruct;
 }
 
+static void mdss_dsi_set_pll_src(void)
+{
+	struct oem_panel_data *oem_data = mdss_dsi_get_oem_data_ptr();
+
+	if (panelstruct.paneldata->panel_operating_mode & USE_DSI1_PLL_FLAG)
+		oem_data->dsi_pll_src = DSI_PLL1;
+
+	if (strcmp(oem_data->sec_panel, "")) {
+		if (oem_data->dsi_pll_src != DSI_PLL_DEFAULT) {
+			dprintf(CRITICAL, "Dual DSI config detected!"
+				"Use default PLL\n");
+			oem_data->dsi_pll_src = DSI_PLL_DEFAULT;
+		}
+	} else if (panelstruct.paneldata->slave_panel_node_id) {
+		if((dsi_video_mode_phy_db.pll_type != DSI_PLL_TYPE_THULIUM)
+			&& (oem_data->dsi_pll_src == DSI_PLL1)) {
+			dprintf(CRITICAL, "Split DSI on 28nm/20nm!"
+				"Use DSI PLL0\n");
+			oem_data->dsi_pll_src = DSI_PLL0;
+		}
+	} else {
+		if ((dsi_video_mode_phy_db.pll_type != DSI_PLL_TYPE_THULIUM)
+			&& !strcmp(panelstruct.paneldata->panel_destination,
+			"DISPLAY_1") && (oem_data->dsi_pll_src == DSI_PLL1)) {
+			dprintf(CRITICAL, "Single DSI with DSI-0 on 28nm/20nm!"
+				"Use DSI PLL0\n");
+			oem_data->dsi_pll_src = DSI_PLL0;
+		}
+	}
+
+	if (oem_data->dsi_pll_src == DSI_PLL1)
+		panelstruct.paneldata->panel_operating_mode |=
+			USE_DSI1_PLL_FLAG;
+	else
+		panelstruct.paneldata->panel_operating_mode &=
+			~USE_DSI1_PLL_FLAG;
+
+}
+
 int gcdb_display_init(const char *panel_name, uint32_t rev, void *base)
 {
 	int ret = NO_ERROR;
@@ -419,6 +458,7 @@
 
 	if (pan_type == PANEL_TYPE_DSI) {
 		target_dsi_phy_config(&dsi_video_mode_phy_db);
+		mdss_dsi_set_pll_src();
 		if (dsi_panel_init(&(panel.panel_info), &panelstruct)) {
 			dprintf(CRITICAL, "DSI panel init failed!\n");
 			ret = ERROR;
diff --git a/dev/gcdb/display/gcdb_display.h b/dev/gcdb/display/gcdb_display.h
index 1fbc2f7..088aa05 100755
--- a/dev/gcdb/display/gcdb_display.h
+++ b/dev/gcdb/display/gcdb_display.h
@@ -43,6 +43,8 @@
 #define BIST_SIZE 6
 #define LANE_SIZE 45
 
+#define DSI_CFG_SIZE 15
+
 /*---------------------------------------------------------------------------*/
 /* API                                                                       */
 /*---------------------------------------------------------------------------*/
@@ -62,12 +64,23 @@
 	struct msm_panel_info *pinfo, struct mdss_dsi_phy_ctrl *phy_db);
 void set_panel_cmd_string(const char *panel_name);
 struct oem_panel_data mdss_dsi_get_oem_data(void);
+struct oem_panel_data *mdss_dsi_get_oem_data_ptr(void);
 struct panel_struct mdss_dsi_get_panel_data(void);
 
 struct oem_panel_data  {
 	char panel[MAX_PANEL_ID_LEN];
+	char sec_panel[MAX_PANEL_ID_LEN];
 	bool cont_splash;
 	bool skip;
+	uint32_t sim_mode;
+	char dsi_config[DSI_CFG_SIZE];
+	uint32_t dsi_pll_src;
+};
+
+enum {
+    DSI_PLL_DEFAULT,
+    DSI_PLL0,
+    DSI_PLL1,
 };
 
 #endif /*_GCDB_DISPLAY_H_ */
diff --git a/dev/gcdb/display/gcdb_display_param.c b/dev/gcdb/display/gcdb_display_param.c
index 027207c..ce98cf0 100644
--- a/dev/gcdb/display/gcdb_display_param.c
+++ b/dev/gcdb/display/gcdb_display_param.c
@@ -37,38 +37,47 @@
 #include "target/display.h"
 #include "fastboot_oem_display.h"
 
-struct oem_panel_data oem_data = {{'\0'}, false, false};
+struct oem_panel_data oem_data = {{'\0'}, {'\0'}, false, false, SIM_NONE, "single_dsi", DSI_PLL_DEFAULT};
 
-void panel_name_to_dt_string(struct panel_lookup_list supp_panels[],
+static int panel_name_to_dt_string(struct panel_lookup_list supp_panels[],
 			  uint32_t supp_panels_size,
-			  const char *panel_name, char **panel_node,
-			  char **slave_panel_node, int *panel_mode)
+			  const char *panel_name, char **panel_node)
 {
 	uint32_t i;
 
 	if (!panel_name) {
 		dprintf(CRITICAL, "Invalid panel name\n");
-		return;
+		return ERR_NOT_VALID;
 	}
 
 	for (i = 0; i < supp_panels_size; i++) {
 		if (!strncmp(panel_name, supp_panels[i].name,
 			MAX_PANEL_ID_LEN)) {
 			*panel_node = supp_panels[i].panel_dt_string;
-			if (supp_panels[i].is_split_dsi) {
-				*slave_panel_node =
-					supp_panels[i].panel_dt_string;
-				*panel_mode = DUAL_DSI_FLAG;
-			} else {
-				*panel_mode = 0;
-			}
+			return supp_panels[i].is_split_dsi;
+		}
+	}
+
+	dprintf(CRITICAL, "Panel_name:%s not found in lookup table\n",
+		panel_name);
+	return ERR_NOT_FOUND;
+}
+
+void sim_override_to_cmdline(struct sim_lookup_list sim[],
+			  uint32_t sim_size, uint32_t sim_mode,
+			  char **sim_string)
+{
+	uint32_t i;
+
+	for (i = 0; i < sim_size; i++) {
+		if (sim_mode == sim[i].sim_mode) {
+			*sim_string = sim[i].override_string;
 			break;
 		}
 	}
 
-	if (i == supp_panels_size)
-		dprintf(CRITICAL, "Panel_name:%s not found in lookup table\n",
-			panel_name);
+	if (i == sim_size)
+		dprintf(CRITICAL, "Sim_mode not found in lookup table\n");
 }
 
 struct oem_panel_data mdss_dsi_get_oem_data(void)
@@ -76,21 +85,106 @@
 	return oem_data;
 }
 
+struct oem_panel_data *mdss_dsi_get_oem_data_ptr(void)
+{
+	return &oem_data;
+}
+
+static char *get_panel_token_end(const char *string)
+{
+	char *ch_hash = NULL, *ch_col = NULL;
+
+	/* ':' and '#' are delimiters in the string */
+	ch_col = strchr((char *) string, ':');
+	ch_hash = strchr((char *) string, '#');
+
+	if (ch_col && ch_hash)
+		return ((ch_col < ch_hash) ? ch_col : ch_hash);
+	else if (ch_col)
+		return ch_col;
+	else if (ch_hash)
+		return ch_hash;
+	return NULL;
+}
+
 void set_panel_cmd_string(const char *panel_name)
 {
-	char *ch = NULL;
+	char *ch = NULL, *ch_tmp = NULL;
 	int i;
 
 	panel_name += strspn(panel_name, " ");
 
-	/* Panel string */
-	ch = strchr((char *) panel_name, ':');
+	/* Primary panel string */
+	ch = strstr((char *) panel_name, "prim:");
 	if (ch) {
-		for (i = 0; (panel_name + i) < ch; i++)
-			oem_data.panel[i] = *(panel_name + i);
+		/*
+		 * Parse the primary panel for cases where 'prim' prefix
+		 * is present in the fastboot oem command before primary
+		 * panel string.
+		 * Examples:
+		 * 1.) fastboot oem select-display-panel prim:jdi_1080p_video:sec:sharp_1080p_cmd
+		 * 2.) fastboot oem select-display-panel prim:jdi_1080p_video:skip:sec:sharp_1080p_cmd
+		 * 3.) fastboot oem select-display-panel prim:jdi_1080p_video:disable:sec:sharp_1080p_cmd
+		 * 4.) fastboot oem select-display-panel prim:jdi_1080p_video:skip#sim:sec:sharp_1080p_cmd
+		 */
+		ch += 5;
+		ch_tmp = get_panel_token_end((const char*) ch);
+		if (!ch_tmp)
+			ch_tmp = ch + strlen(ch);
+		for (i = 0; (ch + i) < ch_tmp; i++)
+			oem_data.panel[i] = *(ch + i);
 		oem_data.panel[i] = '\0';
 	} else {
-		strlcpy(oem_data.panel, panel_name, MAX_PANEL_ID_LEN);
+		/*
+		 * Check if secondary panel string is present.
+		 * The 'prim' prefix definitely needs to be present
+		 * to specify primary panel for cases where secondary panel
+		 * is also specified in fastboot oem command. Otherwise, it
+		 * becomes tough to parse the fastboot oem command for primary
+		 * panel. If 'sec' prefix is used without 'prim' prefix, it
+		 * means the default panel needs to be picked as primary panel.
+		 * Example:
+		 * fastboot oem select-display-panel sec:sharp_1080p_cmd
+		 */
+		ch = strstr((char *) panel_name, "sec:");
+		if (!ch) {
+			/*
+			 * This code will be executed for cases where the
+			 * secondary panel is not specified i.e., single/split
+			 * DSI cases.
+			 * Examples:
+			 * 1.) fastboot oem select-display-panel jdi_1080p_video
+			 * 2.) fastboot oem select-display-panel sharp_1080p_cmd:skip
+			 * 3.) fastboot oem select-display-panel sharp_1080p_cmd:disable
+			 * 4.) fastboot oem select-display-panel sim_cmd_panel#sim-swte
+			 */
+			ch = get_panel_token_end(panel_name);
+			if (ch) {
+				for (i = 0; (panel_name + i) < ch; i++)
+					oem_data.panel[i] =
+						*(panel_name + i);
+				oem_data.panel[i] = '\0';
+			} else {
+				strlcpy(oem_data.panel, panel_name,
+					MAX_PANEL_ID_LEN);
+			}
+		}
+	}
+
+	/*
+	 * Secondary panel string.
+	 * This is relatively simple. The secondary panel string gets
+	 * parsed if the 'sec' prefix is present.
+	 */
+	ch = strstr((char *) panel_name, "sec:");
+	if (ch) {
+		ch += 4;
+		ch_tmp = get_panel_token_end((const char*) ch);
+		if (!ch_tmp)
+			ch_tmp = ch + strlen(ch);
+		for (i = 0; (ch + i) < ch_tmp; i++)
+			oem_data.sec_panel[i] = *(ch + i);
+		oem_data.sec_panel[i] = '\0';
 	}
 
 	/* Skip LK configuration */
@@ -100,11 +194,33 @@
 	/* Cont. splash status */
 	ch = strstr((char *) panel_name, ":disable");
 	oem_data.cont_splash = ch ? false : true;
+
+	/* DSI PLL source */
+	ch = strstr((char *) panel_name, ":pll0");
+	if (ch) {
+		oem_data.dsi_pll_src = DSI_PLL0;
+	} else {
+		ch = strstr((char *) panel_name, ":pll1");
+		if (ch)
+			oem_data.dsi_pll_src = DSI_PLL1;
+	}
+
+	/* Simulator status */
+	oem_data.sim_mode = SIM_NONE;
+	if (strstr((char *) panel_name, "#sim-hwte"))
+		oem_data.sim_mode = SIM_HWTE;
+	else if (strstr((char *) panel_name, "#sim-swte"))
+		oem_data.sim_mode = SIM_SWTE;
+	else if (strstr((char *) panel_name, "#sim"))
+		oem_data.sim_mode = SIM_MODE;
+
 }
 
 static bool mdss_dsi_set_panel_node(char *panel_name, char **dsi_id,
 		char **panel_node, char **slave_panel_node, int *panel_mode)
 {
+	int rc = 0;
+
 	if (!strcmp(panel_name, SIM_VIDEO_PANEL)) {
 		*dsi_id = SIM_DSI_ID;
 		*panel_node = SIM_VIDEO_PANEL_NODE;
@@ -126,12 +242,21 @@
 	} else if (oem_data.skip) {
 		/* For skip panel case, check the lookup table */
 		*dsi_id = SIM_DSI_ID;
-		panel_name_to_dt_string(lookup_skip_panels,
+		rc = panel_name_to_dt_string(lookup_skip_panels,
 			ARRAY_SIZE(lookup_skip_panels), panel_name,
-			panel_node, slave_panel_node, panel_mode);
+			panel_node);
+		if (rc < 0) {
+			return false;
+		} else if (rc == 1) {
+			*slave_panel_node = *panel_node;
+			*panel_mode = DUAL_DSI_FLAG;
+		} else {
+			*panel_mode = 0;
+		}
 	} else {
 		return false;
 	}
+
 	return true;
 }
 
@@ -140,15 +265,16 @@
 	char *dsi_id = NULL;
 	char *panel_node = NULL;
 	char *slave_panel_node = NULL;
+	char *sim_mode_string = NULL;
 	uint16_t dsi_id_len = 0, panel_node_len = 0, slave_panel_node_len = 0;
 	uint32_t arg_size = 0;
-	bool ret = true;
-	bool rc;
+	bool ret = true, rc;
+	int ret_val;
 	char *default_str;
 	struct panel_struct panelstruct;
 	int panel_mode = SPLIT_DISPLAY_FLAG | DUAL_PIPE_FLAG | DST_SPLIT_FLAG;
 	int prefix_string_len = strlen(DISPLAY_CMDLINE_PREFIX);
-	char *sctl_string;
+	char *sctl_string, *pll_src_string = NULL;
 
 	panelstruct = mdss_dsi_get_panel_data();
 
@@ -196,13 +322,44 @@
 		return false;
 	}
 
+	if (oem_data.sec_panel) {
+		if (panel_mode & (DUAL_DSI_FLAG | SPLIT_DISPLAY_FLAG |
+			DST_SPLIT_FLAG)) {
+			dprintf(CRITICAL, "Invalid config: Primary panel is"
+				"split DSI and still secondary panel passed\n");
+		} else {
+			ret_val = panel_name_to_dt_string(lookup_skip_panels,
+				ARRAY_SIZE(lookup_skip_panels), oem_data.sec_panel,
+				&slave_panel_node);
+			if (ret_val < 0) {
+				dprintf(CRITICAL, "Sec. panel not found."
+					" Continue with primary panel\n");
+			} else if (ret_val == 1) {
+				dprintf(CRITICAL, "Invalid config: Secondary panel cant"
+					"be split DSI. Continue with primary panel\n");
+				slave_panel_node = NULL;
+			}
+		}
+	}
+
+	/* Check for the DSI configuration */
+	if (slave_panel_node && (panel_mode & (DUAL_DSI_FLAG |
+		SPLIT_DISPLAY_FLAG | DST_SPLIT_FLAG)))
+		strcpy(oem_data.dsi_config, "split_dsi");
+	else if (slave_panel_node)
+		strcpy(oem_data.dsi_config, "dual_dsi");
+	else
+		strcpy(oem_data.dsi_config, "single_dsi");
+
+	arg_size = DSI_CFG_STRING_LEN + strlen(oem_data.dsi_config);
+
 	dsi_id_len = strlen(dsi_id);
 	panel_node_len = strlen(panel_node);
 	if (!slave_panel_node || !strcmp(slave_panel_node, ""))
 		slave_panel_node = NO_PANEL_CONFIG;
 	slave_panel_node_len = strlen(slave_panel_node);
 
-	arg_size = prefix_string_len + dsi_id_len + panel_node_len +
+	arg_size += prefix_string_len + dsi_id_len + panel_node_len +
 						LK_OVERRIDE_PANEL_LEN + 1;
 
 	if (panelstruct.paneldata &&
@@ -213,6 +370,35 @@
 
 	arg_size += strlen(sctl_string) + slave_panel_node_len;
 
+	if (oem_data.skip && !strcmp(oem_data.dsi_config, "dual_dsi") &&
+		(oem_data.dsi_pll_src != DSI_PLL_DEFAULT)) {
+		dprintf(CRITICAL, "Dual DSI config detected!"
+			" Use default PLL\n");
+		oem_data.dsi_pll_src = DSI_PLL_DEFAULT;
+	}
+
+	if (oem_data.dsi_pll_src != DSI_PLL_DEFAULT) {
+		if (oem_data.dsi_pll_src == DSI_PLL0)
+			pll_src_string = DSI_PLL0_STRING;
+		else
+			pll_src_string = DSI_PLL1_STRING;
+
+		arg_size += strlen(pll_src_string);
+	}
+
+	if (oem_data.sim_mode != SIM_NONE) {
+		sim_override_to_cmdline(lookup_sim,
+			ARRAY_SIZE(lookup_sim), oem_data.sim_mode,
+			&sim_mode_string);
+		if (sim_mode_string) {
+			arg_size += LK_SIM_OVERRIDE_LEN +
+				strlen(sim_mode_string);
+		} else {
+			dprintf(CRITICAL, "SIM string NULL but mode is not NONE\n");
+			return false;
+		}
+	}
+
 	if (buf_size < arg_size) {
 		dprintf(CRITICAL, "display command line buffer is small\n");
 		ret = false;
@@ -230,14 +416,40 @@
 		buf_size -= dsi_id_len;
 
 		strlcpy(pbuf, panel_node, buf_size);
-
 		pbuf += panel_node_len;
 		buf_size -= panel_node_len;
 
 		strlcpy(pbuf, sctl_string, buf_size);
 		pbuf += strlen(sctl_string);
 		buf_size -= strlen(sctl_string);
+
 		strlcpy(pbuf, slave_panel_node, buf_size);
+		pbuf += slave_panel_node_len;
+		buf_size -= slave_panel_node_len;
+
+		strlcpy(pbuf, DSI_CFG_STRING, buf_size);
+		pbuf += DSI_CFG_STRING_LEN;
+		buf_size -= DSI_CFG_STRING_LEN;
+
+		strlcpy(pbuf, oem_data.dsi_config, buf_size);
+		pbuf += strlen(oem_data.dsi_config);
+		buf_size -= strlen(oem_data.dsi_config);
+
+		if (pll_src_string) {
+			strlcpy(pbuf, pll_src_string, buf_size);
+			pbuf += strlen(pll_src_string);
+			buf_size -= strlen(pll_src_string);
+		}
+
+		if (sim_mode_string) {
+			strlcpy(pbuf, LK_SIM_OVERRIDE, buf_size);
+			pbuf += LK_SIM_OVERRIDE_LEN;
+			buf_size -= LK_SIM_OVERRIDE_LEN;
+
+			strlcpy(pbuf, sim_mode_string, buf_size);
+			pbuf += strlen(sim_mode_string);
+			buf_size -= strlen(sim_mode_string);
+		}
 	}
 	return ret;
 }
diff --git a/dev/gcdb/display/include/display_resource.h b/dev/gcdb/display/include/display_resource.h
index 6fc177a..12437aa 100755
--- a/dev/gcdb/display/include/display_resource.h
+++ b/dev/gcdb/display/include/display_resource.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 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
@@ -42,11 +42,20 @@
 #define LK_OVERRIDE_PANEL      "1:"
 #define LK_OVERRIDE_PANEL_LEN  2
 
+#define LK_SIM_OVERRIDE     "#override:"
+#define LK_SIM_OVERRIDE_LEN  10
+
 #define DSI_0_STRING           ":0:"
 #define DSI_0_STRING_LEN       3
 #define DSI_1_STRING           ":1:"
 #define DSI_1_STRING_LEN       3
 
+#define DSI_CFG_STRING         ":cfg:"
+#define DSI_CFG_STRING_LEN	5
+
+#define DSI_PLL0_STRING         ":pll0"
+#define DSI_PLL1_STRING         ":pll1"
+
 #define NO_PANEL_CONFIG "none"
 #define SIM_VIDEO_PANEL "sim_video_panel"
 #define SIM_DUALDSI_VIDEO_PANEL "sim_dualdsi_video_panel"
diff --git a/dev/gcdb/display/include/panel_nt35597_wqxga_dualdsi_cmd.h b/dev/gcdb/display/include/panel_nt35597_wqxga_dualdsi_cmd.h
index b2bf27f..b01752a 100644
--- a/dev/gcdb/display/include/panel_nt35597_wqxga_dualdsi_cmd.h
+++ b/dev/gcdb/display/include/panel_nt35597_wqxga_dualdsi_cmd.h
@@ -230,7 +230,7 @@
 /* Panel timing                                                              */
 /*---------------------------------------------------------------------------*/
 static const uint32_t nt35597_wqxga_dualdsi_cmd_timings[] = {
-	0xe2, 0x36, 0x24, 0x00, 0x66, 0x6a, 0x28, 0x38,  0x2a, 0x03, 0x04, 0x00
+	0xd5, 0x32, 0x22, 0x00, 0x60, 0x64, 0x26, 0x36, 0x29, 0x03, 0x04, 0x00
 };
 
 static const uint32_t nt35597_wqxga_dualdsi_thulium_cmd_timings[] = {
diff --git a/dev/pmic/pm8x41/include/pm8x41_hw.h b/dev/pmic/pm8x41/include/pm8x41_hw.h
index 0a8e2e8..2bae818 100644
--- a/dev/pmic/pm8x41/include/pm8x41_hw.h
+++ b/dev/pmic/pm8x41/include/pm8x41_hw.h
@@ -94,6 +94,9 @@
 /* USB Peripheral registers */
 #define SMBCHGL_USB_ICL_STS_2                 0x1309
 
+/* PMI8950 slave id */
+#define PMI8950_SLAVE_ID 0x20000
+
 /* USB Peripheral register bits */
 #define USBIN_ACTIVE_PWR_SRC                  BIT(0)
 #define DCIN_ACTIVE_PWR_SRC                   BIT(1)
diff --git a/dev/pmic/pm8x41/pm8x41.c b/dev/pmic/pm8x41/pm8x41.c
index 6733656..0a43bff 100644
--- a/dev/pmic/pm8x41/pm8x41.c
+++ b/dev/pmic/pm8x41/pm8x41.c
@@ -545,7 +545,7 @@
 {
 	uint8_t pon_reason = 0;
 
-	pon_reason = REG_READ(SMBCHGL_USB_ICL_STS_2);
+	pon_reason = REG_READ(SMBCHGL_USB_ICL_STS_2|PMI8950_SLAVE_ID);
 	/* check usbin/dcin status on pmi and set the corresponding bits for pon */
 	pon_reason = (pon_reason & (USBIN_ACTIVE_PWR_SRC|DCIN_ACTIVE_PWR_SRC)) << 3 ;
 	pon_reason |= REG_READ(PON_PON_REASON1);
diff --git a/target/mdm9640/init.c b/target/mdm9640/init.c
index 567ccde..2d2bb4b 100644
--- a/target/mdm9640/init.c
+++ b/target/mdm9640/init.c
@@ -84,7 +84,7 @@
 #define LAST_NAND_PTN_LEN_PATTERN                     0xFFFFFFFF
 
 #define EXT4_CMDLINE  " rootwait rootfstype=ext4 root=/dev/mmcblk0p"
-#define UBI_CMDLINE " rootfstype=ubifs rootflags=bulk_read ubi.fm_autoconvert=1"
+#define UBI_CMDLINE " rootfstype=ubifs rootflags=bulk_read"
 
 struct qpic_nand_init_config config;
 
@@ -135,6 +135,8 @@
 {
 	dprintf(INFO, "target_init()\n");
 
+	pmic_info_populate();
+
 	spmi_init(PMIC_ARB_CHANNEL_NUM, PMIC_ARB_OWNER_ID);
 
 	if (platform_boot_dev_isemmc()) {
diff --git a/target/msm8952/include/target/display.h b/target/msm8952/include/target/display.h
index 5c02765..87cbc3a 100644
--- a/target/msm8952/include/target/display.h
+++ b/target/msm8952/include/target/display.h
@@ -91,8 +91,6 @@
 #define MIPI_VSYNC_BACK_PORCH_LINES  3
 #define MIPI_VSYNC_FRONT_PORCH_LINES 9
 
-#endif
-
 /*---------------------------------------------------------------------------*/
 /* Functions		                                                     */
 /*---------------------------------------------------------------------------*/
@@ -104,3 +102,6 @@
 int target_display_get_base_offset(uint32_t base);
 void target_force_cont_splash_disable(uint8_t override);
 uint8_t target_panel_auto_detect_enabled();
+uint32_t oem_panel_max_auto_detect_panels();
+
+#endif
diff --git a/target/msm8952/init.c b/target/msm8952/init.c
index 99550f5..e1a61c4 100644
--- a/target/msm8952/init.c
+++ b/target/msm8952/init.c
@@ -503,6 +503,23 @@
         splash_override = override;
 }
 
+uint8_t target_panel_auto_detect_enabled()
+{
+	uint8_t ret = 0;
+
+	switch(board_hardware_id())
+	{
+		case HW_PLATFORM_QRD:
+			ret = platform_is_msm8956() ? 1 : 0;
+			break;
+		case HW_PLATFORM_SURF:
+		case HW_PLATFORM_MTP:
+		default:
+			ret = 0;
+	}
+	return ret;
+}
+
 /* Do any target specific intialization needed before entering fastboot mode */
 void target_fastboot_init(void)
 {
diff --git a/target/msm8952/oem_panel.c b/target/msm8952/oem_panel.c
index b64ac32..603f990 100644
--- a/target/msm8952/oem_panel.c
+++ b/target/msm8952/oem_panel.c
@@ -49,6 +49,7 @@
 #include "include/panel_sharp_1080p_cmd.h"
 #include "include/panel_nt35597_wqxga_dualdsi_video.h"
 #include "include/panel_nt35597_wqxga_dualdsi_cmd.h"
+#include "include/panel_hx8399a_1080p_video.h"
 
 /*---------------------------------------------------------------------------*/
 /* static panel selection variable                                           */
@@ -60,6 +61,7 @@
 	SHARP_1080P_CMD_PANEL,
 	NT35597_WQXGA_DUALDSI_VIDEO_PANEL,
 	NT35597_WQXGA_DUALDSI_CMD_PANEL,
+	HX8399A_1080P_VIDEO_PANEL,
 	UNKNOWN_PANEL
 };
 
@@ -77,6 +79,8 @@
 	{"sharp_1080p_cmd", SHARP_1080P_CMD_PANEL},
 	{"nt35597_wqxga_dualdsi_video", NT35597_WQXGA_DUALDSI_VIDEO_PANEL},
 	{"nt35597_wqxga_dualdsi_cmd", NT35597_WQXGA_DUALDSI_CMD_PANEL},
+	{"otm1906c_1080p_cmd", OTM1906C_1080P_CMD_PANEL},
+	{"hx8399a_1080p_video", HX8399A_1080P_VIDEO_PANEL},
 };
 
 static uint32_t panel_id;
@@ -198,6 +202,31 @@
 			otm1906c_1080p_cmd_timings, TIMING_SIZE);
 		pinfo->mipi.signature = OTM1906C_1080P_CMD_SIGNATURE;
 		break;
+	case HX8399A_1080P_VIDEO_PANEL:
+		panelstruct->paneldata    = &hx8399a_1080p_video_panel_data;
+		panelstruct->panelres     = &hx8399a_1080p_video_panel_res;
+		panelstruct->color        = &hx8399a_1080p_video_color;
+		panelstruct->videopanel   = &hx8399a_1080p_video_video_panel;
+		panelstruct->commandpanel = &hx8399a_1080p_video_command_panel;
+		panelstruct->state        = &hx8399a_1080p_video_state;
+		panelstruct->laneconfig   = &hx8399a_1080p_video_lane_config;
+		panelstruct->paneltiminginfo
+			= &hx8399a_1080p_video_timing_info;
+		panelstruct->panelresetseq
+					 = &hx8399a_1080p_video_reset_seq;
+		panelstruct->backlightinfo = &hx8399a_1080p_video_backlight;
+		pinfo->mipi.panel_on_cmds
+			= hx8399a_1080p_video_on_command;
+		pinfo->mipi.num_of_panel_on_cmds
+			= HX8399A_1080P_VIDEO_ON_COMMAND;
+		pinfo->mipi.panel_off_cmds
+			= hx8399a_1080p_video_off_command;
+		pinfo->mipi.num_of_panel_off_cmds
+			= HX8399A_1080P_VIDEO_OFF_COMMAND;
+		memcpy(phy_db->timing,
+			hx8399a_1080p_video_timings, TIMING_SIZE);
+		pinfo->mipi.signature = HX8399A_1080P_VIDEO_SIGNATURE;
+		break;
 	case SHARP_1080P_CMD_PANEL:
 		panelstruct->paneldata    = &sharp_1080p_cmd_panel_data;
 		panelstruct->panelres     = &sharp_1080p_cmd_panel_res;
@@ -268,6 +297,9 @@
 		panelstruct->laneconfig   = &nt35597_wqxga_dualdsi_cmd_lane_config;
 		panelstruct->paneltiminginfo
 			= &nt35597_wqxga_dualdsi_cmd_timing_info;
+		/* Clkout timings are different for this panel on 8956 */
+		panelstruct->paneltiminginfo->tclk_post = 0x2b;
+		panelstruct->paneltiminginfo->tclk_pre = 0x28;
 		panelstruct->panelresetseq
 					 = &nt35597_wqxga_dualdsi_cmd_reset_seq;
 		panelstruct->backlightinfo = &nt35597_wqxga_dualdsi_cmd_backlight;
@@ -302,6 +334,15 @@
 	return pan_type;
 }
 
+#define DISPLAY_MAX_PANEL_DETECTION 2
+static uint32_t auto_pan_loop = 0;
+
+uint32_t oem_panel_max_auto_detect_panels()
+{
+	return target_panel_auto_detect_enabled() ?
+		DISPLAY_MAX_PANEL_DETECTION : 0;
+}
+
 int oem_panel_select(const char *panel_name, struct panel_struct *panelstruct,
 			struct msm_panel_info *pinfo,
 			struct mdss_dsi_phy_ctrl *phy_db)
@@ -341,6 +382,24 @@
 		break;
 	case HW_PLATFORM_QRD:
 		panel_id = OTM1906C_1080P_CMD_PANEL;
+
+		/* QRD EVT1 uses OTM1906C, and EVT2 uses HX8399A */
+		if (platform_is_msm8956()) {
+			switch (auto_pan_loop) {
+				case 0:
+					panel_id = HX8399A_1080P_VIDEO_PANEL;
+					break;
+				case 1:
+					panel_id = OTM1906C_1080P_CMD_PANEL;
+					break;
+				default:
+					panel_id = UNKNOWN_PANEL;
+					dprintf(CRITICAL, "Unknown panel\n");
+					return PANEL_TYPE_UNKNOWN;
+			}
+			auto_pan_loop++;
+		}
+
 		break;
 	default:
 		dprintf(CRITICAL, "Display not enabled for %d HW type\n",
diff --git a/target/msm8952/target_display.c b/target/msm8952/target_display.c
index e89beb5..adc5815 100644
--- a/target/msm8952/target_display.c
+++ b/target/msm8952/target_display.c
@@ -522,6 +522,8 @@
 void target_display_init(const char *panel_name)
 {
 	struct oem_panel_data oem;
+	int32_t ret = 0;
+	uint32_t panel_loop = 0;
 
 	set_panel_cmd_string(panel_name);
 	oem = mdss_dsi_get_oem_data();
@@ -535,10 +537,16 @@
 		return;
 	}
 
-	if (gcdb_display_init(oem.panel, MDP_REV_50, (void *)MIPI_FB_ADDR)) {
-		target_force_cont_splash_disable(true);
-		msm_display_off();
-	}
+	do {
+		target_force_cont_splash_disable(false);
+		ret = gcdb_display_init(oem.panel, MDP_REV_50, (void *)MIPI_FB_ADDR);
+		if (!ret || ret == ERR_NOT_SUPPORTED) {
+			break;
+		} else {
+			target_force_cont_splash_disable(true);
+			msm_display_off();
+		}
+	} while (++panel_loop <= oem_panel_max_auto_detect_panels());
 
 	if (!oem.cont_splash) {
 		dprintf(INFO, "Forcing continuous splash disable\n");