Merge 958689fea261475185eb42f5a97f2822175d1e9c on remote branch

Change-Id: I3e66793c314a2b1e654e91353c4002515ff42da8
diff --git a/dev/gcdb/display/include/panel_edo_rm67162_qvga_cmd.h b/dev/gcdb/display/include/panel_edo_rm67162_qvga_cmd.h
index d91a1b7..3199619 100644
--- a/dev/gcdb/display/include/panel_edo_rm67162_qvga_cmd.h
+++ b/dev/gcdb/display/include/panel_edo_rm67162_qvga_cmd.h
@@ -38,7 +38,7 @@
 /*---------------------------------------------------------------------------*/
 static struct panel_config edo_rm67162_qvga_cmd_panel_data = {
 	"qcom,mdss_dsi_edo_rm67162_qvga_cmd", "dsi:0:", "qcom,mdss-dsi-panel",
-	10, 1, "DISPLAY_1", 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+	10, 1, "DISPLAY_1", 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL
 };
 
 /*---------------------------------------------------------------------------*/
@@ -90,7 +90,7 @@
 
 static char edo_rm67162_qvga_cmd_on_cmd6[] = {
 	0x02, 0x00, 0x29, 0xC0,
-	0x51, 0x00, 0xFF, 0xFF,
+	0x51, 0xFF, 0xFF, 0xFF,
 };
 
 static char edo_rm67162_qvga_cmd_on_cmd7[] = {
@@ -172,18 +172,18 @@
 /* Lane configuration                                                        */
 /*---------------------------------------------------------------------------*/
 static struct lane_configuration edo_rm67162_qvga_cmd_lane_config = {
-	1, 0, 1, 0, 0, 0
+	1, 0, 1, 0, 0, 0, 0
 };
 
 /*---------------------------------------------------------------------------*/
 /* Panel timing                                                              */
 /*---------------------------------------------------------------------------*/
 static const uint32_t edo_rm67162_qvga_cmd_12nm_timings[] = {
-	0x06, 0x05, 0x01, 0x01, 0x00, 0x03, 0x01, 0x03
+	0x06, 0x05, 0x01, 0x0A, 0x00, 0x03, 0x01, 0x0F
 };
 
 static struct panel_timing edo_rm67162_qvga_cmd_timing_info = {
-	0, 4, 0x20, 0x2c
+	0, 4, 0x09, 0x2c
 };
 
 /*---------------------------------------------------------------------------*/
@@ -197,7 +197,7 @@
 /* Backlight setting                                                         */
 /*---------------------------------------------------------------------------*/
 static struct backlight edo_rm67162_qvga_cmd_backlight = {
-	1, 1, 4095, 100, 1, "PMIC_8941"
+	2, 1, 255, 100, 2, "BL_CTL_DCS"
 };
 
 #endif /*_PANEL_EDO_RM67162_QVGA_CMD_H_*/
diff --git a/include/km_main.h b/include/km_main.h
index 544dc55..117c24e 100644
--- a/include/km_main.h
+++ b/include/km_main.h
@@ -72,6 +72,7 @@
     KEYMASTER_MILESTONE_CALL				= (KEYMASTER_UTILS_CMD_ID + 4UL),
     KEYMASTER_SECURE_WRITE_PROTECT			= (KEYMASTER_UTILS_CMD_ID + 6UL),
     KEYMASTER_SET_VBH					= (KEYMASTER_UTILS_CMD_ID + 17UL),
+    KEYMASTER_GET_DATE_SUPPORT				= (KEYMASTER_UTILS_CMD_ID + 21UL),
 
     KEYMASTER_LAST_CMD_ENTRY				= (int)0xFFFFFFFFULL
 } keymaster_cmd_t;
@@ -279,4 +280,12 @@
 	int status;
 } __attribute__ ((packed)) km_set_vbh_rsp_t;
 
+typedef struct {
+	uint32_t cmd_id;
+} __attribute__ ((packed)) km_get_date_support_req;
+
+typedef struct {
+	int32_t status;
+} __attribute__ ((packed)) km_get_date_support_rsp;
+
 #endif /* KM_MAIN_H */
diff --git a/platform/msm_shared/avb/VerifiedBoot.c b/platform/msm_shared/avb/VerifiedBoot.c
index 642747d..7a06655 100644
--- a/platform/msm_shared/avb/VerifiedBoot.c
+++ b/platform/msm_shared/avb/VerifiedBoot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, 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 are
@@ -48,6 +48,7 @@
 #define MAX_PART_NAME_SIZE		10
 #define MAX_NUM_REQ_PARTITION	8
 #define BOOT_HEADER_VERSION_ZERO	0
+#define MAX_PROPERTY_SIZE        10
 
 char *avb_verify_partition_name[] = {
 	"boot",
@@ -359,6 +360,43 @@
 	}
 }
 
+static UINT32 ParseBootSecurityLevel (const CHAR8 *BootSecurityLevel,
+                                      size_t BootSecurityLevelStrSize)
+{
+	UINT32 PatchLevelDate = 0;
+	UINT32 PatchLevelMonth = 0;
+	UINT32 PatchLevelYear = 0;
+	UINT32 SeparatorCount = 0;
+	UINT32 Count = 0;
+
+	/*Parse the value of security patch as per YYYY-MM-DD format*/
+	while (Count < BootSecurityLevelStrSize) {
+		if (BootSecurityLevel[Count] == '-') {
+			SeparatorCount++;
+		}
+		else if (SeparatorCount == 2) {
+			PatchLevelDate *= 10;
+			PatchLevelDate += (BootSecurityLevel[Count] - '0');
+		}
+		else if (SeparatorCount == 1) {
+			PatchLevelMonth *= 10;
+			PatchLevelMonth += (BootSecurityLevel[Count] - '0');
+		}
+		else if (SeparatorCount == 0) {
+			PatchLevelYear *= 10;
+			PatchLevelYear += (BootSecurityLevel[Count] - '0');
+		}
+		else {
+			return -1;
+		}
+		Count++;
+	}
+
+	PatchLevelDate = PatchLevelDate << 11;
+	PatchLevelYear = (PatchLevelYear - 2000) << 4;
+	return (PatchLevelDate | PatchLevelYear | PatchLevelMonth);
+}
+
 static VOID ComputeVbMetaDigest (AvbSlotVerifyData* SlotData, CHAR8* Digest) {
 	size_t Index;
 	AvbSHA256Ctx Ctx;
@@ -397,6 +435,9 @@
 	AvbHashtreeErrorMode VerityFlags = AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE;
 	device_info DevInfo_vb;
 	CHAR8 Digest[AVB_SHA256_DIGEST_SIZE] = {0};
+	const CHAR8 *BootSecurityLevelStr = NULL;
+	size_t BootSecurityLevelStrSize = 0;
+	INT32 BootSecurityLevel = 0;
 
 	HeaderVersion = Info->header_version;
 	Info->boot_state = RED;
@@ -568,7 +609,28 @@
 	GUARD_OUT(AppendVBCommonCmdLine(Info));
 	GUARD_OUT(Appendvbcmdline(Info, SlotData->cmdline));
 	DevInfo_vb.is_unlocked = !is_device_locked();
-	set_os_version(ADD_SALT_BUFF_OFFSET(Info->images[0].image_buffer));
+
+	/* Send date value in security patch only when KM TA supports it and the
+	*  property is available in vbmeta data, send the old value in other cases
+	*/
+	BootSecurityLevelStr = avb_property_lookup (
+						SlotData->vbmeta_images[0].vbmeta_data,
+						SlotData->vbmeta_images[0].vbmeta_size,
+						"com.android.build.boot.security_patch",
+						0, &BootSecurityLevelStrSize);
+
+	if (BootSecurityLevelStr != NULL &&
+		BootSecurityLevelStrSize == MAX_PROPERTY_SIZE) {
+		BootSecurityLevel = ParseBootSecurityLevel (BootSecurityLevelStr,
+								BootSecurityLevelStrSize);
+		if (BootSecurityLevel < 0) {
+			dprintf (CRITICAL, "System security patch level format invalid\n");
+			Status = EFI_INVALID_PARAMETER;
+			goto out;
+		}
+	}
+
+	set_os_version_with_date(ADD_SALT_BUFF_OFFSET(Info->images[0].image_buffer), BootSecurityLevel);
 	if(!send_rot_command((uint32_t)DevInfo_vb.is_unlocked))
 		return EFI_LOAD_ERROR;
 
diff --git a/platform/msm_shared/avb/libavb/avb_slot_verify.c b/platform/msm_shared/avb/libavb/avb_slot_verify.c
index e0049e6..5818fa1 100644
--- a/platform/msm_shared/avb/libavb/avb_slot_verify.c
+++ b/platform/msm_shared/avb/libavb/avb_slot_verify.c
@@ -1276,6 +1276,35 @@
   return ret;
 }
 
+static bool has_system_partition(AvbOps* ops, const char* ab_suffix) {
+  char part_name[PART_NAME_MAX_SIZE];
+  char* system_part_name = "system";
+  char guid_buf[37];
+  AvbIOResult io_ret;
+
+  if (!avb_str_concat(part_name,
+                      sizeof part_name,
+                      system_part_name,
+                      avb_strlen(system_part_name),
+                      ab_suffix,
+                      avb_strlen(ab_suffix))) {
+    avb_error("System partition name and suffix does not fit.\n");
+    return false;
+  }
+
+  io_ret = ops->get_unique_guid_for_partition(
+      ops, part_name, guid_buf, sizeof guid_buf);
+  if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION) {
+    avb_debug("No system partition.\n");
+    return false;
+  } else if (io_ret != AVB_IO_RESULT_OK) {
+    avb_error("Error getting unique GUID for system partition.\n");
+    return false;
+  }
+
+  return true;
+}
+
 AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
                                     const char* const* requested_partitions,
                                     const char* ab_suffix,
@@ -1377,8 +1406,16 @@
        * that the system partition is mounted.
        */
       avb_assert(slot_data->cmdline == NULL);
-      slot_data->cmdline =
-          avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
+      // Devices with dynamic partitions won't have system partition.
+      // Instead, it has a large super partition to accommodate *.img files.
+      // See b/119551429 for details.
+      if (has_system_partition(ops, ab_suffix)) {
+        slot_data->cmdline =
+            avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
+      } else {
+        // The |cmdline| field should be a NUL-terminated string.
+        slot_data->cmdline = avb_strdup("");
+      }
       if (slot_data->cmdline == NULL) {
         ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
         goto fail;
@@ -1399,7 +1436,7 @@
     }
 
     /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
-    if (slot_data->cmdline != NULL) {
+    if (slot_data->cmdline != NULL && avb_strlen(slot_data->cmdline) != 0) {
       char* new_cmdline;
       new_cmdline = sub_cmdline(
           ops, slot_data->cmdline, ab_suffix, using_boot_for_vbmeta);
diff --git a/platform/msm_shared/boot_verifier.c b/platform/msm_shared/boot_verifier.c
index 4bc0995..caee469 100644
--- a/platform/msm_shared/boot_verifier.c
+++ b/platform/msm_shared/boot_verifier.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016, 2019 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 are
@@ -779,6 +779,25 @@
 	return oem_keystore;
 }
 
+void set_os_version_with_date(unsigned char* img_addr, uint32_t system_security_level)
+{
+	boot_img_hdr *img_hdr = NULL;
+	bool supported;
+	int ret = get_date_support (&supported);
+
+	/* Extract the os version and patch level */
+	if (img_addr) {
+		img_hdr = (boot_img_hdr *)img_addr;
+		boot_state_info.system_version = (img_hdr->os_version & 0xFFFFF800) >> 11;
+		if(!ret && supported && system_security_level)
+			boot_state_info.system_security_level = system_security_level;
+		else
+			boot_state_info.system_security_level = (img_hdr->os_version & 0x7FF);
+	} else {
+		dprintf(CRITICAL, "Image address should not be NULL\n");
+	}
+}
+
 #if OSVERSION_IN_BOOTIMAGE
 void set_os_version(unsigned char* img_addr)
 {
@@ -825,3 +844,26 @@
 	}
 	return ret;
 }
+
+int get_date_support (bool *supported)
+{
+	int status = 0;
+	km_get_date_support_req date_support_req = {0};
+	km_get_date_support_rsp date_support_rsp = {0};
+	int app_handle = get_secapp_handle();
+
+	date_support_req.cmd_id = KEYMASTER_GET_DATE_SUPPORT;
+	status = qseecom_send_command (app_handle, (void *)&date_support_req, sizeof (date_support_req), (void *)&date_support_rsp, sizeof (date_support_rsp));
+	if (status != 0 || date_support_rsp.status != 0 ) {
+		dprintf(CRITICAL, "QSEEcom command to get date support returned error, status: %d\n",date_support_rsp.status);
+
+		if (status == 0 && date_support_rsp.status == KM_ERROR_INVALID_TAG) {
+			dprintf(INFO, "Date in patch level NOT supported in keymaster\n");
+		}
+		*supported = false;
+		return status;
+	}
+
+	*supported = true;
+	return status;
+}
diff --git a/platform/msm_shared/include/boot_verifier.h b/platform/msm_shared/include/boot_verifier.h
index 5525a7a..6d2b2db 100644
--- a/platform/msm_shared/include/boot_verifier.h
+++ b/platform/msm_shared/include/boot_verifier.h
@@ -178,6 +178,7 @@
 bool send_rot_command(uint32_t is_unlocked);
 /* function to set the os version and patch level. */
 void set_os_version(unsigned char* img_addr);
+void set_os_version_with_date(unsigned char* img_addr, uint32_t system_security_level);
 unsigned char* get_boot_fingerprint(unsigned int* buf_size);
 bool boot_verify_compare_sha256(unsigned char *image_ptr,
 		unsigned int image_size, unsigned char *signature_ptr, RSA *rsa);
@@ -185,4 +186,7 @@
 uint32_t read_der_message_length(unsigned char* input, unsigned sz);
 /* Function to set verified boot hash in keymaster */
 int set_verified_boot_hash (const char *vbh, size_t vbh_size);
+/* Function to check date support in keymaster */
+int get_date_support (bool *supported);
+
 #endif
diff --git a/platform/msm_shared/include/regulator.h b/platform/msm_shared/include/regulator.h
index 9759354..fa68fff 100644
--- a/platform/msm_shared/include/regulator.h
+++ b/platform/msm_shared/include/regulator.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017,2019 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 are
@@ -71,7 +71,9 @@
 #define REG_LDO6	BIT(5)
 #define REG_LDO11	BIT(10)
 #define REG_LDO12	BIT(11)
+#define REG_LDO13	BIT(12)
 #define REG_LDO14	BIT(13)
+#define REG_LDO15	BIT(14)
 #define REG_LDO17	BIT(16)
 #define REG_LDO18	BIT(17)
 #define REG_LDO28	BIT(27)
diff --git a/target/msm8952/init.c b/target/msm8952/init.c
index f0bd911..7513e9e 100644
--- a/target/msm8952/init.c
+++ b/target/msm8952/init.c
@@ -110,6 +110,15 @@
 static uint32_t  mmc_sdc_pwrctl_irq[] =
 	{ SDCC1_PWRCTL_IRQ, SDCC2_PWRCTL_IRQ };
 
+static int sdm429_pm660_target()
+{
+	if (platform_is_sdm429() && (board_hardware_subtype()
+			== HW_PLATFORM_SUBTYPE_429W_PM660))
+		return 1;
+	else
+		return 0;
+}
+
 void target_early_init(void)
 {
 #if WITH_DEBUG_UART
@@ -332,7 +341,8 @@
 
 #if PON_VIB_SUPPORT
 	/* turn on vibrator to indicate that phone is booting up to end user */
-	if(target_is_pmi_enabled() || platform_is_qm215() || platform_is_sdm429w())
+	if(target_is_pmi_enabled() || platform_is_qm215()
+			|| platform_is_sdm429w() || sdm429_pm660_target())
 		vib_timed_turn_on(VIBRATE_TIME);
 #endif
 
@@ -509,7 +519,7 @@
 void target_uninit(void)
 {
 #if PON_VIB_SUPPORT
-	if(target_is_pmi_enabled() || platform_is_sdm429w())
+	if(target_is_pmi_enabled() || platform_is_sdm429w() || sdm429_pm660_target())
 		turn_off_vib_early();
 #endif
 	mmc_put_card_to_sleep(dev);
@@ -704,8 +714,9 @@
 
 bool target_is_pmi_enabled(void)
 {
-	if (platform_is_qm215() || (platform_is_sdm429w()) || (platform_is_msm8917()
-		&& (board_hardware_subtype() == HW_PLATFORM_SUBTYPE_SAP_NOPMI)))
+	if (platform_is_qm215() || platform_is_sdm429w() || sdm429_pm660_target() ||
+			(platform_is_msm8917() && (board_hardware_subtype() ==
+			HW_PLATFORM_SUBTYPE_SAP_NOPMI)))
 		return 0;
 	else
 		return 1;
@@ -760,7 +771,7 @@
 		else
 			return PMIC_IS_PMI8950;
 	} else {
-		if (platform_is_qm215() || platform_is_sdm429w()) {
+		if (platform_is_qm215() || platform_is_sdm429w() || sdm429_pm660_target()) {
 			pmi_type = board_pmic_target(0) & PMIC_TYPE_MASK;
 			return pmi_type;
 		}
diff --git a/target/msm8952/oem_panel.c b/target/msm8952/oem_panel.c
index 27f7eec..55619e7 100644
--- a/target/msm8952/oem_panel.c
+++ b/target/msm8952/oem_panel.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, 2018-2019 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
@@ -65,6 +65,7 @@
 #include "include/panel_lead_fl10802_fwvga_video.h"
 #include "include/panel_hx8399c_fhd_pluse_video.h"
 #include "include/panel_hx8399c_hd_plus_video.h"
+#include "include/panel_edo_rm67162_qvga_cmd.h"
 #include "include/panel_nt35695b_truly_fhd_video.h"
 #include "include/panel_nt35695b_truly_fhd_cmd.h"
 
@@ -94,6 +95,7 @@
 	HX8399C_HD_PLUS_VIDEO_PANEL,
 	NT35695B_TRULY_FHD_VIDEO_PANEL,
 	NT35695B_TRULY_FHD_CMD_PANEL,
+	RM67162_QVGA_CMD_PANEL,
 	UNKNOWN_PANEL
 };
 
@@ -128,6 +130,7 @@
 	{"hx8399c_hd_plus_video", HX8399C_HD_PLUS_VIDEO_PANEL},
 	{"nt35695b_truly_fhd_video", NT35695B_TRULY_FHD_VIDEO_PANEL},
 	{"nt35695b_truly_fhd_cmd", NT35695B_TRULY_FHD_CMD_PANEL},
+	{"rm67162_qvga_cmd", RM67162_QVGA_CMD_PANEL},
 };
 
 static uint32_t panel_id;
@@ -815,6 +818,37 @@
 		pinfo->mipi.signature    = HX8399C_HD_PLUS_VIDEO_SIGNATURE;
 		pinfo->mipi.tx_eot_append = true;
 		break;
+	case RM67162_QVGA_CMD_PANEL:
+		panelstruct->paneldata    = &edo_rm67162_qvga_cmd_panel_data;
+		panelstruct->panelres     = &edo_rm67162_qvga_cmd_panel_res;
+		panelstruct->color        = &edo_rm67162_qvga_cmd_color;
+		panelstruct->videopanel   =
+				&edo_rm67162_qvga_cmd_video_panel;
+		panelstruct->commandpanel =
+				&edo_rm67162_qvga_cmd_command_panel;
+		panelstruct->state        = &edo_rm67162_qvga_cmd_state;
+		panelstruct->laneconfig   =
+				&edo_rm67162_qvga_cmd_lane_config;
+		panelstruct->paneltiminginfo
+				= &edo_rm67162_qvga_cmd_timing_info;
+		panelstruct->panelresetseq
+				= &edo_rm67162_qvga_cmd_reset_seq;
+		panelstruct->backlightinfo = &edo_rm67162_qvga_cmd_backlight;
+		pinfo->labibb = NULL;
+		pinfo->mipi.panel_on_cmds
+				= edo_rm67162_qvga_cmd_on_command;
+		pinfo->mipi.num_of_panel_on_cmds
+				= EDO_RM67162_QVGA_CMD_ON_COMMAND;
+		pinfo->mipi.panel_off_cmds
+				= edo_rm67162_qvga_cmd_off_command;
+		pinfo->mipi.num_of_panel_off_cmds
+				= EDO_RM67162_QVGA_CMD_OFF_COMMAND;
+		if (phy_db->pll_type == DSI_PLL_TYPE_12NM)
+			memcpy(phy_db->timing,
+				edo_rm67162_qvga_cmd_12nm_timings,
+				TIMING_SIZE_12NM);
+		pinfo->mipi.tx_eot_append = true;
+		break;
 	case NT35695B_TRULY_FHD_VIDEO_PANEL:
 		panelstruct->paneldata    = &nt35695b_truly_fhd_video_panel_data;
 		panelstruct->panelres     = &nt35695b_truly_fhd_video_panel_res;
@@ -1008,7 +1042,10 @@
 		}
 
 		if (platform_is_sdm429()) {
-			panel_id = HX8399C_HD_PLUS_VIDEO_PANEL;
+			if (hw_subtype == HW_PLATFORM_SUBTYPE_429W_PM660) /* Spyro target */
+				panel_id = RM67162_QVGA_CMD_PANEL;
+			else
+				panel_id = HX8399C_HD_PLUS_VIDEO_PANEL;
 		}
 
 		/* QRD EVT1 uses OTM1906C, and EVT2 uses HX8394F */
diff --git a/target/msm8952/regulator.c b/target/msm8952/regulator.c
index ee08d30..ecb2ba3 100644
--- a/target/msm8952/regulator.c
+++ b/target/msm8952/regulator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2018-2019, 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 are
@@ -32,6 +32,7 @@
 #include <bits.h>
 #include <debug.h>
 #include <platform.h>
+#include <board.h>
 
 
 static uint32_t ldo1[][11]=
@@ -101,6 +102,56 @@
 	},
 };
 
+static uint32_t ldo6_pm660[][11]=
+{
+	{
+		LDOA_RES_TYPE, 6,
+		KEY_SOFTWARE_ENABLE, 4, GENERIC_DISABLE,
+		KEY_MICRO_VOLT, 4, 0,
+		KEY_CURRENT, 4, 0,
+	},
+
+	{
+		LDOA_RES_TYPE, 6,
+		KEY_SOFTWARE_ENABLE, 4, GENERIC_ENABLE,
+		KEY_MICRO_VOLT, 4, 800000,
+		KEY_CURRENT, 4, 150,
+	},
+};
+
+static uint32_t ldo13_pm660[][11]=
+{
+	{
+		LDOA_RES_TYPE, 13,
+		KEY_SOFTWARE_ENABLE, 4, GENERIC_DISABLE,
+		KEY_MICRO_VOLT, 4, 0,
+		KEY_CURRENT, 4, 0,
+	},
+
+	{
+		LDOA_RES_TYPE, 13,
+		KEY_SOFTWARE_ENABLE, 4, GENERIC_ENABLE,
+		KEY_MICRO_VOLT, 4, 1800000,
+		KEY_CURRENT, 4, 40,
+	},
+};
+
+static uint32_t ldo15_pm660[][11]=
+{
+	{
+		LDOA_RES_TYPE, 15,
+		KEY_SOFTWARE_ENABLE, 4, GENERIC_DISABLE,
+		KEY_MICRO_VOLT, 4, 0,
+		KEY_CURRENT, 4, 0,
+	},
+
+	{
+		LDOA_RES_TYPE, 15,
+		KEY_SOFTWARE_ENABLE, 4, GENERIC_ENABLE,
+		KEY_MICRO_VOLT, 4, 2800000,
+		KEY_CURRENT, 4, 40,
+	},
+};
 
 static uint32_t ldo17[][11]=
 {
@@ -121,6 +172,8 @@
 
 void regulator_enable(uint32_t enable)
 {
+	uint32_t hw_subtype = board_hardware_subtype();
+
 	if (platform_is_msm8956()) {
 		if (enable & REG_LDO1)
 			rpm_send_data(&ldo1[GENERIC_ENABLE][0], 36, RPM_REQUEST_TYPE);
@@ -134,11 +187,26 @@
 			rpm_send_data(&ldo2[GENERIC_ENABLE][0], 36, RPM_REQUEST_TYPE);
 	}
 
+	if (platform_is_sdm429() && hw_subtype
+			== HW_PLATFORM_SUBTYPE_429W_PM660) {
+		if (enable & REG_LDO13)
+			rpm_send_data(&ldo13_pm660[GENERIC_ENABLE][0],
+				36, RPM_REQUEST_TYPE);
+		if (enable & REG_LDO15)
+			rpm_send_data(&ldo15_pm660[GENERIC_ENABLE][0],
+				36, RPM_REQUEST_TYPE);
+	}
+
 	if (enable & REG_LDO17)
 		rpm_send_data(&ldo17[GENERIC_ENABLE][0], 36, RPM_REQUEST_TYPE);
 
-	if (enable & REG_LDO6)
-		rpm_send_data(&ldo6[GENERIC_ENABLE][0], 36, RPM_REQUEST_TYPE);
+	if (enable & REG_LDO6) {
+		if (platform_is_sdm429() && hw_subtype
+				== HW_PLATFORM_SUBTYPE_429W_PM660)
+			rpm_send_data(&ldo6_pm660[GENERIC_ENABLE][0], 36, RPM_REQUEST_TYPE);
+		else
+			rpm_send_data(&ldo6[GENERIC_ENABLE][0], 36, RPM_REQUEST_TYPE);
+	}
 }
 
 void regulator_disable(uint32_t enable)
diff --git a/target/msm8952/target_display.c b/target/msm8952/target_display.c
index 38cf975..7d74abe 100644
--- a/target/msm8952/target_display.c
+++ b/target/msm8952/target_display.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, 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
@@ -452,6 +452,12 @@
 		pinfo->mipi.use_enable_gpio = 1;
 	} else if (platform_is_sdm439() || platform_is_sdm429()) {
 		reset_gpio.pin_id = 60;
+		if (platform_is_sdm429() && hw_subtype
+			== HW_PLATFORM_SUBTYPE_429W_PM660) {
+			reset_gpio.pin_id = 60;
+			pinfo->mipi.use_enable_gpio = 1;
+			enable_gpio.pin_id = 69;
+		}
 	} else if ((hw_id == HW_PLATFORM_QRD) &&
 		   (hw_subtype == HW_PLATFORM_SUBTYPE_POLARIS)) {
 		enable_gpio.pin_id = 19;
@@ -650,6 +656,7 @@
 	int rc = 0;
 	uint32_t ldo_num = REG_LDO6 | REG_LDO17;
 	uint32_t pmic_type = target_get_pmic();
+	uint32_t hw_subtype = board_hardware_subtype();
 
 	if (platform_is_msm8956())
 		ldo_num |= REG_LDO1;
@@ -658,6 +665,10 @@
 	else
 		ldo_num |= REG_LDO2;
 
+	if (platform_is_sdm429() && hw_subtype
+		== HW_PLATFORM_SUBTYPE_429W_PM660)
+		ldo_num |= REG_LDO13 | REG_LDO15;
+
 	if (enable) {
 		regulator_enable(ldo_num);
 		mdelay(10);
@@ -683,6 +694,10 @@
 		 * Do not disable them.
 		 */
 		regulator_disable(REG_LDO17);
+
+		if (platform_is_sdm429() && hw_subtype
+			== HW_PLATFORM_SUBTYPE_429W_PM660)
+			regulator_disable(REG_LDO13 | REG_LDO15);
 	}
 
 	return NO_ERROR;