Merge changes Id9b8570c,I6c849673,I30a1d8b5,I9d35b1a3 into msm-3.0

* changes:
  added G723 and G729
  Fixes for 1. fixes for comments recieved on alsa-devel
  compress: add the core file
  compress: add API header and driver header files
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index dbf3427..2b7b749 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -40,17 +40,6 @@
 /* Address of GIC 0 CPU interface */
 void __iomem *gic_cpu_base_addr __read_mostly;
 
-struct gic_chip_data {
-	unsigned int irq_offset;
-	void __iomem *dist_base;
-	void __iomem *cpu_base;
-	unsigned int max_irq;
-#ifdef CONFIG_PM
-	unsigned int wakeup_irqs[32];
-	unsigned int enabled_irqs[32];
-#endif
-};
-
 /*
  * Supported arch specific GIC irq extension.
  * Default make them NULL.
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index a4964be..3e754fc 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -32,6 +32,7 @@
 CONFIG_ARCH_MSMCOPPER=y
 CONFIG_MSM_KRAIT_TBB_ABORT_HANDLER=y
 # CONFIG_MSM_STACKED_MEMORY is not set
+CONFIG_DEBUG_MSMCOPPER_UART=y
 CONFIG_CPU_HAS_L2_PMU=y
 # CONFIG_MSM_JTAG_V7 is not set
 # CONFIG_MSM_FIQ_SUPPORT is not set
@@ -141,6 +142,8 @@
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
 CONFIG_KEYS=y
 CONFIG_CRYPTO_AUTHENC=y
 CONFIG_CRYPTO_CBC=y
diff --git a/arch/arm/configs/msm7627_defconfig b/arch/arm/configs/msm7627_defconfig
index 7da4daf..4aabe08 100644
--- a/arch/arm/configs/msm7627_defconfig
+++ b/arch/arm/configs/msm7627_defconfig
@@ -288,13 +288,20 @@
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
+CONFIG_LOCKUP_DETECTOR=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_TIMER_STATS=y
+CONFIG_SLUB_DEBUG_ON=y
 CONFIG_DEBUG_MUTEXES=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_INFO=y
 CONFIG_LATENCYTOP=y
+CONFIG_DEBUG_LIST=y
+CONFIG_DEBUG_PAGEALLOC=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
 CONFIG_CRYPTO_SHA256=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index 5e0cd9f..dccefd8 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -25,6 +25,7 @@
 # CONFIG_SLUB_DEBUG is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -421,12 +422,10 @@
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
-# CONFIG_STACKTRACE is not set
 CONFIG_DEBUG_INFO=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index d63a018..141bfde 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -93,7 +93,7 @@
 CONFIG_MISC_DEVICES=y
 # CONFIG_ANDROID_PMEM is not set
 CONFIG_NETDEVICES=y
-CONFIG_HOSTAP=m
+CONFIG_HOSTAP=y
 # CONFIG_MSM_RMNET is not set
 CONFIG_MSM_RMNET_BAM=y
 # CONFIG_INPUT_MOUSEDEV is not set
@@ -132,11 +132,39 @@
 CONFIG_REGULATOR_GPIO=y
 # CONFIG_HID_SUPPORT is not set
 CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_CI13XXX_MSM=y
 CONFIG_USB_G_ANDROID=y
 CONFIG_RMNET_SMD_CTL_CHANNEL="DATA36_CNTL"
 CONFIG_RMNET_SMD_DATA_CHANNEL="DATA36"
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_UNSAFE_RESUME=y
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 27adea3..e90400b 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -43,6 +43,17 @@
 void gic_enable_ppi(unsigned int);
 bool gic_is_spi_pending(unsigned int irq);
 void gic_clear_spi_pending(unsigned int irq);
+
+struct gic_chip_data {
+	unsigned int irq_offset;
+	void __iomem *dist_base;
+	void __iomem *cpu_base;
+	unsigned int max_irq;
+#ifdef CONFIG_PM
+	unsigned int wakeup_irqs[32];
+	unsigned int enabled_irqs[32];
+#endif
+};
 #endif
 
 #endif
diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h
index 7ef3a30..7dac1d4 100644
--- a/arch/arm/include/asm/setup.h
+++ b/arch/arm/include/asm/setup.h
@@ -211,7 +211,8 @@
 	for (iter = 0; iter < (mi)->nr_banks; iter++)
 
 #define bank_pfn_start(bank)	__phys_to_pfn((bank)->start)
-#define bank_pfn_end(bank)	__phys_to_pfn((bank)->start + (bank)->size)
+#define bank_pfn_end(bank)	(__phys_to_pfn((bank)->start) + \
+						__phys_to_pfn((bank)->size))
 #define bank_pfn_size(bank)	((bank)->size >> PAGE_SHIFT)
 #define bank_phys_start(bank)	(bank)->start
 #define bank_phys_end(bank)	((bank)->start + (bank)->size)
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index e5f7449..fc27feb 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1626,6 +1626,14 @@
 	  allocate physical memory which is used by bus performance hardware to
 	  dump performance data.
 
+config MSM_TZ_LOG
+	tristate "MSM Trust Zone (TZ) Log Driver"
+	depends on DEBUG_FS
+	help
+	  This option enables a driver with a debugfs interface for messages
+	  produced by the Secure code (Trust zone). These messages provide
+	  diagnostic information about TZ operation.
+
 config MSM_RPM_LOG
 	tristate "MSM Resource Power Manager Log Driver"
 	depends on DEBUG_FS
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index e4f88ec..bccc05b 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -257,6 +257,7 @@
 obj-$(CONFIG_MSM_MPM) += mpm.o
 obj-$(CONFIG_MSM_RPM_STATS_LOG) += rpm_stats.o
 obj-$(CONFIG_MSM_RPM_LOG) += rpm_log.o
+obj-$(CONFIG_MSM_TZ_LOG) += tz_log.o
 obj-$(CONFIG_MSM_XO) += msm_xo.o
 obj-$(CONFIG_MSM_BUS_SCALING) += msm_bus/
 obj-$(CONFIG_MSM_BUSPM_DEV) += msm-buspm-dev.o
@@ -300,3 +301,5 @@
 obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30-regulator.o
 obj-$(CONFIG_ARCH_MSM7X27A) += board-msm7x27a-regulator.o
 endif
+
+obj-$(CONFIG_ARCH_MSM8960) += mdm2.o mdm_common.o
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 5e2d311..c70e1b5 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -292,6 +292,17 @@
 		queue_rx();
 		return;
 	}
+
+	if (rx_hdr->ch_id >= BAM_DMUX_NUM_CHANNELS) {
+		pr_err("%s: dropping invalid LCID %d reserved %d cmd %d"
+			" pad %d ch %d len %d\n", __func__,
+			rx_hdr->ch_id, rx_hdr->reserved, rx_hdr->cmd,
+			rx_hdr->pad_len, rx_hdr->ch_id, rx_hdr->pkt_len);
+		dev_kfree_skb_any(rx_skb);
+		queue_rx();
+		return;
+	}
+
 	switch (rx_hdr->cmd) {
 	case BAM_MUX_HDR_CMD_DATA:
 		DBG_INC_READ_CNT(rx_hdr->pkt_len);
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index eddd4ed..44b78d1 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -623,11 +623,63 @@
 	.src_clk_rate = 24000000,
 };
 
+#define USB_5V_EN		3
+#define PM_USB_5V_EN	PM8018_GPIO_PM_TO_SYS(USB_5V_EN)
+
+static void msm_hsusb_vbus_power(bool on)
+{
+	int rc;
+	static bool vbus_is_on;
+	struct pm_gpio usb_vbus = {
+			.direction      = PM_GPIO_DIR_OUT,
+			.pull           = PM_GPIO_PULL_NO,
+			.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
+			.output_value   = 0,
+			.vin_sel        = 2,
+			.out_strength   = PM_GPIO_STRENGTH_HIGH,
+			.function       = PM_GPIO_FUNC_NORMAL,
+			.inv_int_pol    = 0,
+	};
+
+	if (vbus_is_on == on)
+		return;
+
+	if (on) {
+		rc = pm8xxx_gpio_config(PM_USB_5V_EN, &usb_vbus);
+		if (rc) {
+			pr_err("failed to config usb_5v_en gpio\n");
+			return;
+		}
+
+		rc = gpio_request(PM_USB_5V_EN,
+						"usb_5v_en");
+		if (rc < 0) {
+			pr_err("failed to request usb_5v_en gpio\n");
+			return;
+		}
+
+		rc = gpio_direction_output(PM_USB_5V_EN, 1);
+		if (rc) {
+			pr_err("%s: unable to set_direction for gpio [%d]\n",
+				__func__, PM_USB_5V_EN);
+			goto free_usb_5v_en;
+		}
+
+		vbus_is_on = true;
+		return;
+	}
+	gpio_set_value(PM_USB_5V_EN, 0);
+free_usb_5v_en:
+	gpio_free(PM_USB_5V_EN);
+	vbus_is_on = false;
+}
+
 static struct msm_otg_platform_data msm_otg_pdata = {
-	.mode			= USB_PERIPHERAL,
-	.otg_control		= OTG_NO_CONTROL,
+	.mode			= USB_OTG,
+	.otg_control	= OTG_PHY_CONTROL,
 	.phy_type		= SNPS_28NM_INTEGRATED_PHY,
-	.pclk_src_name		= "dfab_usb_hs_clk",
+	.pclk_src_name	= "dfab_usb_hs_clk",
+	.vbus_power		= msm_hsusb_vbus_power,
 };
 
 static int usb_diag_update_pid_and_serial_num(uint32_t pid, const char *snum)
@@ -662,6 +714,7 @@
 	&msm_device_smd,
 	&msm_device_otg,
 	&msm_device_gadget_peripheral,
+	&msm_device_hsusb_host,
 	&android_usb_device,
 	&msm9615_device_uart_gsbi4,
 	&msm9615_device_ext_2p95v_vreg,
diff --git a/arch/arm/mach-msm/board-apq8064.c b/arch/arm/mach-msm/board-apq8064.c
index 6662751..00886c6 100644
--- a/arch/arm/mach-msm/board-apq8064.c
+++ b/arch/arm/mach-msm/board-apq8064.c
@@ -432,12 +432,14 @@
 {
 	if ((machine_is_apq8064_rumi3()) || machine_is_apq8064_sim()) {
 		if (apq8064_sdc1_pdata) {
-			apq8064_sdc1_pdata->disable_bam = true;
+			if (machine_is_apq8064_sim())
+				apq8064_sdc1_pdata->disable_bam = true;
 			apq8064_sdc1_pdata->disable_runtime_pm = true;
 			apq8064_sdc1_pdata->disable_cmd23 = true;
 		}
 		if (apq8064_sdc3_pdata) {
-			apq8064_sdc3_pdata->disable_bam = true;
+			if (machine_is_apq8064_sim())
+				apq8064_sdc3_pdata->disable_bam = true;
 			apq8064_sdc3_pdata->disable_runtime_pm = true;
 			apq8064_sdc3_pdata->disable_cmd23 = true;
 		}
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 1435774..aada890 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -1072,7 +1072,7 @@
 #define MSM_PMEM_MDP_SIZE       0x1900000
 #define MSM7x25A_MSM_PMEM_MDP_SIZE	0x1000000
 
-#define MSM_PMEM_ADSP_SIZE      0x1000000
+#define MSM_PMEM_ADSP_SIZE      0x2000000
 #define MSM7x25A_MSM_PMEM_ADSP_SIZE      0xB91000
 
 
diff --git a/arch/arm/mach-msm/board-msm7x30-regulator.c b/arch/arm/mach-msm/board-msm7x30-regulator.c
index 0ca7f16..5329bbe 100644
--- a/arch/arm/mach-msm/board-msm7x30-regulator.c
+++ b/arch/arm/mach-msm/board-msm7x30-regulator.c
@@ -274,7 +274,7 @@
 	 *             name  id  supp    min uV    max uV  R   P  A  B  V  S */
 	PCOM_VREG_SMP(smps0,  3, NULL,   500000,  1500000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_SMP(smps1,  4, NULL,   500000,  1500000, 0, -1, 0, 0, 0, 0),
-	PCOM_VREG_SMP(smps2, 28, NULL,  1225000,  1225000, 0, -1, 0, 0, 0, 0),
+	PCOM_VREG_SMP(smps2, 28, NULL,  1300000,  1300000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_SMP(smps3, 29, NULL,  1800000,  1800000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_SMP(smps4, 43, NULL,  2200000,  2200000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo00,  5, NULL,  1200000,  1200000, 0, -1, 0, 0, 0, 0),
@@ -282,7 +282,7 @@
 	PCOM_VREG_LDO(ldo03, 19, NULL,  1800000,  3000000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo04,  9, NULL,  2850000,  2850000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo05, 18, NULL,  2850000,  2850000, 0, -1, 0, 0, 0, 0),
-	PCOM_VREG_LDO(ldo06, 16, NULL,  3075000,  3075000, 0, -1, 0, 0, 0, 0),
+	PCOM_VREG_LDO(ldo06, 16, NULL,  3075000,  3400000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo07, 44, NULL,  1800000,  1800000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo08, 32, NULL,  1800000,  1800000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo09,  8, NULL,  2050000,  2050000, 0, -1, 0, 0, 0, 0),
@@ -291,16 +291,16 @@
 	PCOM_VREG_LDO(ldo12, 34, NULL,  1800000,  1800000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo13, 15, NULL,  2900000,  2900000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo14, 24, NULL,  2850000,  2850000, 0, -1, 0, 0, 0, 0),
-	PCOM_VREG_LDO(ldo15, 23, NULL,  3100000,  3100000, 0, -1, 0, 0, 0, 0),
+	PCOM_VREG_LDO(ldo15, 23, NULL,  3050000,  3100000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo16, 35, NULL,  2600000,  2600000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo17, 36, NULL,  2600000,  2600000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo18, 37, NULL,  2200000,  2200000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo19, 45, NULL,  2500000,  2500000, 0, -1, 0, 0, 0, 0),
-	PCOM_VREG_LDO(ldo20, 38, NULL,  1500000,  1500000, 0, -1, 0, 0, 0, 0),
+	PCOM_VREG_LDO(ldo20, 38, NULL,  1500000,  1800000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo21, 39, NULL,  1100000,  1100000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo22, 40, NULL,  1300000,  1300000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo23, 22, NULL,  1350000,  1350000, 0, -1, 0, 0, 0, 0),
-	PCOM_VREG_LDO(ldo24, 41, NULL,  1225000,  1225000, 0, -1, 0, 0, 0, 0),
+	PCOM_VREG_LDO(ldo24, 41, NULL,  1200000,  1200000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo25, 42, NULL,  1200000,  1200000, 0, -1, 0, 0, 0, 0),
 
 	/* Low-voltage switches */
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index eda29cd..d73f612 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -37,6 +37,7 @@
 #include <linux/input/cy8c_ts.h>
 #include <linux/msm_adc.h>
 #include <linux/dma-mapping.h>
+#include <linux/regulator/consumer.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -331,56 +332,43 @@
 };
 
 static struct kobject *properties_kobj;
+static struct regulator_bulk_data cyttsp_regs[] = {
+	{ .supply = "ldo8",  .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "ldo15", .min_uV = 3050000, .max_uV = 3100000 },
+};
 
 #define CYTTSP_TS_GPIO_IRQ	150
 static int cyttsp_platform_init(struct i2c_client *client)
 {
 	int rc = -EINVAL;
-	struct vreg *vreg_ldo8, *vreg_ldo15;
 
-	vreg_ldo8 = vreg_get(NULL, "gp7");
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(cyttsp_regs), cyttsp_regs);
 
-	if (!vreg_ldo8) {
-		pr_err("%s: VREG L8 get failed\n", __func__);
-		return rc;
-	}
-
-	rc = vreg_set_level(vreg_ldo8, 1800);
 	if (rc) {
-		pr_err("%s: VREG L8 set failed\n", __func__);
-		goto l8_put;
+		pr_err("%s: could not get regulators: %d\n", __func__, rc);
+		goto out;
 	}
 
-	rc = vreg_enable(vreg_ldo8);
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(cyttsp_regs), cyttsp_regs);
+
 	if (rc) {
-		pr_err("%s: VREG L8 enable failed\n", __func__);
-		goto l8_put;
+		pr_err("%s: could not set regulator voltages: %d\n", __func__,
+				rc);
+		goto regs_free;
 	}
 
-	vreg_ldo15 = vreg_get(NULL, "gp6");
+	rc = regulator_bulk_enable(ARRAY_SIZE(cyttsp_regs), cyttsp_regs);
 
-	if (!vreg_ldo15) {
-		pr_err("%s: VREG L15 get failed\n", __func__);
-		goto l8_disable;
-	}
-
-	rc = vreg_set_level(vreg_ldo15, 3050);
 	if (rc) {
-		pr_err("%s: VREG L15 set failed\n", __func__);
-		goto l8_disable;
-	}
-
-	rc = vreg_enable(vreg_ldo15);
-	if (rc) {
-		pr_err("%s: VREG L15 enable failed\n", __func__);
-		goto l8_disable;
+		pr_err("%s: could not enable regulators: %d\n", __func__, rc);
+		goto regs_free;
 	}
 
 	/* check this device active by reading first byte/register */
 	rc = i2c_smbus_read_byte_data(client, 0x01);
 	if (rc < 0) {
 		pr_err("%s: i2c sanity check failed\n", __func__);
-		goto l8_disable;
+		goto regs_disable;
 	}
 
 	rc = gpio_tlmm_config(GPIO_CFG(CYTTSP_TS_GPIO_IRQ, 0, GPIO_CFG_INPUT,
@@ -388,7 +376,7 @@
 	if (rc) {
 		pr_err("%s: Could not configure gpio %d\n",
 					 __func__, CYTTSP_TS_GPIO_IRQ);
-		goto l8_disable;
+		goto regs_disable;
 	}
 
 	/* virtual keys */
@@ -404,10 +392,11 @@
 
 	return CY_OK;
 
-l8_disable:
-	vreg_disable(vreg_ldo8);
-l8_put:
-	vreg_put(vreg_ldo8);
+regs_disable:
+	regulator_bulk_disable(ARRAY_SIZE(cyttsp_regs), cyttsp_regs);
+regs_free:
+	regulator_bulk_free(ARRAY_SIZE(cyttsp_regs), cyttsp_regs);
+out:
 	return rc;
 }
 
@@ -1371,58 +1360,54 @@
 	pr_info("%s: power off amplifier\n", __func__);
 }
 
-static struct vreg *snddev_vreg_ncp, *snddev_vreg_gp4;
+static struct regulator_bulk_data snddev_regs[] = {
+	{ .supply = "gp4", .min_uV = 2600000, .max_uV = 2600000 },
+	{ .supply = "ncp", .min_uV = 1800000, .max_uV = 1800000 },
+};
 
-void msm_snddev_hsed_voltage_on(void)
+static int __init snddev_hsed_voltage_init(void)
 {
 	int rc;
 
-	snddev_vreg_gp4 = vreg_get(NULL, "gp4");
-	if (IS_ERR(snddev_vreg_gp4)) {
-		pr_err("%s: vreg_get(%s) failed (%ld)\n",
-		__func__, "gp4", PTR_ERR(snddev_vreg_gp4));
-		return;
-	}
-	rc = vreg_enable(snddev_vreg_gp4);
-	if (rc)
-		pr_err("%s: vreg_enable(gp4) failed (%d)\n", __func__, rc);
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(snddev_regs), snddev_regs);
 
-	snddev_vreg_ncp = vreg_get(NULL, "ncp");
-	if (IS_ERR(snddev_vreg_ncp)) {
-		pr_err("%s: vreg_get(%s) failed (%ld)\n",
-		__func__, "ncp", PTR_ERR(snddev_vreg_ncp));
-		return;
+	if (rc) {
+		pr_err("%s: could not get regulators: %d\n", __func__, rc);
+		goto out;
 	}
-	rc = vreg_enable(snddev_vreg_ncp);
+
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(snddev_regs), snddev_regs);
+
+	if (rc) {
+		pr_err("%s: could not set regulator voltages: %d\n",
+				__func__, rc);
+		goto regs_free;
+	}
+
+	return 0;
+
+regs_free:
+	regulator_bulk_free(ARRAY_SIZE(snddev_regs), snddev_regs);
+out:
+	return rc;
+}
+
+
+void msm_snddev_hsed_voltage_on(void)
+{
+	int rc = regulator_bulk_enable(ARRAY_SIZE(snddev_regs), snddev_regs);
+
 	if (rc)
-		pr_err("%s: vreg_enable(ncp) failed (%d)\n", __func__, rc);
+		pr_err("%s: could not enable regulators: %d\n", __func__, rc);
 }
 
 void msm_snddev_hsed_voltage_off(void)
 {
-	int rc;
+	int rc = regulator_bulk_disable(ARRAY_SIZE(snddev_regs), snddev_regs);
 
-	if (IS_ERR(snddev_vreg_ncp)) {
-		pr_err("%s: vreg_get(%s) failed (%ld)\n",
-		__func__, "ncp", PTR_ERR(snddev_vreg_ncp));
-		return;
+	if (rc) {
+		pr_err("%s: could not disable regulators: %d\n", __func__, rc);
 	}
-	rc = vreg_disable(snddev_vreg_ncp);
-	if (rc)
-		pr_err("%s: vreg_disable(ncp) failed (%d)\n", __func__, rc);
-	vreg_put(snddev_vreg_ncp);
-
-	if (IS_ERR(snddev_vreg_gp4)) {
-		pr_err("%s: vreg_get(%s) failed (%ld)\n",
-		__func__, "gp4", PTR_ERR(snddev_vreg_gp4));
-		return;
-	}
-	rc = vreg_disable(snddev_vreg_gp4);
-	if (rc)
-		pr_err("%s: vreg_disable(gp4) failed (%d)\n", __func__, rc);
-
-	vreg_put(snddev_vreg_gp4);
-
 }
 
 static unsigned aux_pcm_gpio_on[] = {
@@ -1605,10 +1590,9 @@
 	VER_UNSUPPORTED = 0xFF
 };
 
-
-static struct vreg *vreg_marimba_1;
-static struct vreg *vreg_marimba_2;
-static struct vreg *vreg_marimba_3;
+static struct regulator *vreg_marimba_1;
+static struct regulator *vreg_marimba_2;
+static struct regulator *vreg_bahama;
 
 static struct msm_gpio timpani_reset_gpio_cfg[] = {
 { GPIO_CFG(TIMPANI_RESET_GPIO, 0, GPIO_CFG_OUTPUT,
@@ -1666,34 +1650,33 @@
 	if (rc < 0)
 		goto out;
 
-	rc = vreg_enable(vreg_marimba_1);
+	rc = regulator_enable(vreg_marimba_1);
 	if (rc) {
-		printk(KERN_ERR "%s: vreg_enable() = %d\n",
-					__func__, rc);
+		pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
 		goto out;
 	}
-	rc = vreg_enable(vreg_marimba_2);
+
+	rc = regulator_enable(vreg_marimba_2);
 	if (rc) {
-		printk(KERN_ERR "%s: vreg_enable() = %d\n",
-					__func__, rc);
-		goto fail_disable_vreg_marimba_1;
+		pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
+		goto disable_marimba_1;
 	}
 
 	rc = gpio_direction_output(TIMPANI_RESET_GPIO, 1);
 	if (rc < 0) {
-		printk(KERN_ERR
-			"%s: gpio_direction_output failed (%d)\n",
+		pr_err("%s: gpio_direction_output failed (%d)\n",
 				__func__, rc);
 		msm_gpios_free(timpani_reset_gpio_cfg,
 				ARRAY_SIZE(timpani_reset_gpio_cfg));
-		vreg_disable(vreg_marimba_2);
-	} else
-		goto out;
+		goto disable_marimba_2;
+	}
 
+	return 0;
 
-fail_disable_vreg_marimba_1:
-	vreg_disable(vreg_marimba_1);
-
+disable_marimba_2:
+	regulator_disable(vreg_marimba_2);
+disable_marimba_1:
+	regulator_disable(vreg_marimba_1);
 out:
 	return rc;
 };
@@ -1702,23 +1685,18 @@
 {
 	int rc;
 
-	rc = vreg_disable(vreg_marimba_1);
-	if (rc) {
-		printk(KERN_ERR "%s: return val: %d\n",
-					__func__, rc);
-	}
-	rc = vreg_disable(vreg_marimba_2);
-	if (rc) {
-		printk(KERN_ERR "%s: return val: %d\n",
-					__func__, rc);
-	}
+	rc = regulator_disable(vreg_marimba_2);
+	if (rc)
+		pr_err("%s: regulator_disable failed (%d)\n", __func__, rc);
+
+	rc = regulator_disable(vreg_marimba_1);
+	if (rc)
+		pr_err("%s: regulator_disable failed (%d)\n", __func__, rc);
 
 	rc = gpio_direction_output(TIMPANI_RESET_GPIO, 0);
-	if (rc < 0) {
-		printk(KERN_ERR
-			"%s: gpio_direction_output failed (%d)\n",
+	if (rc < 0)
+		pr_err("%s: gpio_direction_output failed (%d)\n",
 				__func__, rc);
-	}
 
 	msm_gpios_free(timpani_reset_gpio_cfg,
 				   ARRAY_SIZE(timpani_reset_gpio_cfg));
@@ -1767,13 +1745,10 @@
 
 static unsigned int msm_bahama_setup_power(void)
 {
-	int rc;
+	int rc = regulator_enable(vreg_bahama);
 
-	rc = vreg_enable(vreg_marimba_3);
-	if (rc) {
-		printk(KERN_ERR "%s: vreg_enable() = %d\n",
-				__func__, rc);
-	}
+	if (rc)
+		pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
 
 	return rc;
 };
@@ -1783,11 +1758,11 @@
 	int rc = 0;
 
 	if (value != BAHAMA_ID) {
-		rc = vreg_disable(vreg_marimba_3);
-		if (rc) {
-			printk(KERN_ERR "%s: return val: %d\n",
+		rc = regulator_disable(vreg_bahama);
+
+		if (rc)
+			pr_err("%s: regulator_disable failed (%d)\n",
 					__func__, rc);
-		}
 	}
 
 	return rc;
@@ -1817,39 +1792,42 @@
 {
 	int rc;
 
-	rc = vreg_enable(vreg_marimba_1);
+	rc = regulator_enable(vreg_marimba_1);
 	if (rc) {
-		printk(KERN_ERR "%s: vreg_enable() = %d \n",
-					__func__, rc);
+		pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
 		goto out;
 	}
-	rc = vreg_enable(vreg_marimba_2);
+
+	rc = regulator_enable(vreg_marimba_2);
 	if (rc) {
-		printk(KERN_ERR "%s: vreg_enable() = %d \n",
-					__func__, rc);
-		goto out;
+		pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
+		goto disable_marimba_1;
 	}
 
 	if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa()) {
 		rc = msm_gpios_request_enable(marimba_svlte_config_clock,
 				ARRAY_SIZE(marimba_svlte_config_clock));
 		if (rc < 0) {
-			printk(KERN_ERR
-				"%s: msm_gpios_request_enable failed (%d)\n",
+			pr_err("%s: msm_gpios_request_enable failed (%d)\n",
 					__func__, rc);
-			return rc;
+			goto disable_marimba_2;
 		}
 
 		rc = gpio_direction_output(GPIO_PIN
 			(marimba_svlte_config_clock->gpio_cfg), 0);
 		if (rc < 0) {
-			printk(KERN_ERR
-				"%s: gpio_direction_output failed (%d)\n",
+			pr_err("%s: gpio_direction_output failed (%d)\n",
 					__func__, rc);
-			return rc;
+			goto disable_marimba_2;
 		}
 	}
 
+	return 0;
+
+disable_marimba_2:
+	regulator_disable(vreg_marimba_2);
+disable_marimba_1:
+	regulator_disable(vreg_marimba_1);
 out:
 	return rc;
 };
@@ -1858,16 +1836,13 @@
 {
 	int rc;
 
-	rc = vreg_disable(vreg_marimba_1);
-	if (rc) {
-		printk(KERN_ERR "%s: return val: %d\n",
-					__func__, rc);
-	}
-	rc = vreg_disable(vreg_marimba_2);
-	if (rc) {
-		printk(KERN_ERR "%s: return val: %d \n",
-					__func__, rc);
-	}
+	rc = regulator_disable(vreg_marimba_2);
+	if (rc)
+		pr_err("%s: regulator_disable failed (%d)\n", __func__, rc);
+
+	rc = regulator_disable(vreg_marimba_1);
+	if (rc)
+		pr_err("%s: regulator_disable failed (%d)\n", __func__, rc);
 };
 
 static int bahama_present(void)
@@ -1888,81 +1863,89 @@
 	}
 }
 
-struct vreg *fm_regulator;
+struct regulator *fm_regulator;
 static int fm_radio_setup(struct marimba_fm_platform_data *pdata)
 {
-	int rc;
+	int rc, voltage;
 	uint32_t irqcfg;
 	const char *id = "FMPW";
 
 	int bahama_not_marimba = bahama_present();
 
-	if (bahama_not_marimba == -1) {
-		printk(KERN_WARNING "%s: bahama_present: %d\n",
+	if (bahama_not_marimba < 0) {
+		pr_warn("%s: bahama_present: %d\n",
 				__func__, bahama_not_marimba);
-		return -ENODEV;
+		rc = -ENODEV;
+		goto out;
 	}
-	if (bahama_not_marimba)
-		fm_regulator = vreg_get(NULL, "s3");
-	else
-		fm_regulator = vreg_get(NULL, "s2");
+	if (bahama_not_marimba) {
+		fm_regulator = regulator_get(NULL, "s3");
+		voltage = 1800000;
+	} else {
+		fm_regulator = regulator_get(NULL, "s2");
+		voltage = 1300000;
+	}
 
 	if (IS_ERR(fm_regulator)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
-			__func__, PTR_ERR(fm_regulator));
-		return -1;
+		rc = PTR_ERR(fm_regulator);
+		pr_err("%s: regulator_get failed (%d)\n", __func__, rc);
+		goto out;
 	}
-	if (!bahama_not_marimba) {
 
-		rc = pmapp_vreg_level_vote(id, PMAPP_VREG_S2, 1300);
+	rc = regulator_set_voltage(fm_regulator, voltage, voltage);
 
-		if (rc < 0) {
-			printk(KERN_ERR "%s: voltage level vote failed (%d)\n",
-				__func__, rc);
-			return rc;
-		}
-	}
-	rc = vreg_enable(fm_regulator);
 	if (rc) {
-		printk(KERN_ERR "%s: vreg_enable() = %d\n",
-					__func__, rc);
-		return rc;
+		pr_err("%s: regulator_set_voltage failed (%d)\n", __func__, rc);
+		goto regulator_free;
 	}
 
-	rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO,
-					  PMAPP_CLOCK_VOTE_ON);
-	if (rc < 0) {
-		printk(KERN_ERR "%s: clock vote failed (%d)\n",
-			__func__, rc);
-		goto fm_clock_vote_fail;
+	rc = regulator_enable(fm_regulator);
+
+	if (rc) {
+		pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
+		goto regulator_free;
 	}
+
+	rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO, PMAPP_CLOCK_VOTE_ON);
+
+	if (rc < 0) {
+		pr_err("%s: clock vote failed (%d)\n", __func__, rc);
+		goto regulator_disable;
+	}
+
 	/*Request the Clock Using GPIO34/AP2MDM_MRMBCK_EN in case
 	of svlte*/
-	if (machine_is_msm8x55_svlte_surf() ||
-			machine_is_msm8x55_svlte_ffa())	{
+	if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa()) {
 		rc = marimba_gpio_config(1);
-		if (rc < 0)
-			printk(KERN_ERR "%s: clock enable for svlte : %d\n",
-						__func__, rc);
+		if (rc < 0) {
+			pr_err("%s: clock enable for svlte : %d\n",
+					__func__, rc);
+			goto clock_devote;
+		}
 	}
 	irqcfg = GPIO_CFG(147, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL,
 					GPIO_CFG_2MA);
 	rc = gpio_tlmm_config(irqcfg, GPIO_CFG_ENABLE);
 	if (rc) {
-		printk(KERN_ERR "%s: gpio_tlmm_config(%#x)=%d\n",
-				__func__, irqcfg, rc);
+		pr_err("%s: gpio_tlmm_config(%#x)=%d\n", __func__, irqcfg, rc);
 		rc = -EIO;
-		goto fm_gpio_config_fail;
+		goto gpio_deconfig;
 
 	}
 	return 0;
-fm_gpio_config_fail:
-	pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO,
-				  PMAPP_CLOCK_VOTE_OFF);
-fm_clock_vote_fail:
-	vreg_disable(fm_regulator);
-	return rc;
 
+gpio_deconfig:
+	if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa())
+		marimba_gpio_config(0);
+clock_devote:
+	pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO, PMAPP_CLOCK_VOTE_OFF);
+regulator_disable:
+	regulator_disable(fm_regulator);
+regulator_free:
+	regulator_put(fm_regulator);
+	fm_regulator = NULL;
+out:
+	return rc;
 };
 
 static void fm_radio_shutdown(struct marimba_fm_platform_data *pdata)
@@ -1974,48 +1957,36 @@
 
 	int bahama_not_marimba = bahama_present();
 	if (bahama_not_marimba == -1) {
-		printk(KERN_WARNING "%s: bahama_present: %d\n",
-			__func__, bahama_not_marimba);
+		pr_warn("%s: bahama_present: %d\n",
+				__func__, bahama_not_marimba);
 		return;
 	}
 
 	rc = gpio_tlmm_config(irqcfg, GPIO_CFG_ENABLE);
 	if (rc) {
-		printk(KERN_ERR "%s: gpio_tlmm_config(%#x)=%d\n",
-				__func__, irqcfg, rc);
+		pr_err("%s: gpio_tlmm_config(%#x)=%d\n", __func__, irqcfg, rc);
 	}
-	if (fm_regulator != NULL) {
-		rc = vreg_disable(fm_regulator);
+	if (!IS_ERR_OR_NULL(fm_regulator)) {
+		rc = regulator_disable(fm_regulator);
 
-		if (rc) {
-			printk(KERN_ERR "%s: return val: %d\n",
-					__func__, rc);
-		}
+		if (rc)
+			pr_err("%s: return val: %d\n", __func__, rc);
+
+		regulator_put(fm_regulator);
 		fm_regulator = NULL;
 	}
 	rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO,
 					  PMAPP_CLOCK_VOTE_OFF);
 	if (rc < 0)
-		printk(KERN_ERR "%s: clock_vote return val: %d\n",
-						__func__, rc);
+		pr_err("%s: clock_vote return val: %d\n", __func__, rc);
 
 	/*Disable the Clock Using GPIO34/AP2MDM_MRMBCK_EN in case
 	of svlte*/
-	if (machine_is_msm8x55_svlte_surf() ||
-			machine_is_msm8x55_svlte_ffa())	{
+	if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa()) {
 		rc = marimba_gpio_config(0);
 		if (rc < 0)
-			printk(KERN_ERR "%s: clock disable for svlte : %d\n",
-						__func__, rc);
-	}
-
-
-	if (!bahama_not_marimba)	{
-		rc = pmapp_vreg_level_vote(id, PMAPP_VREG_S2, 0);
-
-		if (rc < 0)
-			printk(KERN_ERR "%s: vreg level vote return val: %d\n",
-						__func__, rc);
+			pr_err("%s: clock disable for svlte : %d\n",
+					__func__, rc);
 	}
 }
 
@@ -2042,82 +2013,60 @@
 #define BAHAMA_SLAVE_ID_QMEMBIST_ADDR   0x7B
 
 static const char *tsadc_id = "MADC";
-static const char *vregs_tsadc_name[] = {
-	"gp12",
-	"s2",
-};
-static struct vreg *vregs_tsadc[ARRAY_SIZE(vregs_tsadc_name)];
 
-static const char *vregs_timpani_tsadc_name[] = {
-	"s3",
-	"gp12",
-	"gp16"
+static struct regulator_bulk_data regs_tsadc_marimba[] = {
+	{ .supply = "gp12", .min_uV = 2200000, .max_uV = 2200000 },
+	{ .supply = "s2",   .min_uV = 1300000, .max_uV = 1300000 },
 };
-static struct vreg *vregs_timpani_tsadc[ARRAY_SIZE(vregs_timpani_tsadc_name)];
+
+static struct regulator_bulk_data regs_tsadc_timpani[] = {
+	{ .supply = "s3",   .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "gp12", .min_uV = 2200000, .max_uV = 2200000 },
+	{ .supply = "gp16", .min_uV = 1200000, .max_uV = 1200000 },
+};
+
+static struct regulator_bulk_data *regs_tsadc;
+static int regs_tsadc_count;
 
 static int marimba_tsadc_power(int vreg_on)
 {
-	int i, rc = 0;
+	int rc = 0;
 	int tsadc_adie_type = adie_get_detected_codec_type();
 
-	if (tsadc_adie_type == TIMPANI_ID) {
-		for (i = 0; i < ARRAY_SIZE(vregs_timpani_tsadc_name); i++) {
-			if (!vregs_timpani_tsadc[i]) {
-				pr_err("%s: vreg_get %s failed(%d)\n",
-				__func__, vregs_timpani_tsadc_name[i], rc);
-				goto vreg_fail;
-			}
-
-			rc = vreg_on ? vreg_enable(vregs_timpani_tsadc[i]) :
-				  vreg_disable(vregs_timpani_tsadc[i]);
-			if (rc < 0) {
-				pr_err("%s: vreg %s %s failed(%d)\n",
-					__func__, vregs_timpani_tsadc_name[i],
-				       vreg_on ? "enable" : "disable", rc);
-				goto vreg_fail;
-			}
-		}
-		/* Vote for D0 and D1 buffer */
+	switch (tsadc_adie_type) {
+	case TIMPANI_ID:
 		rc = pmapp_clock_vote(tsadc_id, PMAPP_CLOCK_ID_D1,
 			vreg_on ? PMAPP_CLOCK_VOTE_ON : PMAPP_CLOCK_VOTE_OFF);
 		if (rc)	{
 			pr_err("%s: unable to %svote for d1 clk\n",
 				__func__, vreg_on ? "" : "de-");
-			goto do_vote_fail;
+			goto D1_vote_fail;
 		}
+
+		/* fall through */
+	case MARIMBA_ID:
 		rc = pmapp_clock_vote(tsadc_id, PMAPP_CLOCK_ID_DO,
 			vreg_on ? PMAPP_CLOCK_VOTE_ON : PMAPP_CLOCK_VOTE_OFF);
 		if (rc)	{
 			pr_err("%s: unable to %svote for d1 clk\n",
 				__func__, vreg_on ? "" : "de-");
-			goto do_vote_fail;
+			goto D0_vote_fail;
 		}
-	} else if (tsadc_adie_type == MARIMBA_ID) {
-		for (i = 0; i < ARRAY_SIZE(vregs_tsadc_name); i++) {
-			if (!vregs_tsadc[i]) {
-				pr_err("%s: vreg_get %s failed (%d)\n",
-					__func__, vregs_tsadc_name[i], rc);
-				goto vreg_fail;
-			}
 
-			rc = vreg_on ? vreg_enable(vregs_tsadc[i]) :
-				  vreg_disable(vregs_tsadc[i]);
-			if (rc < 0) {
-				pr_err("%s: vreg %s %s failed (%d)\n",
-					__func__, vregs_tsadc_name[i],
-				       vreg_on ? "enable" : "disable", rc);
-				goto vreg_fail;
-			}
+		WARN_ON(regs_tsadc_count == 0);
+
+		rc = vreg_on ?
+			regulator_bulk_enable(regs_tsadc_count, regs_tsadc) :
+			regulator_bulk_disable(regs_tsadc_count, regs_tsadc);
+
+		if (rc) {
+			pr_err("%s: regulator %sable failed: %d\n",
+					__func__, vreg_on ? "en" : "dis", rc);
+			goto regulator_switch_fail;
 		}
-		/* If marimba vote for DO buffer */
-		rc = pmapp_clock_vote(tsadc_id, PMAPP_CLOCK_ID_DO,
-			vreg_on ? PMAPP_CLOCK_VOTE_ON : PMAPP_CLOCK_VOTE_OFF);
-		if (rc)	{
-			pr_err("%s: unable to %svote for d0 clk\n",
-				__func__, vreg_on ? "" : "de-");
-			goto do_vote_fail;
-		}
-	} else {
+
+		break;
+	default:
 		pr_err("%s:Adie %d not supported\n",
 				__func__, tsadc_adie_type);
 		return -ENODEV;
@@ -2127,112 +2076,69 @@
 
 	return 0;
 
-do_vote_fail:
-vreg_fail:
-	while (i) {
-		if (vreg_on) {
-			if (tsadc_adie_type == TIMPANI_ID)
-				vreg_disable(vregs_timpani_tsadc[--i]);
-			else if (tsadc_adie_type == MARIMBA_ID)
-				vreg_disable(vregs_tsadc[--i]);
-		} else {
-			if (tsadc_adie_type == TIMPANI_ID)
-				vreg_enable(vregs_timpani_tsadc[--i]);
-			else if (tsadc_adie_type == MARIMBA_ID)
-				vreg_enable(vregs_tsadc[--i]);
-		}
-	}
-
-	return rc;
-}
-
-static int marimba_tsadc_vote(int vote_on)
-{
-	int rc = 0;
-
-	if (adie_get_detected_codec_type() == MARIMBA_ID) {
-		int level = vote_on ? 1300 : 0;
-		rc = pmapp_vreg_level_vote(tsadc_id, PMAPP_VREG_S2, level);
-		if (rc < 0)
-			pr_err("%s: vreg level %s failed (%d)\n",
-			__func__, vote_on ? "on" : "off", rc);
-	}
-
+regulator_switch_fail:
+	pmapp_clock_vote(tsadc_id, PMAPP_CLOCK_ID_DO,
+		vreg_on ? PMAPP_CLOCK_VOTE_OFF : PMAPP_CLOCK_VOTE_ON);
+D0_vote_fail:
+	if (tsadc_adie_type == TIMPANI_ID)
+		pmapp_clock_vote(tsadc_id, PMAPP_CLOCK_ID_D1,
+			vreg_on ? PMAPP_CLOCK_VOTE_OFF : PMAPP_CLOCK_VOTE_ON);
+D1_vote_fail:
 	return rc;
 }
 
 static int marimba_tsadc_init(void)
 {
-	int i, rc = 0;
+	int rc = 0;
 	int tsadc_adie_type = adie_get_detected_codec_type();
 
-	if (tsadc_adie_type == TIMPANI_ID) {
-		for (i = 0; i < ARRAY_SIZE(vregs_timpani_tsadc_name); i++) {
-			vregs_timpani_tsadc[i] = vreg_get(NULL,
-						vregs_timpani_tsadc_name[i]);
-			if (IS_ERR(vregs_timpani_tsadc[i])) {
-				pr_err("%s: vreg get %s failed (%ld)\n",
-				       __func__, vregs_timpani_tsadc_name[i],
-				       PTR_ERR(vregs_timpani_tsadc[i]));
-				rc = PTR_ERR(vregs_timpani_tsadc[i]);
-				goto vreg_get_fail;
-			}
-		}
-	} else if (tsadc_adie_type == MARIMBA_ID) {
-		for (i = 0; i < ARRAY_SIZE(vregs_tsadc_name); i++) {
-			vregs_tsadc[i] = vreg_get(NULL, vregs_tsadc_name[i]);
-			if (IS_ERR(vregs_tsadc[i])) {
-				pr_err("%s: vreg get %s failed (%ld)\n",
-				       __func__, vregs_tsadc_name[i],
-				       PTR_ERR(vregs_tsadc[i]));
-				rc = PTR_ERR(vregs_tsadc[i]);
-				goto vreg_get_fail;
-			}
-		}
-	} else {
+	switch (tsadc_adie_type) {
+	case MARIMBA_ID:
+		regs_tsadc = regs_tsadc_marimba;
+		regs_tsadc_count = ARRAY_SIZE(regs_tsadc_marimba);
+		break;
+	case TIMPANI_ID:
+		regs_tsadc = regs_tsadc_timpani;
+		regs_tsadc_count = ARRAY_SIZE(regs_tsadc_timpani);
+		break;
+	default:
 		pr_err("%s:Adie %d not supported\n",
 				__func__, tsadc_adie_type);
-		return -ENODEV;
+		rc = -ENODEV;
+		goto out;
+	}
+
+	rc = regulator_bulk_get(NULL, regs_tsadc_count, regs_tsadc);
+	if (rc) {
+		pr_err("%s: could not get regulators: %d\n",
+				__func__, rc);
+		goto out;
+	}
+
+	rc = regulator_bulk_set_voltage(regs_tsadc_count, regs_tsadc);
+	if (rc) {
+		pr_err("%s: could not set regulator voltages: %d\n",
+				__func__, rc);
+		goto vreg_free;
 	}
 
 	return 0;
 
-vreg_get_fail:
-	while (i) {
-		if (tsadc_adie_type == TIMPANI_ID)
-			vreg_put(vregs_timpani_tsadc[--i]);
-		else if (tsadc_adie_type == MARIMBA_ID)
-			vreg_put(vregs_tsadc[--i]);
-	}
+vreg_free:
+	regulator_bulk_free(regs_tsadc_count, regs_tsadc);
+out:
+	regs_tsadc = NULL;
+	regs_tsadc_count = 0;
 	return rc;
 }
 
 static int marimba_tsadc_exit(void)
 {
-	int i, rc = 0;
-	int tsadc_adie_type = adie_get_detected_codec_type();
+	regulator_bulk_free(regs_tsadc_count, regs_tsadc);
+	regs_tsadc_count = 0;
+	regs_tsadc = NULL;
 
-	if (tsadc_adie_type == TIMPANI_ID) {
-		for (i = 0; i < ARRAY_SIZE(vregs_timpani_tsadc_name); i++) {
-			if (vregs_tsadc[i])
-				vreg_put(vregs_timpani_tsadc[i]);
-		}
-	} else if (tsadc_adie_type == MARIMBA_ID) {
-		for (i = 0; i < ARRAY_SIZE(vregs_tsadc_name); i++) {
-			if (vregs_tsadc[i])
-				vreg_put(vregs_tsadc[i]);
-		}
-		rc = pmapp_vreg_level_vote(tsadc_id, PMAPP_VREG_S2, 0);
-		if (rc < 0)
-			pr_err("%s: vreg level off failed (%d)\n",
-						__func__, rc);
-	} else {
-		pr_err("%s:Adie %d not supported\n",
-				__func__, tsadc_adie_type);
-		rc = -ENODEV;
-	}
-
-	return rc;
+	return 0;
 }
 
 
@@ -2252,7 +2158,6 @@
 	.marimba_tsadc_power =  marimba_tsadc_power,
 	.init		     =  marimba_tsadc_init,
 	.exit		     =  marimba_tsadc_exit,
-	.level_vote	     =  marimba_tsadc_vote,
 	.tsadc_prechg_en = true,
 	.can_wakeup	= false,
 	.setup = {
@@ -2271,39 +2176,47 @@
 	.tssc_data = &msm_ts_data,
 };
 
-static struct vreg *vreg_codec_s4;
+static struct regulator_bulk_data codec_regs[] = {
+	{ .supply = "s4", .min_uV = 2200000, .max_uV = 2200000 },
+};
+
+static int __init msm_marimba_codec_init(void)
+{
+	int rc = regulator_bulk_get(NULL, ARRAY_SIZE(codec_regs), codec_regs);
+
+	if (rc) {
+		pr_err("%s: could not get regulators: %d\n", __func__, rc);
+		goto out;
+	}
+
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(codec_regs), codec_regs);
+	if (rc) {
+		pr_err("%s: could not set regulator voltages: %d\n",
+				__func__, rc);
+		goto reg_free;
+	}
+
+	return rc;
+
+reg_free:
+	regulator_bulk_free(ARRAY_SIZE(codec_regs), codec_regs);
+out:
+	return rc;
+}
+
 static int msm_marimba_codec_power(int vreg_on)
 {
-	int rc = 0;
+	int rc = vreg_on ?
+		regulator_bulk_enable(ARRAY_SIZE(codec_regs), codec_regs) :
+		regulator_bulk_disable(ARRAY_SIZE(codec_regs), codec_regs);
 
-	if (!vreg_codec_s4) {
-
-		vreg_codec_s4 = vreg_get(NULL, "s4");
-
-		if (IS_ERR(vreg_codec_s4)) {
-			printk(KERN_ERR "%s: vreg_get() failed (%ld)\n",
-				__func__, PTR_ERR(vreg_codec_s4));
-			rc = PTR_ERR(vreg_codec_s4);
-			goto  vreg_codec_s4_fail;
-		}
+	if (rc) {
+		pr_err("%s: could not %sable regulators: %d",
+				__func__, vreg_on ? "en" : "dis", rc);
+		return rc;
 	}
 
-	if (vreg_on) {
-		rc = vreg_enable(vreg_codec_s4);
-		if (rc)
-			printk(KERN_ERR "%s: vreg_enable() = %d \n",
-					__func__, rc);
-		goto vreg_codec_s4_fail;
-	} else {
-		rc = vreg_disable(vreg_codec_s4);
-		if (rc)
-			printk(KERN_ERR "%s: vreg_disable() = %d \n",
-					__func__, rc);
-		goto vreg_codec_s4_fail;
-	}
-
-vreg_codec_s4_fail:
-	return rc;
+	return 0;
 }
 
 static struct marimba_codec_platform_data mariba_codec_pdata = {
@@ -2334,29 +2247,38 @@
 {
 	int rc;
 
-	vreg_marimba_1 = vreg_get(NULL, "s3");
-	if (IS_ERR(vreg_marimba_1)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
-			__func__, PTR_ERR(vreg_marimba_1));
-		return;
-	}
-	rc = vreg_set_level(vreg_marimba_1, 1800);
+	struct regulator_bulk_data regs[] = {
+		{ .supply = "s3",   .min_uV = 1800000, .max_uV = 1800000 },
+		{ .supply = "gp16", .min_uV = 1200000, .max_uV = 1200000 },
+		{ .supply = "usb2", .min_uV = 1800000, .max_uV = 1800000 },
+	};
 
-	vreg_marimba_2 = vreg_get(NULL, "gp16");
-	if (IS_ERR(vreg_marimba_1)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
-			__func__, PTR_ERR(vreg_marimba_1));
-		return;
-	}
-	rc = vreg_set_level(vreg_marimba_2, 1200);
+	rc = msm_marimba_codec_init();
 
-	vreg_marimba_3 = vreg_get(NULL, "usb2");
-	if (IS_ERR(vreg_marimba_3)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
-			__func__, PTR_ERR(vreg_marimba_3));
+	if (rc) {
+		pr_err("%s: msm_marimba_codec_init failed (%d)\n",
+				__func__, rc);
 		return;
 	}
-	rc = vreg_set_level(vreg_marimba_3, 1800);
+
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs), regs);
+
+	if (rc) {
+		pr_err("%s: could not get regulators: %d\n", __func__, rc);
+		return;
+	}
+
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs), regs);
+
+	if (rc) {
+		pr_err("%s: could not set voltages: %d\n", __func__, rc);
+		regulator_bulk_free(ARRAY_SIZE(regs), regs);
+		return;
+	}
+
+	vreg_marimba_1 = regs[0].consumer;
+	vreg_marimba_2 = regs[1].consumer;
+	vreg_bahama    = regs[2].consumer;
 }
 
 static struct marimba_codec_platform_data timpani_codec_pdata = {
@@ -2748,6 +2670,13 @@
 	"optnav_chip_select" },
 };
 
+static struct regulator_bulk_data optnav_regulators[] = {
+	{ .supply = "gp7", .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "gp4", .min_uV = 2600000, .max_uV = 2600000 },
+	{ .supply = "gp9", .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "usb", .min_uV = 3300000, .max_uV = 3300000 },
+};
+
 static void __iomem *virtual_optnav;
 
 static int optnav_gpio_setup(void)
@@ -2756,6 +2685,9 @@
 	rc = msm_gpios_request_enable(optnav_config_data,
 			ARRAY_SIZE(optnav_config_data));
 
+	if (rc)
+		return rc;
+
 	/* Configure the FPGA for GPIOs */
 	virtual_optnav = ioremap(FPGA_OPTNAV_GPIO_ADDR, 0x4);
 	if (!virtual_optnav) {
@@ -2767,6 +2699,22 @@
 	 * normal, active(enabled), output(MSM to SURF)
 	 */
 	writew(0x311E, virtual_optnav);
+
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(optnav_regulators),
+			optnav_regulators);
+	if (rc)
+		return rc;
+
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(optnav_regulators),
+			optnav_regulators);
+
+	if (rc)
+		goto regulator_put;
+
+	return rc;
+
+regulator_put:
+	regulator_bulk_free(ARRAY_SIZE(optnav_regulators), optnav_regulators);
 	return rc;
 }
 
@@ -2775,13 +2723,9 @@
 	msm_gpios_disable_free(optnav_config_data,
 		ARRAY_SIZE(optnav_config_data));
 	iounmap(virtual_optnav);
+	regulator_bulk_free(ARRAY_SIZE(optnav_regulators), optnav_regulators);
 }
 
-static struct vreg *vreg_gp7;
-static struct vreg *vreg_gp4;
-static struct vreg *vreg_gp9;
-static struct vreg *vreg_usb3_3;
-
 static int optnav_enable(void)
 {
 	int rc;
@@ -2789,80 +2733,24 @@
 	 * Enable the VREGs L8(gp7), L10(gp4), L12(gp9), L6(usb)
 	 * for I2C communication with keyboard.
 	 */
-	vreg_gp7 = vreg_get(NULL, "gp7");
-	rc = vreg_set_level(vreg_gp7, 1800);
-	if (rc) {
-		pr_err("%s: vreg_set_level failed \n", __func__);
-		goto fail_vreg_gp7;
-	}
 
-	rc = vreg_enable(vreg_gp7);
-	if (rc) {
-		pr_err("%s: vreg_enable failed \n", __func__);
-		goto fail_vreg_gp7;
-	}
+	rc = regulator_bulk_enable(ARRAY_SIZE(optnav_regulators),
+			optnav_regulators);
 
-	vreg_gp4 = vreg_get(NULL, "gp4");
-	rc = vreg_set_level(vreg_gp4, 2600);
-	if (rc) {
-		pr_err("%s: vreg_set_level failed \n", __func__);
-		goto fail_vreg_gp4;
-	}
-
-	rc = vreg_enable(vreg_gp4);
-	if (rc) {
-		pr_err("%s: vreg_enable failed \n", __func__);
-		goto fail_vreg_gp4;
-	}
-
-	vreg_gp9 = vreg_get(NULL, "gp9");
-	rc = vreg_set_level(vreg_gp9, 1800);
-	if (rc) {
-		pr_err("%s: vreg_set_level failed \n", __func__);
-		goto fail_vreg_gp9;
-	}
-
-	rc = vreg_enable(vreg_gp9);
-	if (rc) {
-		pr_err("%s: vreg_enable failed \n", __func__);
-		goto fail_vreg_gp9;
-	}
-
-	vreg_usb3_3 = vreg_get(NULL, "usb");
-	rc = vreg_set_level(vreg_usb3_3, 3300);
-	if (rc) {
-		pr_err("%s: vreg_set_level failed \n", __func__);
-		goto fail_vreg_3_3;
-	}
-
-	rc = vreg_enable(vreg_usb3_3);
-	if (rc) {
-		pr_err("%s: vreg_enable failed \n", __func__);
-		goto fail_vreg_3_3;
-	}
+	if (rc)
+		return rc;
 
 	/* Enable the chip select GPIO */
 	gpio_set_value(OPTNAV_CHIP_SELECT, 1);
 	gpio_set_value(OPTNAV_CHIP_SELECT, 0);
 
 	return 0;
-
-fail_vreg_3_3:
-	vreg_disable(vreg_gp9);
-fail_vreg_gp9:
-	vreg_disable(vreg_gp4);
-fail_vreg_gp4:
-	vreg_disable(vreg_gp7);
-fail_vreg_gp7:
-	return rc;
 }
 
 static void optnav_disable(void)
 {
-	vreg_disable(vreg_usb3_3);
-	vreg_disable(vreg_gp9);
-	vreg_disable(vreg_gp4);
-	vreg_disable(vreg_gp7);
+	regulator_bulk_disable(ARRAY_SIZE(optnav_regulators),
+			optnav_regulators);
 
 	gpio_set_value(OPTNAV_CHIP_SELECT, 1);
 }
@@ -2907,74 +2795,61 @@
 };
 
 #ifdef CONFIG_BOSCH_BMA150
-static struct vreg *vreg_gp6;
-static int sensors_ldo_enable(void)
+
+static struct regulator_bulk_data sensors_ldo[] = {
+	{ .supply = "gp7", .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "gp6", .min_uV = 3050000, .max_uV = 3100000 },
+};
+
+static int __init sensors_ldo_init(void)
 {
 	int rc;
 
-	/*
-	 * Enable the VREGs L8(gp7), L15(gp6)
-	 * for I2C communication with sensors.
-	 */
-	pr_info("sensors_ldo_enable called!!\n");
-	vreg_gp7 = vreg_get(NULL, "gp7");
-	if (IS_ERR(vreg_gp7)) {
-		pr_err("%s: vreg_get gp7 failed\n", __func__);
-		rc = PTR_ERR(vreg_gp7);
-		goto fail_gp7_get;
-	}
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(sensors_ldo), sensors_ldo);
 
-	rc = vreg_set_level(vreg_gp7, 1800);
 	if (rc) {
-		pr_err("%s: vreg_set_level gp7 failed\n", __func__);
-		goto fail_gp7_level;
+		pr_err("%s: could not get regulators: %d\n", __func__, rc);
+		goto out;
 	}
 
-	rc = vreg_enable(vreg_gp7);
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(sensors_ldo), sensors_ldo);
+
 	if (rc) {
-		pr_err("%s: vreg_enable gp7 failed\n", __func__);
-		goto fail_gp7_level;
-	}
-
-	vreg_gp6 = vreg_get(NULL, "gp6");
-	if (IS_ERR(vreg_gp6)) {
-		pr_err("%s: vreg_get gp6 failed\n", __func__);
-		rc = PTR_ERR(vreg_gp6);
-		goto fail_gp6_get;
-	}
-
-	rc = vreg_set_level(vreg_gp6, 3050);
-	if (rc) {
-		pr_err("%s: vreg_set_level gp6 failed\n", __func__);
-		goto fail_gp6_level;
-	}
-
-	rc = vreg_enable(vreg_gp6);
-	if (rc) {
-		pr_err("%s: vreg_enable gp6 failed\n", __func__);
-		goto fail_gp6_level;
+		pr_err("%s: could not set voltages: %d\n", __func__, rc);
+		goto reg_free;
 	}
 
 	return 0;
 
-fail_gp6_level:
-	vreg_put(vreg_gp6);
-fail_gp6_get:
-	vreg_disable(vreg_gp7);
-fail_gp7_level:
-	vreg_put(vreg_gp7);
-fail_gp7_get:
+reg_free:
+	regulator_bulk_free(ARRAY_SIZE(sensors_ldo), sensors_ldo);
+out:
 	return rc;
 }
 
+static int sensors_ldo_set(int on)
+{
+	int rc = on ?
+		regulator_bulk_enable(ARRAY_SIZE(sensors_ldo), sensors_ldo) :
+		regulator_bulk_disable(ARRAY_SIZE(sensors_ldo), sensors_ldo);
+
+	if (rc)
+		pr_err("%s: could not %sable regulators: %d\n",
+				__func__, on ? "en" : "dis", rc);
+
+	return rc;
+}
+
+static int sensors_ldo_enable(void)
+{
+	return sensors_ldo_set(1);
+}
+
 static void sensors_ldo_disable(void)
 {
-	pr_info("sensors_ldo_disable called!!\n");
-	vreg_disable(vreg_gp6);
-	vreg_put(vreg_gp6);
-	vreg_disable(vreg_gp7);
-	vreg_put(vreg_gp7);
+	sensors_ldo_set(0);
 }
+
 static struct bma150_platform_data bma150_data = {
 	.power_on = sensors_ldo_enable,
 	.power_off = sensors_ldo_disable,
@@ -3262,27 +3137,27 @@
 #endif
 
 #ifdef CONFIG_USB_MSM_OTG_72K
-static struct vreg *vreg_3p3;
+static struct regulator *vreg_3p3;
 static int msm_hsusb_ldo_init(int init)
 {
 	uint32_t version = 0;
-	int def_vol = 3400;
+	int def_vol = 3400000;
 
 	version = socinfo_get_version();
 
 	if (SOCINFO_VERSION_MAJOR(version) >= 2 &&
 			SOCINFO_VERSION_MINOR(version) >= 1) {
-		def_vol = 3075;
+		def_vol = 3075000;
 		pr_debug("%s: default voltage:%d\n", __func__, def_vol);
 	}
 
 	if (init) {
-		vreg_3p3 = vreg_get(NULL, "usb");
+		vreg_3p3 = regulator_get(NULL, "usb");
 		if (IS_ERR(vreg_3p3))
 			return PTR_ERR(vreg_3p3);
-		vreg_set_level(vreg_3p3, def_vol);
+		regulator_set_voltage(vreg_3p3, def_vol, def_vol);
 	} else
-		vreg_put(vreg_3p3);
+		regulator_put(vreg_3p3);
 
 	return 0;
 }
@@ -3300,14 +3175,14 @@
 	ldo_status = enable;
 
 	if (enable)
-		return vreg_enable(vreg_3p3);
-
-	return vreg_disable(vreg_3p3);
+		return regulator_enable(vreg_3p3);
+	else
+		return regulator_disable(vreg_3p3);
 }
 
 static int msm_hsusb_ldo_set_voltage(int mV)
 {
-	static int cur_voltage = 3400;
+	static int cur_voltage;
 
 	if (!vreg_3p3 || IS_ERR(vreg_3p3))
 		return -ENODEV;
@@ -3319,7 +3194,7 @@
 
 	pr_debug("%s: (%d)\n", __func__, mV);
 
-	return vreg_set_level(vreg_3p3, mV);
+	return regulator_set_voltage(vreg_3p3, mV*1000, mV*1000);
 }
 #endif
 
@@ -3500,35 +3375,163 @@
 	GPIO_CFG(37, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA);
 #endif
 
-static int gpio_set(const char *label, const char *name, int level, int on)
+static struct regulator_bulk_data hdmi_core_regs[] = {
+	{ .supply = "ldo8",  .min_uV = 1800000, .max_uV = 1800000 },
+};
+
+static struct regulator_bulk_data hdmi_comm_regs[] = {
+	{ .supply = "ldo8",  .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "ldo10", .min_uV = 2600000, .max_uV = 2600000 },
+};
+
+static struct regulator_bulk_data hdmi_cec_regs[] = {
+	{ .supply = "ldo17", .min_uV = 2600000, .max_uV = 2600000 },
+};
+
+static int __init hdmi_init_regs(void)
 {
-	struct vreg *vreg = vreg_get(NULL, label);
 	int rc;
 
-	if (IS_ERR(vreg)) {
-		rc = PTR_ERR(vreg);
-		pr_err("%s: vreg %s get failed (%d)\n",
-			__func__, name, rc);
-		return rc;
-	}
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(hdmi_core_regs),
+			hdmi_core_regs);
 
-	rc = vreg_set_level(vreg, level);
 	if (rc) {
-		pr_err("%s: vreg %s set level failed (%d)\n",
-			__func__, name, rc);
-		return rc;
+		pr_err("%s: could not get %s regulators: %d\n",
+				__func__, "core", rc);
+		goto out;
 	}
 
-	if (on)
-		rc = vreg_enable(vreg);
-	else
-		rc = vreg_disable(vreg);
-	if (rc)
-		pr_err("%s: vreg %s enable failed (%d)\n",
-			__func__, name, rc);
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(hdmi_core_regs),
+			hdmi_core_regs);
+
+	if (rc) {
+		pr_err("%s: could not set %s voltages: %d\n",
+				__func__, "core", rc);
+		goto free_core;
+	}
+
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(hdmi_comm_regs),
+			hdmi_comm_regs);
+
+	if (rc) {
+		pr_err("%s: could not get %s regulators: %d\n",
+				__func__, "comm", rc);
+		goto free_core;
+	}
+
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(hdmi_comm_regs),
+			hdmi_comm_regs);
+
+	if (rc) {
+		pr_err("%s: could not set %s voltages: %d\n",
+				__func__, "comm", rc);
+		goto free_comm;
+	}
+
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(hdmi_cec_regs),
+			hdmi_cec_regs);
+
+	if (rc) {
+		pr_err("%s: could not get %s regulators: %d\n",
+				__func__, "cec", rc);
+		goto free_comm;
+	}
+
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(hdmi_cec_regs),
+			hdmi_cec_regs);
+
+	if (rc) {
+		pr_err("%s: could not set %s voltages: %d\n",
+				__func__, "cec", rc);
+		goto free_cec;
+	}
+
+	return 0;
+
+free_cec:
+	regulator_bulk_free(ARRAY_SIZE(hdmi_cec_regs), hdmi_cec_regs);
+free_comm:
+	regulator_bulk_free(ARRAY_SIZE(hdmi_comm_regs), hdmi_comm_regs);
+free_core:
+	regulator_bulk_free(ARRAY_SIZE(hdmi_core_regs), hdmi_core_regs);
+out:
 	return rc;
 }
 
+static int hdmi_init_irq(void)
+{
+	int rc = msm_gpios_enable(dtv_panel_irq_gpios,
+			ARRAY_SIZE(dtv_panel_irq_gpios));
+	if (rc < 0) {
+		pr_err("%s: gpio enable failed: %d\n", __func__, rc);
+		return rc;
+	}
+	pr_info("%s\n", __func__);
+
+	return 0;
+}
+
+static int hdmi_enable_5v(int on)
+{
+	int pmic_gpio_hdmi_5v_en ;
+
+	if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa() ||
+						machine_is_msm7x30_fluid())
+		pmic_gpio_hdmi_5v_en = PMIC_GPIO_HDMI_5V_EN_V2 ;
+	else
+		pmic_gpio_hdmi_5v_en = PMIC_GPIO_HDMI_5V_EN_V3 ;
+
+	pr_info("%s: %d\n", __func__, on);
+	if (on) {
+		int rc;
+		rc = gpio_request(PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en),
+			"hdmi_5V_en");
+		if (rc) {
+			pr_err("%s PMIC_GPIO_HDMI_5V_EN gpio_request failed\n",
+				__func__);
+			return rc;
+		}
+		gpio_set_value_cansleep(
+			PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en), 1);
+	} else {
+		gpio_set_value_cansleep(
+			PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en), 0);
+		gpio_free(PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en));
+	}
+	return 0;
+}
+
+static int hdmi_comm_power(int on, int show)
+{
+	if (show)
+		pr_info("%s: i2c comm: %d <LDO8+LDO10>\n", __func__, on);
+	return on ?
+		regulator_bulk_enable(ARRAY_SIZE(hdmi_comm_regs),
+				hdmi_comm_regs) :
+		regulator_bulk_disable(ARRAY_SIZE(hdmi_comm_regs),
+				hdmi_comm_regs);
+}
+
+static int hdmi_core_power(int on, int show)
+{
+	if (show)
+		pr_info("%s: %d <LDO8>\n", __func__, on);
+	return on ?
+		regulator_bulk_enable(ARRAY_SIZE(hdmi_core_regs),
+				hdmi_core_regs) :
+		regulator_bulk_disable(ARRAY_SIZE(hdmi_core_regs),
+				hdmi_core_regs);
+}
+
+static int hdmi_cec_power(int on)
+{
+	pr_info("%s: %d <LDO17>\n", __func__, on);
+	return on ? regulator_bulk_enable(ARRAY_SIZE(hdmi_cec_regs),
+				hdmi_cec_regs) :
+		regulator_bulk_disable(ARRAY_SIZE(hdmi_cec_regs),
+				hdmi_cec_regs);
+}
+
 #if defined(CONFIG_FB_MSM_HDMI_ADV7520_PANEL) || defined(CONFIG_BOSCH_BMA150)
 /* there is an i2c address conflict between adv7520 and bma150 sensor after
  * power up on fluid. As a solution, the default address of adv7520's packet
@@ -3541,7 +3544,6 @@
 	struct i2c_msg msgs[3];
 	int res;
 	int rc = -EINVAL;
-	struct vreg *vreg_ldo8;
 	struct i2c_adapter *adapter;
 
 	if (machine_is_msm7x30_fluid()) {
@@ -3552,24 +3554,13 @@
 		}
 
 		/* turn on LDO8 */
-		vreg_ldo8 = vreg_get(NULL, "gp7");
-		if (!vreg_ldo8) {
-			pr_err("%s: VREG L8 get failed\n", __func__);
+		rc = hdmi_core_power(1, 0);
+		if (rc) {
+			pr_err("%s: could not enable hdmi core regs: %d",
+					__func__, rc);
 			goto adapter_put;
 		}
 
-		rc = vreg_set_level(vreg_ldo8, 1800);
-		if (rc) {
-			pr_err("%s: VREG L8 set failed\n", __func__);
-			goto ldo8_put;
-		}
-
-		rc = vreg_enable(vreg_ldo8);
-		if (rc) {
-			pr_err("%s: VREG L8 enable failed\n", __func__);
-			goto ldo8_put;
-		}
-
 		/* change packet memory address to 0x74 */
 		wBuff[0] = 0x45;
 		wBuff[1] = 0x74;
@@ -3627,9 +3618,7 @@
 	return 0;
 
 ldo8_disable:
-	vreg_disable(vreg_ldo8);
-ldo8_put:
-	vreg_put(vreg_ldo8);
+	hdmi_core_power(0, 0);
 adapter_put:
 	i2c_put_adapter(adapter);
 	return rc;
@@ -3637,77 +3626,6 @@
 fs_initcall_sync(fluid_i2c_address_fixup);
 #endif
 
-static int hdmi_comm_power(int on, int show)
-{
-	int rc = gpio_set("gp7", "LDO8", 1800, on);
-	if (rc) {
-		pr_warning("hdmi_comm_power: LDO8 gpio failed: rc=%d\n", rc);
-		return rc;
-	}
-	rc = gpio_set("gp4", "LDO10", 2600, on);
-	if (rc)
-		pr_warning("hdmi_comm_power: LDO10 gpio failed: rc=%d\n", rc);
-	if (show)
-		pr_info("%s: i2c comm: %d <LDO8+LDO10>\n", __func__, on);
-	return rc;
-}
-
-static int hdmi_init_irq(void)
-{
-	int rc = msm_gpios_enable(dtv_panel_irq_gpios,
-			ARRAY_SIZE(dtv_panel_irq_gpios));
-	if (rc < 0) {
-		pr_err("%s: gpio enable failed: %d\n", __func__, rc);
-		return rc;
-	}
-	pr_info("%s\n", __func__);
-
-	return 0;
-}
-
-static int hdmi_enable_5v(int on)
-{
-	int pmic_gpio_hdmi_5v_en ;
-
-	if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa() ||
-						machine_is_msm7x30_fluid())
-		pmic_gpio_hdmi_5v_en = PMIC_GPIO_HDMI_5V_EN_V2 ;
-	else
-		pmic_gpio_hdmi_5v_en = PMIC_GPIO_HDMI_5V_EN_V3 ;
-
-	pr_info("%s: %d\n", __func__, on);
-	if (on) {
-		int rc;
-		rc = gpio_request(PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en),
-			"hdmi_5V_en");
-		if (rc) {
-			pr_err("%s PMIC_GPIO_HDMI_5V_EN gpio_request failed\n",
-				__func__);
-			return rc;
-		}
-		gpio_set_value_cansleep(
-			PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en), 1);
-	} else {
-		gpio_set_value_cansleep(
-			PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en), 0);
-		gpio_free(PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en));
-	}
-	return 0;
-}
-
-static int hdmi_core_power(int on, int show)
-{
-	if (show)
-		pr_info("%s: %d <LDO8>\n", __func__, on);
-	return gpio_set("gp7", "LDO8", 1800, on);
-}
-
-static int hdmi_cec_power(int on)
-{
-	pr_info("%s: %d <LDO17>\n", __func__, on);
-	return gpio_set("gp11", "LDO17", 2600, on);
-}
-
 static bool hdmi_check_hdcp_hw_support(void)
 {
 	if (machine_is_msm7x30_fluid())
@@ -4024,18 +3942,86 @@
 	},
 };
 
+static struct regulator *mddi_ldo20;
+static struct regulator *mddi_ldo12;
+static struct regulator *mddi_ldo16;
+static struct regulator *mddi_ldo6;
+static struct regulator *mddi_lcd;
+
+static int display_common_init(void)
+{
+	struct regulator_bulk_data regs[5] = {
+		{ .supply = "ldo20", /* voltage set in display_common_power */},
+		{ .supply = "ldo12", .min_uV = 1800000, .max_uV = 1800000 },
+		{ .supply = "ldo6",  .min_uV = 3075000, .max_uV = 3400000 },
+		{ .supply = "ldo16", .min_uV = 2600000, .max_uV = 2600000 },
+		{ .supply = NULL,    /* mddi_lcd, initialized below */ },
+	};
+
+	int rc = 0;
+
+	if (machine_is_msm7x30_fluid()) {
+		/* lcd: LDO8 @1.8V */
+		regs[4].supply = "ldo8";
+		regs[4].min_uV = 1800000;
+		regs[4].max_uV = 1800000;
+	} else {
+		/* lcd: LDO15 @3.1V */
+		regs[4].supply = "ldo15";
+		regs[4].min_uV = 3100000;
+		regs[4].max_uV = 3100000;
+	}
+
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs), regs);
+	if (rc) {
+		pr_err("%s: regulator_bulk_get failed: %d\n",
+				__func__, rc);
+		goto bail;
+	}
+
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs), regs);
+	if (rc) {
+		pr_err("%s: regulator_bulk_set_voltage failed: %d\n",
+				__func__, rc);
+		goto put_regs;
+	}
+
+	mddi_ldo20 = regs[0].consumer;
+	mddi_ldo12 = regs[1].consumer;
+	mddi_ldo6  = regs[2].consumer;
+	mddi_ldo16 = regs[3].consumer;
+	mddi_lcd   = regs[4].consumer;
+
+	return rc;
+
+put_regs:
+	regulator_bulk_free(ARRAY_SIZE(regs), regs);
+bail:
+	return rc;
+}
+
 static int display_common_power(int on)
 {
 	int rc = 0, flag_on = !!on;
 	static int display_common_power_save_on;
-	struct vreg *vreg_ldo12, *vreg_ldo15 = NULL, *vreg_ldo6;
-	struct vreg *vreg_ldo20, *vreg_ldo16, *vreg_ldo8 = NULL;
+	static bool display_regs_initialized;
 
 	if (display_common_power_save_on == flag_on)
 		return 0;
 
 	display_common_power_save_on = flag_on;
 
+	if (unlikely(!display_regs_initialized)) {
+		rc = display_common_init();
+		if (rc) {
+			pr_err("%s: regulator init failed: %d\n",
+					__func__, rc);
+			return rc;
+		}
+		display_regs_initialized = true;
+	}
+
+
 	if (on) {
 		/* reset Toshiba WeGA chip -- toggle reset pin -- gpio_180 */
 		rc = gpio_tlmm_config(wega_reset_gpio, GPIO_CFG_ENABLE);
@@ -4075,172 +4061,57 @@
 		}
 	}
 
-	/* Toshiba WeGA power -- has 3 power source */
-	/* 1.5V -- LDO20*/
-	vreg_ldo20 = vreg_get(NULL, "gp13");
-
-	if (IS_ERR(vreg_ldo20)) {
-		rc = PTR_ERR(vreg_ldo20);
-		pr_err("%s: gp13 vreg get failed (%d)\n",
-		       __func__, rc);
-		return rc;
-	}
-
-	/* 1.8V -- LDO12 */
-	vreg_ldo12 = vreg_get(NULL, "gp9");
-
-	if (IS_ERR(vreg_ldo12)) {
-		rc = PTR_ERR(vreg_ldo12);
-		pr_err("%s: gp9 vreg get failed (%d)\n",
-		       __func__, rc);
-		return rc;
-	}
-
-	/* 2.6V -- LDO16 */
-	vreg_ldo16 = vreg_get(NULL, "gp10");
-
-	if (IS_ERR(vreg_ldo16)) {
-		rc = PTR_ERR(vreg_ldo16);
-		pr_err("%s: gp10 vreg get failed (%d)\n",
-			   __func__, rc);
-		return rc;
-	}
-
-	/* 3.075V -- LDO6 */
-	vreg_ldo6 = vreg_get(NULL, "usb");
-
-	if (IS_ERR(vreg_ldo6)) {
-		rc = PTR_ERR(vreg_ldo6);
-		pr_err("%s: usb vreg get failed (%d)\n",
-			   __func__, rc);
-		return rc;
-	}
-
-	if (machine_is_msm7x30_fluid()) {
-		/* 1.8V -- LDO8 */
-		vreg_ldo8 = vreg_get(NULL, "gp7");
-
-		if (IS_ERR(vreg_ldo8)) {
-			rc = PTR_ERR(vreg_ldo8);
-			pr_err("%s: gp7 vreg get failed (%d)\n",
-				__func__, rc);
-			return rc;
-		}
-	} else {
-		/* lcd panel power */
-		/* 3.1V -- LDO15 */
-		vreg_ldo15 = vreg_get(NULL, "gp6");
-
-		if (IS_ERR(vreg_ldo15)) {
-			rc = PTR_ERR(vreg_ldo15);
-			pr_err("%s: gp6 vreg get failed (%d)\n",
-				__func__, rc);
-			return rc;
-		}
-	}
-
-	/* For QuickLogic chip, LDO20 requires 1.8V */
-	/* Toshiba chip requires 1.5V, but can tolerate 1.8V since max is 3V */
 	if (quickvx_mddi_client)
-		rc = vreg_set_level(vreg_ldo20, 1800);
+		rc = regulator_set_voltage(mddi_ldo20, 1800000, 1800000);
 	else
-		rc = vreg_set_level(vreg_ldo20, 1500);
+		rc = regulator_set_voltage(mddi_ldo20, 1500000, 1500000);
+
 	if (rc) {
-		pr_err("%s: vreg LDO20 set level failed (%d)\n",
-		       __func__, rc);
-		return rc;
-	}
-
-	rc = vreg_set_level(vreg_ldo12, 1800);
-	if (rc) {
-		pr_err("%s: vreg LDO12 set level failed (%d)\n",
-		       __func__, rc);
-		return rc;
-	}
-
-	if (other_mddi_client) {
-		rc = vreg_set_level(vreg_ldo16, 2600);
-		if (rc) {
-			pr_err("%s: vreg LDO16 set level failed (%d)\n",
-				   __func__, rc);
-			return rc;
-		}
-	}
-
-	if (quickvx_mddi_client) {
-		rc = vreg_set_level(vreg_ldo6, 3075);
-		if (rc) {
-			pr_err("%s: vreg LDO6 set level failed (%d)\n",
-				   __func__, rc);
-			return rc;
-		}
-	}
-
-	if (machine_is_msm7x30_fluid()) {
-		rc = vreg_set_level(vreg_ldo8, 1800);
-		if (rc) {
-			pr_err("%s: vreg LDO8 set level failed (%d)\n",
+		pr_err("%s: could not set voltage for ldo20: %d\n",
 				__func__, rc);
-			return rc;
-		}
-	} else {
-		rc = vreg_set_level(vreg_ldo15, 3100);
-		if (rc) {
-			pr_err("%s: vreg LDO15 set level failed (%d)\n",
-				__func__, rc);
-			return rc;
-		}
+		return rc;
 	}
 
 	if (on) {
-		rc = vreg_enable(vreg_ldo20);
+		rc = regulator_enable(mddi_ldo20);
 		if (rc) {
-			pr_err("%s: LDO20 vreg enable failed (%d)\n",
+			pr_err("%s: LDO20 regulator enable failed (%d)\n",
 			       __func__, rc);
 			return rc;
 		}
 
-		rc = vreg_enable(vreg_ldo12);
+		rc = regulator_enable(mddi_ldo12);
 		if (rc) {
-			pr_err("%s: LDO12 vreg enable failed (%d)\n",
+			pr_err("%s: LDO12 regulator enable failed (%d)\n",
 			       __func__, rc);
 			return rc;
 		}
 
 		if (other_mddi_client) {
-			rc = vreg_enable(vreg_ldo16);
+			rc = regulator_enable(mddi_ldo16);
 			if (rc) {
-				pr_err("%s: LDO16 vreg enable failed (%d)\n",
+				pr_err("%s: LDO16 regulator enable failed (%d)\n",
 					   __func__, rc);
 				return rc;
 			}
 		}
 
-		if (quickvx_mddi_client && quickvx_ldo_enabled) {
+		if (quickvx_ldo_enabled) {
 			/* Disable LDO6 during display ON */
-			rc = vreg_disable(vreg_ldo6);
+			rc = regulator_disable(mddi_ldo6);
 			if (rc) {
-				pr_err("%s: LDO6 vreg disable failed (%d)\n",
+				pr_err("%s: LDO6 regulator disable failed (%d)\n",
 					   __func__, rc);
 				return rc;
 			}
 			quickvx_ldo_enabled = 0;
 		}
 
-		if (machine_is_msm7x30_fluid()) {
-			rc = vreg_enable(vreg_ldo8);
-			if (rc) {
-				pr_err("%s: LDO8 vreg enable failed (%d)\n",
-					__func__, rc);
-				return rc;
-			}
-		} else {
-			rc = vreg_enable(vreg_ldo15);
-			if (rc) {
-				pr_err("%s: LDO15 vreg enable failed (%d)\n",
-					__func__, rc);
-				return rc;
-			}
+		rc = regulator_enable(mddi_lcd);
+		if (rc) {
+			pr_err("%s: LCD regulator enable failed (%d)\n",
+				__func__, rc);
+			return rc;
 		}
 
 		mdelay(5);		/* ensure power is stable */
@@ -4279,18 +4150,18 @@
 		}
 
 	} else {
-		rc = vreg_disable(vreg_ldo20);
+		rc = regulator_disable(mddi_ldo20);
 		if (rc) {
-			pr_err("%s: LDO20 vreg disable failed (%d)\n",
+			pr_err("%s: LDO20 regulator disable failed (%d)\n",
 			       __func__, rc);
 			return rc;
 		}
 
 
 		if (other_mddi_client) {
-			rc = vreg_disable(vreg_ldo16);
+			rc = regulator_disable(mddi_ldo16);
 			if (rc) {
-				pr_err("%s: LDO16 vreg disable failed (%d)\n",
+				pr_err("%s: LDO16 regulator disable failed (%d)\n",
 					   __func__, rc);
 				return rc;
 			}
@@ -4299,9 +4170,9 @@
 		if (quickvx_mddi_client && !quickvx_ldo_enabled) {
 			/* Enable LDO6 during display OFF for
 			   Quicklogic chip to sleep with data retention */
-			rc = vreg_enable(vreg_ldo6);
+			rc = regulator_enable(mddi_ldo6);
 			if (rc) {
-				pr_err("%s: LDO6 vreg enable failed (%d)\n",
+				pr_err("%s: LDO6 regulator enable failed (%d)\n",
 					   __func__, rc);
 				return rc;
 			}
@@ -4316,27 +4187,18 @@
 				PMIC_GPIO_QUICKVX_CLK), 0);
 		}
 
-		if (machine_is_msm7x30_fluid()) {
-			rc = vreg_disable(vreg_ldo8);
-			if (rc) {
-				pr_err("%s: LDO8 vreg disable failed (%d)\n",
-					__func__, rc);
-				return rc;
-			}
-		} else {
-			rc = vreg_disable(vreg_ldo15);
-			if (rc) {
-				pr_err("%s: LDO15 vreg disable failed (%d)\n",
-					__func__, rc);
-				return rc;
-			}
+		rc = regulator_disable(mddi_lcd);
+		if (rc) {
+			pr_err("%s: LCD regulator disable failed (%d)\n",
+				__func__, rc);
+			return rc;
 		}
 
 		mdelay(5);	/* ensure power is stable */
 
-		rc = vreg_disable(vreg_ldo12);
+		rc = regulator_disable(mddi_ldo12);
 		if (rc) {
-			pr_err("%s: LDO12 vreg disable failed (%d)\n",
+			pr_err("%s: LDO12 regulator disable failed (%d)\n",
 			       __func__, rc);
 			return rc;
 		}
@@ -4365,51 +4227,19 @@
 
 static int msm_fb_mddi_client_power(u32 client_id)
 {
-	struct vreg *vreg_ldo20, *vreg_ldo16;
-	int rc;
-
 	printk(KERN_NOTICE "\n client_id = 0x%x", client_id);
 	/* Check if it is Quicklogic client */
 	if (client_id == 0xc5835800) {
 		printk(KERN_NOTICE "\n Quicklogic MDDI client");
 		other_mddi_client = 0;
-		vreg_ldo16 = vreg_get(NULL, "gp10");
-
-		if (IS_ERR(vreg_ldo16)) {
-			rc = PTR_ERR(vreg_ldo16);
-			pr_err("%s: gp10 vreg get failed (%d)\n",
-				   __func__, rc);
-			return rc;
-		}
-
-		rc = vreg_disable(vreg_ldo16);
-		if (rc) {
-			pr_err("%s: LDO16 vreg enable failed (%d)\n",
-				   __func__, rc);
-			return rc;
-		}
 	} else {
 		printk(KERN_NOTICE "\n Non-Quicklogic MDDI client");
 		quickvx_mddi_client = 0;
 		gpio_set_value(97, 0);
 		gpio_set_value_cansleep(PM8058_GPIO_PM_TO_SYS(
 			PMIC_GPIO_QUICKVX_CLK), 0);
-
-		vreg_ldo20 = vreg_get(NULL, "gp13");
-
-		if (IS_ERR(vreg_ldo20)) {
-			rc = PTR_ERR(vreg_ldo20);
-			pr_err("%s: gp13 vreg get failed (%d)\n",
-				   __func__, rc);
-			return rc;
-		}
-		rc = vreg_set_level(vreg_ldo20, 1500);
-		if (rc) {
-			pr_err("%s: vreg LDO20 set level failed (%d)\n",
-			       __func__, rc);
-			return rc;
-		}
 	}
+
 	return 0;
 }
 
@@ -4574,13 +4404,18 @@
 static int lcdc_panel_power(int on)
 {
 	int flag_on = !!on;
-	static int lcdc_power_save_on;
+	static int lcdc_power_save_on, lcdc_power_initialized;
 
 	if (lcdc_power_save_on == flag_on)
 		return 0;
 
 	lcdc_power_save_on = flag_on;
-	quickvx_mddi_client = 0;
+
+	if (unlikely(!lcdc_power_initialized)) {
+		quickvx_mddi_client = 0;
+		display_common_init();
+		lcdc_power_initialized = 1;
+	}
 
 	if (machine_is_msm7x30_fluid())
 		return lcdc_sharp_panel_power(on);
@@ -4592,47 +4427,64 @@
 	.lcdc_power_save   = lcdc_panel_power,
 };
 
+static struct regulator *atv_s4, *atv_ldo9;
+
+static int __init atv_dac_power_init(void)
+{
+	int rc;
+	struct regulator_bulk_data regs[] = {
+		{ .supply = "smps4", .min_uV = 2200000, .max_uV = 2200000 },
+		{ .supply = "ldo9",  .min_uV = 2050000, .max_uV = 2050000 },
+	};
+
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs), regs);
+
+	if (rc) {
+		pr_err("%s: could not get regulators: %d\n", __func__, rc);
+		goto bail;
+	}
+
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs), regs);
+
+	if (rc) {
+		pr_err("%s: could not set voltages: %d\n", __func__, rc);
+		goto reg_free;
+	}
+
+	atv_s4   = regs[0].consumer;
+	atv_ldo9 = regs[1].consumer;
+
+reg_free:
+	regulator_bulk_free(ARRAY_SIZE(regs), regs);
+bail:
+	return rc;
+}
+
 static int atv_dac_power(int on)
 {
 	int rc = 0;
-	struct vreg *vreg_s4, *vreg_ldo9;
-
-	vreg_s4 = vreg_get(NULL, "s4");
-	if (IS_ERR(vreg_s4)) {
-		rc = PTR_ERR(vreg_s4);
-		pr_err("%s: s4 vreg get failed (%d)\n",
-			__func__, rc);
-		return -1;
-	}
-	vreg_ldo9 = vreg_get(NULL, "gp1");
-	if (IS_ERR(vreg_ldo9)) {
-		rc = PTR_ERR(vreg_ldo9);
-		pr_err("%s: ldo9 vreg get failed (%d)\n",
-			__func__, rc);
-		return rc;
-	}
 
 	if (on) {
-		rc = vreg_enable(vreg_s4);
+		rc = regulator_enable(atv_s4);
 		if (rc) {
 			pr_err("%s: s4 vreg enable failed (%d)\n",
 				__func__, rc);
 			return rc;
 		}
-		rc = vreg_enable(vreg_ldo9);
+		rc = regulator_enable(atv_ldo9);
 		if (rc) {
 			pr_err("%s: ldo9 vreg enable failed (%d)\n",
 				__func__, rc);
 			return rc;
 		}
 	} else {
-		rc = vreg_disable(vreg_ldo9);
+		rc = regulator_disable(atv_ldo9);
 		if (rc) {
 			pr_err("%s: ldo9 vreg disable failed (%d)\n",
 				   __func__, rc);
 			return rc;
 		}
-		rc = vreg_disable(vreg_s4);
+		rc = regulator_disable(atv_s4);
 		if (rc) {
 			pr_err("%s: s4 vreg disable failed (%d)\n",
 				   __func__, rc);
@@ -4707,24 +4559,31 @@
 		"UART1DM_Tx" }
 };
 
-static const char *vregs_bt_marimba_name[] = {
-	"s3",
-	"s2",
-	"gp16",
-	"wlan"
-};
-static struct vreg *vregs_bt_marimba[ARRAY_SIZE(vregs_bt_marimba_name)];
-
-static const char *vregs_bt_bahama_name[] = {
-	"s3",
-	"usb2",
-	"s2",
-	"wlan"
-};
-static struct vreg *vregs_bt_bahama[ARRAY_SIZE(vregs_bt_bahama_name)];
-
 static u8 bahama_version;
 
+static struct regulator_bulk_data regs_bt_marimba[] = {
+	{ .supply = "smps3", .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "smps2", .min_uV = 1300000, .max_uV = 1300000 },
+	{ .supply = "ldo24", .min_uV = 1200000, .max_uV = 1200000 },
+	{ .supply = "ldo13", .min_uV = 2900000, .max_uV = 2900000 },
+};
+
+static struct regulator_bulk_data regs_bt_bahama_v1[] = {
+	{ .supply = "smps3", .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "ldo7",  .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "smps2", .min_uV = 1300000, .max_uV = 1300000 },
+	{ .supply = "ldo13", .min_uV = 2900000, .max_uV = 2900000 },
+};
+
+static struct regulator_bulk_data regs_bt_bahama_v2[] = {
+	{ .supply = "smps3", .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "ldo7",  .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "ldo13", .min_uV = 2900000, .max_uV = 2900000 },
+};
+
+static struct regulator_bulk_data *regs_bt;
+static int regs_bt_count;
+
 static int marimba_bt(int on)
 {
 	int rc;
@@ -4946,15 +4805,6 @@
 
 	on = on ? 1 : 0;
 
-	bahama_version = read_bahama_ver();
-
-	if (((int)bahama_version) < 0 ||
-		bahama_version == VER_UNSUPPORTED) {
-		dev_err(&msm_bt_power_device.dev,
-			"%s: i2c failure or unsupported version: %d\n",
-			__func__, bahama_version);
-		return -EIO;
-	}
 
 	if (bahama_version == VER_2_0) {
 		if (marimba_get_fm_status(&config))
@@ -4990,69 +4840,62 @@
 	else
 		marimba_set_bt_status(&config, false);
 
-	if (bahama_version == VER_2_0 && on) { /* variant of bahama v2 */
-		/* Disable s2 as bahama v2 uses internal LDO regulator */
-		for (i = 0; i < ARRAY_SIZE(vregs_bt_bahama_name); i++) {
-			if (!strcmp(vregs_bt_bahama_name[i], "s2")) {
-				rc = vreg_disable(vregs_bt_bahama[i]);
-				if (rc < 0) {
-					printk(KERN_ERR
-						"%s: vreg %s disable "
-						"failed (%d)\n",
-						__func__,
-						vregs_bt_bahama_name[i], rc);
-					return -EIO;
-				}
-				rc = pmapp_vreg_level_vote("BTPW",
-								PMAPP_VREG_S2,
-								0);
-				if (rc < 0) {
-					printk(KERN_ERR "%s: vreg "
-						"level off failed (%d)\n",
-						__func__, rc);
-					return -EIO;
-				}
-				printk(KERN_INFO "%s: vreg disable & "
-					"level off successful (%d)\n",
-					__func__, rc);
-			}
-		}
-	}
-
 	return 0;
 }
 
-static int bluetooth_power_regulators(int on, int bahama_not_marimba)
+static int bluetooth_regs_init(int bahama_not_marimba)
 {
-	int i, rc;
-	const char **vregs_name;
-	struct vreg **vregs;
-	int vregs_size;
+	int rc = 0;
+	struct device *const dev = &msm_bt_power_device.dev;
 
 	if (bahama_not_marimba) {
-		vregs_name = vregs_bt_bahama_name;
-		vregs = vregs_bt_bahama;
-		vregs_size = ARRAY_SIZE(vregs_bt_bahama_name);
+		bahama_version = read_bahama_ver();
+
+		switch (bahama_version) {
+		case VER_1_0:
+			regs_bt = regs_bt_bahama_v1;
+			regs_bt_count = ARRAY_SIZE(regs_bt_bahama_v1);
+			break;
+		case VER_2_0:
+			regs_bt = regs_bt_bahama_v2;
+			regs_bt_count = ARRAY_SIZE(regs_bt_bahama_v2);
+			break;
+		case VER_UNSUPPORTED:
+		default:
+			dev_err(dev,
+				"%s: i2c failure or unsupported version: %d\n",
+				__func__, bahama_version);
+			rc = -EIO;
+			goto out;
+		}
 	} else {
-		vregs_name = vregs_bt_marimba_name;
-		vregs = vregs_bt_marimba;
-		vregs_size = ARRAY_SIZE(vregs_bt_marimba_name);
+		regs_bt = regs_bt_marimba;
+		regs_bt_count = ARRAY_SIZE(regs_bt_marimba);
 	}
 
-	for (i = 0; i < vregs_size; i++) {
-		if (bahama_not_marimba && (bahama_version == VER_2_0) &&
-			!on && !strcmp(vregs_bt_bahama_name[i], "s2"))
-			continue;
-		rc = on ? vreg_enable(vregs[i]) :
-			  vreg_disable(vregs[i]);
-		if (rc < 0) {
-			printk(KERN_ERR "%s: vreg %s %s failed (%d)\n",
-				__func__, vregs_name[i],
-			       on ? "enable" : "disable", rc);
-			return -EIO;
-		}
+	rc = regulator_bulk_get(&msm_bt_power_device.dev,
+			regs_bt_count, regs_bt);
+	if (rc) {
+		dev_err(dev, "%s: could not get regulators: %d\n",
+				__func__, rc);
+		goto out;
 	}
+
+	rc = regulator_bulk_set_voltage(regs_bt_count, regs_bt);
+	if (rc) {
+		dev_err(dev, "%s: could not set voltages: %d\n",
+				__func__, rc);
+		goto reg_free;
+	}
+
 	return 0;
+
+reg_free:
+	regulator_bulk_free(regs_bt_count, regs_bt);
+out:
+	regs_bt_count = 0;
+	regs_bt = NULL;
+	return rc;
 }
 
 static int bluetooth_power(int on)
@@ -5068,17 +4911,16 @@
 		return -ENODEV;
 	}
 
-	if (on) {
-		rc = pmapp_vreg_level_vote(id, PMAPP_VREG_S2, 1300);
-		if (rc < 0) {
-			printk(KERN_ERR "%s: vreg level on failed (%d)\n",
-				__func__, rc);
+	if (unlikely(regs_bt_count == 0)) {
+		rc = bluetooth_regs_init(bahama_not_marimba);
+		if (rc)
 			return rc;
-		}
+	}
 
-		rc = bluetooth_power_regulators(on, bahama_not_marimba);
-		if (rc < 0)
-			return -EIO;
+	if (on) {
+		rc = regulator_bulk_enable(regs_bt_count, regs_bt);
+		if (rc)
+			return rc;
 
 		rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO,
 					  PMAPP_CLOCK_VOTE_ON);
@@ -5135,18 +4977,10 @@
 		if (rc < 0)
 			return -EIO;
 
-		rc = bluetooth_power_regulators(on, bahama_not_marimba);
-		if (rc < 0)
-			return -EIO;
+		rc = regulator_bulk_disable(regs_bt_count, regs_bt);
+		if (rc)
+			return rc;
 
-		if (bahama_version == VER_1_0) {
-			rc = pmapp_vreg_level_vote(id, PMAPP_VREG_S2, 0);
-			if (rc < 0) {
-				printk(KERN_ERR "%s: vreg level off failed "
-				"(%d)\n", __func__, rc);
-				return -EIO;
-			}
-		}
 	}
 
 out:
@@ -5157,29 +4991,7 @@
 
 static void __init bt_power_init(void)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(vregs_bt_marimba_name); i++) {
-		vregs_bt_marimba[i] = vreg_get(NULL, vregs_bt_marimba_name[i]);
-		if (IS_ERR(vregs_bt_marimba[i])) {
-			printk(KERN_ERR "%s: vreg get %s failed (%ld)\n",
-			       __func__, vregs_bt_marimba_name[i],
-			       PTR_ERR(vregs_bt_marimba[i]));
-			return;
-		}
-	}
-
-	for (i = 0; i < ARRAY_SIZE(vregs_bt_bahama_name); i++) {
-		vregs_bt_bahama[i] = vreg_get(NULL, vregs_bt_bahama_name[i]);
-		if (IS_ERR(vregs_bt_bahama[i])) {
-			printk(KERN_ERR "%s: vreg get %s failed (%ld)\n",
-			       __func__, vregs_bt_bahama_name[i],
-			       PTR_ERR(vregs_bt_bahama[i]));
-			return;
-		}
-	}
-
-    msm_bt_power_device.dev.platform_data = &bluetooth_power;
+	msm_bt_power_device.dev.platform_data = &bluetooth_power;
 }
 #else
 #define bt_power_init(x) do {} while (0)
@@ -5415,7 +5227,7 @@
 }
 /*This needs to be enabled only for OEMS*/
 #ifndef CONFIG_QUP_EXCLUSIVE_TO_CAMERA
-static struct vreg *qup_vreg;
+static struct regulator *qup_vreg;
 #endif
 static void
 qup_i2c_gpio_config(int adap_id, int config_type)
@@ -5434,15 +5246,10 @@
 		printk(KERN_ERR "QUP GPIO enable failed: %d\n", rc);
 	/*This needs to be enabled only for OEMS*/
 #ifndef CONFIG_QUP_EXCLUSIVE_TO_CAMERA
-	if (qup_vreg) {
-		int rc = vreg_set_level(qup_vreg, 1800);
+	if (!IS_ERR_OR_NULL(qup_vreg)) {
+		rc = regulator_enable(qup_vreg);
 		if (rc) {
-			pr_err("%s: vreg LVS1 set level failed (%d)\n",
-			__func__, rc);
-		}
-		rc = vreg_enable(qup_vreg);
-		if (rc) {
-			pr_err("%s: vreg_enable() = %d \n",
+			pr_err("%s: regulator_enable failed: %d\n",
 			__func__, rc);
 		}
 	}
@@ -5491,9 +5298,10 @@
 	qup_device_i2c.dev.platform_data = &qup_i2c_pdata;
 	/*This needs to be enabled only for OEMS*/
 #ifndef CONFIG_QUP_EXCLUSIVE_TO_CAMERA
-	qup_vreg = vreg_get(NULL, "lvsw1");
+	qup_vreg = regulator_get(&qup_device_i2c.dev, "lvsw1");
 	if (IS_ERR(qup_vreg)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
+		dev_err(&qup_device_i2c.dev,
+			"%s: regulator_get failed: %ld\n",
 			__func__, PTR_ERR(qup_vreg));
 	}
 #endif
@@ -5516,9 +5324,6 @@
 	{GPIO_CFG(115, 2, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "ebi2_busy1"},
 };
 
-struct vreg *vreg_s3;
-struct vreg *vreg_mmc;
-
 #if (defined(CONFIG_MMC_MSM_SDC1_SUPPORT)\
 	|| defined(CONFIG_MMC_MSM_SDC2_SUPPORT)\
 	|| defined(CONFIG_MMC_MSM_SDC3_SUPPORT)\
@@ -5615,12 +5420,7 @@
 	},
 };
 
-struct sdcc_vreg {
-	struct vreg *vreg_data;
-	unsigned level;
-};
-
-static struct sdcc_vreg sdcc_vreg_data[4];
+static struct regulator *sdcc_vreg_data[ARRAY_SIZE(sdcc_cfg_data)];
 
 static unsigned long vreg_sts, gpio_sts;
 
@@ -5656,37 +5456,36 @@
 static uint32_t msm_sdcc_setup_vreg(int dev_id, unsigned int enable)
 {
 	int rc = 0;
-	struct sdcc_vreg *curr;
+	struct regulator *curr = sdcc_vreg_data[dev_id - 1];
 	static int enabled_once[] = {0, 0, 0, 0};
 
-	curr = &sdcc_vreg_data[dev_id - 1];
-
-	if (!(test_bit(dev_id, &vreg_sts)^enable))
+	if (test_bit(dev_id, &vreg_sts) == enable)
 		return rc;
 
 	if (!enable || enabled_once[dev_id - 1])
 		return 0;
 
+	if (!curr)
+		return -ENODEV;
+
+	if (IS_ERR(curr))
+		return PTR_ERR(curr);
+
 	if (enable) {
 		set_bit(dev_id, &vreg_sts);
-		rc = vreg_set_level(curr->vreg_data, curr->level);
-		if (rc) {
-			printk(KERN_ERR "%s: vreg_set_level() = %d \n",
+
+		rc = regulator_enable(curr);
+		if (rc)
+			pr_err("%s: could not enable regulator: %d\n",
 					__func__, rc);
-		}
-		rc = vreg_enable(curr->vreg_data);
-		if (rc) {
-			printk(KERN_ERR "%s: vreg_enable() = %d \n",
-					__func__, rc);
-		}
 		enabled_once[dev_id - 1] = 1;
 	} else {
 		clear_bit(dev_id, &vreg_sts);
-		rc = vreg_disable(curr->vreg_data);
-		if (rc) {
-			printk(KERN_ERR "%s: vreg_disable() = %d \n",
+
+		rc = regulator_disable(curr);
+		if (rc)
+			pr_err("%s: could not disable regulator: %d\n",
 					__func__, rc);
-		}
 	}
 	return rc;
 }
@@ -5757,109 +5556,76 @@
 	return rc;
 }
 
-static int mbp_setup_rf_vregs(int state)
+static struct regulator_bulk_data mbp_regs_io[2];
+static struct regulator_bulk_data mbp_regs_rf[2];
+static struct regulator_bulk_data mbp_regs_adc[1];
+static struct regulator_bulk_data mbp_regs_core[1];
+
+static int mbp_init_regs(struct device *dev)
 {
-	struct vreg *vreg_rf = NULL;
-	struct vreg *vreg_rf_switch	= NULL;
+	struct regulator_bulk_data regs[] = {
+		/* Analog and I/O regs */
+		{ .supply = "gp4",  .min_uV = 2600000, .max_uV = 2600000 },
+		{ .supply = "s3",   .min_uV = 1800000, .max_uV = 1800000 },
+		/* RF regs */
+		{ .supply = "s2",   .min_uV = 1300000, .max_uV = 1300000 },
+		{ .supply = "rf",   .min_uV = 2600000, .max_uV = 2600000 },
+		/* ADC regs */
+		{ .supply = "s4",   .min_uV = 2200000, .max_uV = 2200000 },
+		/* Core regs */
+		{ .supply = "gp16", .min_uV = 1200000, .max_uV = 1200000 },
+	};
+
+	struct regulator_bulk_data *regptr = regs;
 	int rc;
 
-	vreg_rf = vreg_get(NULL, "s2");
-	if (IS_ERR(vreg_rf)) {
-		pr_err("%s: s2 vreg get failed (%ld)",
-				__func__, PTR_ERR(vreg_rf));
-		return -EFAULT;
-	}
-	vreg_rf_switch = vreg_get(NULL, "rf");
-	if (IS_ERR(vreg_rf_switch)) {
-		pr_err("%s: rf vreg get failed (%ld)",
-				__func__, PTR_ERR(vreg_rf_switch));
-		return -EFAULT;
+	rc = regulator_bulk_get(dev, ARRAY_SIZE(regs), regs);
+
+	if (rc) {
+		dev_err(dev, "%s: could not get regulators: %d\n",
+				__func__, rc);
+		goto out;
 	}
 
-	if (state) {
-		rc = vreg_set_level(vreg_rf, 1300);
-		if (rc) {
-			pr_err("%s: vreg s2 set level failed (%d)\n",
-					__func__, rc);
-			return rc;
-		}
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs), regs);
 
-		rc = vreg_enable(vreg_rf);
-		if (rc) {
-			printk(KERN_ERR "%s: vreg_enable(s2) = %d\n",
-					__func__, rc);
-		}
-
-		rc = vreg_set_level(vreg_rf_switch, 2600);
-		if (rc) {
-			pr_err("%s: vreg rf switch set level failed (%d)\n",
-					__func__, rc);
-			return rc;
-		}
-		rc = vreg_enable(vreg_rf_switch);
-		if (rc) {
-			printk(KERN_ERR "%s: vreg_enable(rf) = %d\n",
-					__func__, rc);
-		}
-	} else {
-		(void) vreg_disable(vreg_rf);
-		(void) vreg_disable(vreg_rf_switch);
+	if (rc) {
+		dev_err(dev, "%s: could not set voltages: %d\n",
+				__func__, rc);
+		goto reg_free;
 	}
+
+	memcpy(mbp_regs_io, regptr, sizeof(mbp_regs_io));
+	regptr += ARRAY_SIZE(mbp_regs_io);
+
+	memcpy(mbp_regs_rf, regptr, sizeof(mbp_regs_rf));
+	regptr += ARRAY_SIZE(mbp_regs_rf);
+
+	memcpy(mbp_regs_adc, regptr, sizeof(mbp_regs_adc));
+	regptr += ARRAY_SIZE(mbp_regs_adc);
+
+	memcpy(mbp_regs_core, regptr, sizeof(mbp_regs_core));
+
 	return 0;
+
+reg_free:
+	regulator_bulk_free(ARRAY_SIZE(regs), regs);
+out:
+	return rc;
+}
+
+static int mbp_setup_rf_vregs(int state)
+{
+	return state ?
+		regulator_bulk_enable(ARRAY_SIZE(mbp_regs_rf), mbp_regs_rf) :
+		regulator_bulk_disable(ARRAY_SIZE(mbp_regs_rf), mbp_regs_rf);
 }
 
 static int mbp_setup_vregs(int state)
 {
-	struct vreg *vreg_analog = NULL;
-	struct vreg *vreg_io = NULL;
-	int rc;
-
-	vreg_analog = vreg_get(NULL, "gp4");
-	if (IS_ERR(vreg_analog)) {
-		pr_err("%s: gp4 vreg get failed (%ld)",
-				__func__, PTR_ERR(vreg_analog));
-		return -EFAULT;
-	}
-	vreg_io = vreg_get(NULL, "s3");
-	if (IS_ERR(vreg_io)) {
-		pr_err("%s: s3 vreg get failed (%ld)",
-				__func__, PTR_ERR(vreg_io));
-		return -EFAULT;
-	}
-	if (state) {
-		rc = vreg_set_level(vreg_analog, 2600);
-		if (rc) {
-			pr_err("%s: vreg_set_level failed (%d)",
-					__func__, rc);
-		}
-		rc = vreg_enable(vreg_analog);
-		if (rc) {
-			pr_err("%s: analog vreg enable failed (%d)",
-					__func__, rc);
-		}
-		rc = vreg_set_level(vreg_io, 1800);
-		if (rc) {
-			pr_err("%s: vreg_set_level failed (%d)",
-					__func__, rc);
-		}
-		rc = vreg_enable(vreg_io);
-		if (rc) {
-			pr_err("%s: io vreg enable failed (%d)",
-					__func__, rc);
-		}
-	} else {
-		rc = vreg_disable(vreg_analog);
-		if (rc) {
-			pr_err("%s: analog vreg disable failed (%d)",
-					__func__, rc);
-		}
-		rc = vreg_disable(vreg_io);
-		if (rc) {
-			pr_err("%s: io vreg disable failed (%d)",
-					__func__, rc);
-		}
-	}
-	return rc;
+	return state ?
+		regulator_bulk_enable(ARRAY_SIZE(mbp_regs_io), mbp_regs_io) :
+		regulator_bulk_disable(ARRAY_SIZE(mbp_regs_io), mbp_regs_io);
 }
 
 static int mbp_set_tcxo_en(int enable)
@@ -5875,16 +5641,6 @@
 			__func__, enable ? "" : "de-");
 		return -EIO;
 	}
-	if (!enable) {
-		vreg_analog = vreg_get(NULL, "gp4");
-		if (IS_ERR(vreg_analog)) {
-			pr_err("%s: gp4 vreg get failed (%ld)",
-					__func__, PTR_ERR(vreg_analog));
-			return -EFAULT;
-		}
-
-		(void) vreg_disable(vreg_analog);
-	}
 	return rc;
 }
 
@@ -5898,28 +5654,20 @@
 
 static int mbp_set_core_voltage_en(int enable)
 {
-	int rc;
-	struct vreg *vreg_core1p2 = NULL;
+	static bool is_enabled;
+	int rc = 0;
 
-	vreg_core1p2 = vreg_get(NULL, "gp16");
-	if (IS_ERR(vreg_core1p2)) {
-		pr_err("%s: gp16 vreg get failed (%ld)",
-				__func__, PTR_ERR(vreg_core1p2));
-		return -EFAULT;
-	}
-	if (enable) {
-		rc = vreg_set_level(vreg_core1p2, 1200);
+	if (enable && !is_enabled) {
+		rc = regulator_bulk_enable(ARRAY_SIZE(mbp_regs_core),
+				mbp_regs_core);
 		if (rc) {
-			pr_err("%s: vreg_set_level failed (%d)",
+			pr_err("%s: could not enable regulators: %d\n",
 					__func__, rc);
+		} else {
+			is_enabled = true;
 		}
-		(void) vreg_enable(vreg_core1p2);
-
-		return 80;
-	} else {
-		gpio_set_value(85, 1);
-		return 0;
 	}
+
 	return rc;
 }
 
@@ -5950,34 +5698,9 @@
 
 static int mbp_setup_adc_vregs(int state)
 {
-	struct vreg *vreg_adc = NULL;
-	int rc;
-
-	vreg_adc = vreg_get(NULL, "s4");
-	if (IS_ERR(vreg_adc)) {
-		pr_err("%s: s4 vreg get failed (%ld)",
-				__func__, PTR_ERR(vreg_adc));
-		return -EFAULT;
-	}
-	if (state) {
-		rc = vreg_set_level(vreg_adc, 2200);
-		if (rc) {
-			pr_err("%s: vreg_set_level failed (%d)",
-					__func__, rc);
-		}
-		rc = vreg_enable(vreg_adc);
-		if (rc) {
-			pr_err("%s: enable vreg adc failed (%d)",
-					__func__, rc);
-		}
-	} else {
-		rc = vreg_disable(vreg_adc);
-		if (rc) {
-			pr_err("%s: disable vreg adc failed (%d)",
-					__func__, rc);
-		}
-	}
-	return rc;
+	return state ?
+		regulator_bulk_enable(ARRAY_SIZE(mbp_regs_adc), mbp_regs_adc) :
+		regulator_bulk_disable(ARRAY_SIZE(mbp_regs_adc), mbp_regs_adc);
 }
 
 static int mbp_power_up(void)
@@ -6042,14 +5765,6 @@
 static int mbp_power_down(void)
 {
 	int rc;
-	struct vreg *vreg_adc = NULL;
-
-	vreg_adc = vreg_get(NULL, "s4");
-	if (IS_ERR(vreg_adc)) {
-		pr_err("%s: s4 vreg get failed (%ld)",
-				__func__, PTR_ERR(vreg_adc));
-		return -EFAULT;
-	}
 
 	mbp_set_reset(MBP_ON);
 	pr_debug("%s: mbp_set_reset(MBP_ON) done\n", __func__);
@@ -6079,13 +5794,16 @@
 		goto exit;
 	pr_debug("%s: mbp_set_core_voltage_en(MBP_OFF) done\n", __func__);
 
-	gpio_set_value(85, 1);
-
 	rc = mbp_set_tcxo_en(MBP_OFF);
 	if (rc)
 		goto exit;
 	pr_debug("%s: mbp_set_tcxo_en(MBP_OFF) done\n", __func__);
 
+	rc = mbp_setup_vregs(MBP_OFF);
+	if (rc)
+		goto exit;
+	pr_debug("%s: mbp_setup_vregs(MBP_OFF) done\n", __func__);
+
 	rc = mbp_config_gpios_pre_init(MBP_OFF);
 	if (rc)
 		goto exit;
@@ -6147,6 +5865,12 @@
 		goto out;
 	}
 	if (!mbp_power_init_done) {
+		rc = mbp_init_regs(dv);
+		if (rc) {
+			dev_err(dv, "%s: regulator init failed: %d\n",
+					__func__, rc);
+			goto out;
+		}
 		mbp_setup_power(dv, 1);
 		mbp_setup_power(dv, 0);
 		mbp_power_init_done = 1;
@@ -6285,18 +6009,32 @@
 #endif
 
 #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
-static void msm_sdc1_lvlshft_enable(void)
+static int msm_sdc1_lvlshft_enable(void)
 {
+	static struct regulator *ldo5;
 	int rc;
 
 	/* Enable LDO5, an input to the FET that powers slot 1 */
-	rc = vreg_set_level(vreg_mmc, 2850);
-	if (rc)
-		printk(KERN_ERR "%s: vreg_set_level() = %d \n",	__func__, rc);
 
-	rc = vreg_enable(vreg_mmc);
-	if (rc)
-		printk(KERN_ERR "%s: vreg_enable() = %d \n", __func__, rc);
+	ldo5 = regulator_get(NULL, "ldo5");
+
+	if (IS_ERR(ldo5)) {
+		rc = PTR_ERR(ldo5);
+		pr_err("%s: could not get ldo5: %d\n", __func__, rc);
+		goto out;
+	}
+
+	rc = regulator_set_voltage(ldo5, 2850000, 2850000);
+	if (rc) {
+		pr_err("%s: could not set ldo5 voltage: %d\n", __func__, rc);
+		goto ldo5_free;
+	}
+
+	rc = regulator_enable(ldo5);
+	if (rc) {
+		pr_err("%s: could not enable ldo5: %d\n", __func__, rc);
+		goto ldo5_free;
+	}
 
 	/* Enable GPIO 35, to turn on the FET that powers slot 1 */
 	rc = msm_gpios_request_enable(sdc1_lvlshft_cfg_data,
@@ -6308,35 +6046,72 @@
 				1);
 	if (rc)
 		printk(KERN_ERR "%s: Failed to turn on GPIO 35\n", __func__);
+
+	return 0;
+
+ldo5_free:
+	regulator_put(ldo5);
+out:
+	ldo5 = NULL;
+	return rc;
 }
 #endif
 
+static int mmc_regulator_init(int sdcc_no, const char *supply, int uV)
+{
+	int rc;
+
+	BUG_ON(sdcc_no < 1 || sdcc_no > 4);
+
+	sdcc_no--;
+
+	sdcc_vreg_data[sdcc_no] = regulator_get(NULL, supply);
+
+	if (IS_ERR(sdcc_vreg_data[sdcc_no])) {
+		rc = PTR_ERR(sdcc_vreg_data[sdcc_no]);
+		pr_err("%s: could not get regulator \"%s\": %d\n",
+				__func__, supply, rc);
+		goto out;
+	}
+
+	rc = regulator_set_voltage(sdcc_vreg_data[sdcc_no], uV, uV);
+
+	if (rc) {
+		pr_err("%s: could not set voltage for \"%s\" to %d uV: %d\n",
+				__func__, supply, uV, rc);
+		goto reg_free;
+	}
+
+	return rc;
+
+reg_free:
+	regulator_put(sdcc_vreg_data[sdcc_no]);
+out:
+	sdcc_vreg_data[sdcc_no] = NULL;
+	return rc;
+}
+
 static void __init msm7x30_init_mmc(void)
 {
-	vreg_s3 = vreg_get(NULL, "s3");
-	if (IS_ERR(vreg_s3)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
-		       __func__, PTR_ERR(vreg_s3));
-		return;
-	}
-
-	vreg_mmc = vreg_get(NULL, "mmc");
-	if (IS_ERR(vreg_mmc)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
-		       __func__, PTR_ERR(vreg_mmc));
-		return;
-	}
-
 #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
+	if (mmc_regulator_init(1, "s3", 1800000))
+		goto out1;
+
 	if (machine_is_msm7x30_fluid()) {
 		msm7x30_sdc1_data.ocr_mask =  MMC_VDD_27_28 | MMC_VDD_28_29;
-		msm_sdc1_lvlshft_enable();
+		if (msm_sdc1_lvlshft_enable()) {
+			pr_err("%s: could not enable level shift\n");
+			goto out1;
+		}
 	}
-	sdcc_vreg_data[0].vreg_data = vreg_s3;
-	sdcc_vreg_data[0].level = 1800;
+
 	msm_add_sdcc(1, &msm7x30_sdc1_data);
+out1:
 #endif
 #ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
+	if (mmc_regulator_init(2, "s3", 1800000))
+		goto out2;
+
 	if (machine_is_msm8x55_svlte_surf())
 		msm7x30_sdc2_data.msmsdcc_fmax =  24576000;
 	if (machine_is_msm8x55_svlte_surf() ||
@@ -6344,19 +6119,22 @@
 		msm7x30_sdc2_data.sdiowakeup_irq = MSM_GPIO_TO_INT(68);
 		msm7x30_sdc2_data.is_sdio_al_client = 1;
 	}
-	sdcc_vreg_data[1].vreg_data = vreg_s3;
-	sdcc_vreg_data[1].level = 1800;
+
 	msm_add_sdcc(2, &msm7x30_sdc2_data);
+out2:
 #endif
 #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
-	sdcc_vreg_data[2].vreg_data = vreg_s3;
-	sdcc_vreg_data[2].level = 1800;
+	if (mmc_regulator_init(3, "s3", 1800000))
+		goto out3;
+
 	msm_sdcc_setup_gpio(3, 1);
 	msm_add_sdcc(3, &msm7x30_sdc3_data);
+out3:
 #endif
 #ifdef CONFIG_MMC_MSM_SDC4_SUPPORT
-	sdcc_vreg_data[3].vreg_data = vreg_mmc;
-	sdcc_vreg_data[3].level = 2850;
+	if (mmc_regulator_init(4, "mmc", 2850000))
+		return;
+
 	msm_add_sdcc(4, &msm7x30_sdc4_data);
 #endif
 
@@ -6468,68 +6246,50 @@
 	"tsc2007_irq" },
 };
 
-static struct vreg *vreg_tsc_s3;
-static struct vreg *vreg_tsc_s2;
+static struct regulator_bulk_data tsc2007_regs[] = {
+	{ .supply = "s3", .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "s2", .min_uV = 1300000, .max_uV = 1300000 },
+};
 
 static int tsc2007_init(void)
 {
 	int rc;
 
-	vreg_tsc_s3 = vreg_get(NULL, "s3");
-	if (IS_ERR(vreg_tsc_s3)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
-		       __func__, PTR_ERR(vreg_tsc_s3));
-		return -ENODEV;
-	}
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
 
-	rc = vreg_set_level(vreg_tsc_s3, 1800);
 	if (rc) {
-		pr_err("%s: vreg_set_level failed \n", __func__);
-		goto fail_vreg_set_level;
+		pr_err("%s: could not get regulators: %d\n", __func__, rc);
+		goto out;
 	}
 
-	rc = vreg_enable(vreg_tsc_s3);
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
+
 	if (rc) {
-		pr_err("%s: vreg_enable failed \n", __func__);
-		goto fail_vreg_set_level;
+		pr_err("%s: could not set voltages: %d\n", __func__, rc);
+		goto reg_free;
 	}
 
-	vreg_tsc_s2 = vreg_get(NULL, "s2");
-	if (IS_ERR(vreg_tsc_s2)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
-		       __func__, PTR_ERR(vreg_tsc_s2));
-		goto fail_vreg_get;
-	}
+	rc = regulator_bulk_enable(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
 
-	rc = vreg_set_level(vreg_tsc_s2, 1300);
 	if (rc) {
-		pr_err("%s: vreg_set_level failed \n", __func__);
-		goto fail_vreg_s2_level;
-	}
-
-	rc = vreg_enable(vreg_tsc_s2);
-	if (rc) {
-		pr_err("%s: vreg_enable failed \n", __func__);
-		goto fail_vreg_s2_level;
+		pr_err("%s: could not enable regulators: %d\n", __func__, rc);
+		goto reg_free;
 	}
 
 	rc = msm_gpios_request_enable(tsc2007_config_data,
 			ARRAY_SIZE(tsc2007_config_data));
 	if (rc) {
 		pr_err("%s: Unable to request gpios\n", __func__);
-		goto fail_gpio_req;
+		goto reg_disable;
 	}
 
 	return 0;
 
-fail_gpio_req:
-	vreg_disable(vreg_tsc_s2);
-fail_vreg_s2_level:
-	vreg_put(vreg_tsc_s2);
-fail_vreg_get:
-	vreg_disable(vreg_tsc_s3);
-fail_vreg_set_level:
-	vreg_put(vreg_tsc_s3);
+reg_disable:
+	regulator_bulk_disable(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
+reg_free:
+	regulator_bulk_free(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
+out:
 	return rc;
 }
 
@@ -6549,10 +6309,9 @@
 
 static void tsc2007_exit(void)
 {
-	vreg_disable(vreg_tsc_s3);
-	vreg_put(vreg_tsc_s3);
-	vreg_disable(vreg_tsc_s2);
-	vreg_put(vreg_tsc_s2);
+
+	regulator_bulk_disable(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
+	regulator_bulk_free(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
 
 	msm_gpios_disable_free(tsc2007_config_data,
 		ARRAY_SIZE(tsc2007_config_data));
@@ -6562,35 +6321,20 @@
 {
 	int rc;
 
-	if (enable == false) {
-		rc = vreg_enable(vreg_tsc_s2);
-		if (rc) {
-			pr_err("%s: vreg_enable failed\n", __func__);
-			return rc;
-		}
-		rc = vreg_enable(vreg_tsc_s3);
-		if (rc) {
-			pr_err("%s: vreg_enable failed\n", __func__);
-			vreg_disable(vreg_tsc_s2);
-			return rc;
-		}
-		/* Voltage settling delay */
-		msleep(20);
-	} else {
-		rc = vreg_disable(vreg_tsc_s2);
-		if (rc) {
-			pr_err("%s: vreg_disable failed\n", __func__);
-			return rc;
-		}
-		rc = vreg_disable(vreg_tsc_s3);
-		if (rc) {
-			pr_err("%s: vreg_disable failed\n", __func__);
-			vreg_enable(vreg_tsc_s2);
-			return rc;
-		}
+	rc = (enable == false) ?
+		regulator_bulk_enable(ARRAY_SIZE(tsc2007_regs), tsc2007_regs) :
+		regulator_bulk_disable(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
+
+	if (rc) {
+		pr_err("%s: could not %sable regulators: %d\n",
+				__func__, enable ? "dis" : "en", rc);
+		return rc;
 	}
 
-	return rc;
+	if (enable == false)
+		msleep(20);
+
+	return 0;
 }
 
 static struct tsc2007_platform_data tsc2007_ts_data = {
@@ -6617,36 +6361,23 @@
 };
 #endif
 
-static const char *vregs_isa1200_name[] = {
-	"gp7",
-	"gp10",
+static struct regulator_bulk_data regs_isa1200[] = {
+	{ .supply = "gp7",  .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "gp10", .min_uV = 2600000, .max_uV = 2600000 },
 };
 
-static const int vregs_isa1200_val[] = {
-	1800,
-	2600,
-};
-static struct vreg *vregs_isa1200[ARRAY_SIZE(vregs_isa1200_name)];
-
 static int isa1200_power(int vreg_on)
 {
-	int i, rc = 0;
+	int rc = 0;
 
-	for (i = 0; i < ARRAY_SIZE(vregs_isa1200_name); i++) {
-		if (!vregs_isa1200[i]) {
-			pr_err("%s: vreg_get %s failed (%d)\n",
-				__func__, vregs_isa1200_name[i], rc);
-			goto vreg_fail;
-		}
+	rc = vreg_on ?
+		regulator_bulk_enable(ARRAY_SIZE(regs_isa1200), regs_isa1200) :
+		regulator_bulk_disable(ARRAY_SIZE(regs_isa1200), regs_isa1200);
 
-		rc = vreg_on ? vreg_enable(vregs_isa1200[i]) :
-			  vreg_disable(vregs_isa1200[i]);
-		if (rc < 0) {
-			pr_err("%s: vreg %s %s failed (%d)\n",
-				__func__, vregs_isa1200_name[i],
-			       vreg_on ? "enable" : "disable", rc);
-			goto vreg_fail;
-		}
+	if (rc) {
+		pr_err("%s: could not %sable regulators: %d\n",
+				__func__, vreg_on ? "en" : "dis", rc);
+		goto out;
 	}
 
 	/* vote for DO buffer */
@@ -6661,33 +6392,34 @@
 	return 0;
 
 vreg_fail:
-	while (i)
-		vreg_disable(vregs_isa1200[--i]);
+	if (vreg_on)
+		regulator_bulk_disable(ARRAY_SIZE(regs_isa1200), regs_isa1200);
+	else
+		regulator_bulk_enable(ARRAY_SIZE(regs_isa1200), regs_isa1200);
+out:
 	return rc;
 }
 
 static int isa1200_dev_setup(bool enable)
 {
-	int i, rc;
+	int rc;
 
 	if (enable == true) {
-		for (i = 0; i < ARRAY_SIZE(vregs_isa1200_name); i++) {
-			vregs_isa1200[i] = vreg_get(NULL,
-						vregs_isa1200_name[i]);
-			if (IS_ERR(vregs_isa1200[i])) {
-				pr_err("%s: vreg get %s failed (%ld)\n",
-					__func__, vregs_isa1200_name[i],
-					PTR_ERR(vregs_isa1200[i]));
-				rc = PTR_ERR(vregs_isa1200[i]);
-				goto vreg_get_fail;
-			}
-			rc = vreg_set_level(vregs_isa1200[i],
-					vregs_isa1200_val[i]);
-			if (rc) {
-				pr_err("%s: vreg_set_level() = %d\n",
+		rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_isa1200),
+				regs_isa1200);
+
+		if (rc) {
+			pr_err("%s: could not get regulators: %d\n",
 					__func__, rc);
-				goto vreg_get_fail;
-			}
+			goto out;
+		}
+
+		rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_isa1200),
+				regs_isa1200);
+		if (rc) {
+			pr_err("%s: could not set voltages: %d\n",
+					__func__, rc);
+			goto reg_free;
 		}
 
 		rc = gpio_tlmm_config(GPIO_CFG(HAP_LVL_SHFT_MSM_GPIO, 0,
@@ -6696,28 +6428,27 @@
 		if (rc) {
 			pr_err("%s: Could not configure gpio %d\n",
 					__func__, HAP_LVL_SHFT_MSM_GPIO);
-			goto vreg_get_fail;
+			goto reg_free;
 		}
 
 		rc = gpio_request(HAP_LVL_SHFT_MSM_GPIO, "haptics_shft_lvl_oe");
 		if (rc) {
 			pr_err("%s: unable to request gpio %d (%d)\n",
 					__func__, HAP_LVL_SHFT_MSM_GPIO, rc);
-			goto vreg_get_fail;
+			goto reg_free;
 		}
 
 		gpio_set_value(HAP_LVL_SHFT_MSM_GPIO, 1);
 	} else {
-		for (i = 0; i < ARRAY_SIZE(vregs_isa1200_name); i++)
-			vreg_put(vregs_isa1200[i]);
-
+		regulator_bulk_free(ARRAY_SIZE(regs_isa1200), regs_isa1200);
 		gpio_free(HAP_LVL_SHFT_MSM_GPIO);
 	}
 
 	return 0;
-vreg_get_fail:
-	while (i)
-		vreg_put(vregs_isa1200[--i]);
+
+reg_free:
+	regulator_bulk_free(ARRAY_SIZE(regs_isa1200), regs_isa1200);
+out:
 	return rc;
 }
 static struct isa1200_platform_data isa1200_1_pdata = {
@@ -6777,69 +6508,48 @@
 	}
 };
 
-static const char *vregs_tma300_name[] = {
-	"gp6",
-	"gp7",
+static struct regulator_bulk_data regs_tma300[] = {
+	{ .supply = "gp6", .min_uV = 3050000, .max_uV = 3100000 },
+	{ .supply = "gp7", .min_uV = 1800000, .max_uV = 1800000 },
 };
 
-static const int vregs_tma300_val[] = {
-	3050,
-	1800,
-};
-static struct vreg *vregs_tma300[ARRAY_SIZE(vregs_tma300_name)];
-
 static int tma300_power(int vreg_on)
 {
-	int i, rc = -EINVAL;
+	int rc;
 
-	for (i = 0; i < ARRAY_SIZE(vregs_tma300_name); i++) {
-		/* Never disable gp6 for fluid as lcd has a problem with it */
-		if (!i && !vreg_on)
-			continue;
-		if (!vregs_tma300[i]) {
-			printk(KERN_ERR "%s: vreg_get %s failed (%d)\n",
-				__func__, vregs_tma300_name[i], rc);
-			return rc;
-		}
+	rc = vreg_on ?
+		regulator_bulk_enable(ARRAY_SIZE(regs_tma300), regs_tma300) :
+		regulator_bulk_disable(ARRAY_SIZE(regs_tma300), regs_tma300);
 
-		rc = vreg_on ? vreg_enable(vregs_tma300[i]) :
-			  vreg_disable(vregs_tma300[i]);
-		if (rc < 0) {
-			printk(KERN_ERR "%s: vreg %s %s failed (%d)\n",
-				__func__, vregs_tma300_name[i],
-			       vreg_on ? "enable" : "disable", rc);
-			return rc;
-		}
-	}
-
-	return 0;
+	if (rc)
+		pr_err("%s: could not %sable regulators: %d\n",
+				__func__, vreg_on ? "en" : "dis", rc);
+	return rc;
 }
 
 #define TS_GPIO_IRQ 150
 
 static int tma300_dev_setup(bool enable)
 {
-	int i, rc;
+	int rc;
 
 	if (enable) {
-		/* get voltage sources */
-		for (i = 0; i < ARRAY_SIZE(vregs_tma300_name); i++) {
-			vregs_tma300[i] = vreg_get(NULL, vregs_tma300_name[i]);
-			if (IS_ERR(vregs_tma300[i])) {
-				pr_err("%s: vreg get %s failed (%ld)\n",
-					__func__, vregs_tma300_name[i],
-					PTR_ERR(vregs_tma300[i]));
-				rc = PTR_ERR(vregs_tma300[i]);
-				goto vreg_get_fail;
-			}
-			rc = vreg_set_level(vregs_tma300[i],
-					vregs_tma300_val[i]);
-			if (rc) {
-				pr_err("%s: vreg_set_level() = %d\n",
+		rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_tma300),
+				regs_tma300);
+
+		if (rc) {
+			pr_err("%s: could not get regulators: %d\n",
 					__func__, rc);
-				i++;
-				goto vreg_get_fail;
-			}
+			goto out;
+		}
+
+		rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_tma300),
+				regs_tma300);
+
+		if (rc) {
+			pr_err("%s: could not set voltages: %d\n",
+					__func__, rc);
+			goto reg_free;
 		}
 
 		/* enable interrupt gpio */
@@ -6848,7 +6558,7 @@
 		if (rc) {
 			pr_err("%s: Could not configure gpio %d\n",
 					__func__, TS_GPIO_IRQ);
-			goto vreg_get_fail;
+			goto reg_free;
 		}
 
 		/* virtual keys */
@@ -6856,23 +6566,20 @@
 		properties_kobj = kobject_create_and_add("board_properties",
 					NULL);
 		if (!properties_kobj) {
-			pr_err("%s: failed to create a kobject"
-					"for board_properites\n", __func__);
+			pr_err("%s: failed to create a kobject "
+					"for board_properties\n", __func__);
 			rc = -ENOMEM;
-			goto vreg_get_fail;
+			goto reg_free;
 		}
 		rc = sysfs_create_group(properties_kobj,
 				&tma300_properties_attr_group);
 		if (rc) {
 			pr_err("%s: failed to create a sysfs entry %s\n",
 					__func__, tma300_vkeys_attr.attr.name);
-			kobject_put(properties_kobj);
-			goto vreg_get_fail;
+			goto kobj_free;
 		}
 	} else {
-		/* put voltage sources */
-		for (i = 0; i < ARRAY_SIZE(vregs_tma300_name); i++)
-			vreg_put(vregs_tma300[i]);
+		regulator_bulk_free(ARRAY_SIZE(regs_tma300), regs_tma300);
 		/* destroy virtual keys */
 		if (properties_kobj) {
 			sysfs_remove_group(properties_kobj,
@@ -6882,9 +6589,12 @@
 	}
 	return 0;
 
-vreg_get_fail:
-	while (i)
-		vreg_put(vregs_tma300[--i]);
+kobj_free:
+	kobject_put(properties_kobj);
+	properties_kobj = NULL;
+reg_free:
+	regulator_bulk_free(ARRAY_SIZE(regs_tma300), regs_tma300);
+out:
 	return rc;
 }
 
@@ -6995,6 +6705,9 @@
 			ARRAY_SIZE(lcdc_toshiba_spi_board_info));
 #endif
 
+	atv_dac_power_init();
+	sensors_ldo_init();
+	hdmi_init_regs();
 	msm_fb_add_devices();
 	msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
 	BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_RESET_VECTOR,
@@ -7005,6 +6718,7 @@
 	msm7x30_init_marimba();
 #ifdef CONFIG_MSM7KV2_AUDIO
 	snddev_poweramp_gpio_init();
+	snddev_hsed_voltage_init();
 	aux_pcm_gpio_init();
 #endif
 
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index 22767cec..e1e922e 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -76,6 +76,7 @@
 
 #include <linux/ion.h>
 #include <mach/ion.h>
+#include <mach/mdm2.h>
 
 #include "timer.h"
 #include "devices.h"
@@ -92,6 +93,11 @@
 #include "pm-boot.h"
 #include "msm_watchdog.h"
 
+#define PLATFORM_IS_CHARM25() \
+	(machine_is_msm8960_cdp() && \
+		(socinfo_get_platform_subtype() == 1) \
+	)
+
 static struct platform_device msm_fm_platform_init = {
 	.name = "iris_fm",
 	.id   = -1,
@@ -744,6 +750,7 @@
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_DOWN,
+	.dir = GPIOMUX_OUT_LOW,
 };
 
 static struct gpiomux_setting hsic_hub_act_cfg = {
@@ -2662,6 +2669,138 @@
 };
 #endif
 
+#define MDM2AP_ERRFATAL			70
+#define AP2MDM_ERRFATAL			95
+#define MDM2AP_STATUS			69
+#define AP2MDM_STATUS			94
+#define AP2MDM_PMIC_RESET_N		80
+#define AP2MDM_KPDPWR_N			81
+
+static struct gpiomux_setting ap2mdm_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting mdm2ap_status_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting mdm2ap_errfatal_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_16MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting ap2mdm_kpdpwr_n_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct msm_gpiomux_config mdm_configs[] __initdata = {
+	/* AP2MDM_STATUS */
+	{
+		.gpio = AP2MDM_STATUS,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
+		}
+	},
+	/* MDM2AP_STATUS */
+	{
+		.gpio = MDM2AP_STATUS,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &mdm2ap_status_cfg,
+		}
+	},
+	/* MDM2AP_ERRFATAL */
+	{
+		.gpio = MDM2AP_ERRFATAL,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &mdm2ap_errfatal_cfg,
+		}
+	},
+	/* AP2MDM_ERRFATAL */
+	{
+		.gpio = AP2MDM_ERRFATAL,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
+		}
+	},
+	/* AP2MDM_KPDPWR_N */
+	{
+		.gpio = AP2MDM_KPDPWR_N,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ap2mdm_kpdpwr_n_cfg,
+		}
+	},
+	/* AP2MDM_PMIC_RESET_N */
+	{
+		.gpio = AP2MDM_PMIC_RESET_N,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ap2mdm_kpdpwr_n_cfg,
+		}
+	}
+};
+
+static struct resource mdm_resources[] = {
+	{
+		.start	= MDM2AP_ERRFATAL,
+		.end	= MDM2AP_ERRFATAL,
+		.name	= "MDM2AP_ERRFATAL",
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.start	= AP2MDM_ERRFATAL,
+		.end	= AP2MDM_ERRFATAL,
+		.name	= "AP2MDM_ERRFATAL",
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.start	= MDM2AP_STATUS,
+		.end	= MDM2AP_STATUS,
+		.name	= "MDM2AP_STATUS",
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.start	= AP2MDM_STATUS,
+		.end	= AP2MDM_STATUS,
+		.name	= "AP2MDM_STATUS",
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.start	= AP2MDM_PMIC_RESET_N,
+		.end	= AP2MDM_PMIC_RESET_N,
+		.name	= "AP2MDM_PMIC_RESET_N",
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.start	= AP2MDM_KPDPWR_N,
+		.end	= AP2MDM_KPDPWR_N,
+		.name	= "AP2MDM_KPDPWR_N",
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+static struct mdm_platform_data mdm_platform_data = {
+	.mdm_version = "2.5",
+};
+
+struct platform_device mdm_device = {
+	.name		= "mdm2_modem",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(mdm_resources),
+	.resource	= mdm_resources,
+	.dev		= {
+		.platform_data = &mdm_platform_data,
+	},
+};
+
+static struct platform_device *mdm_devices[] __initdata = {
+	&mdm_device,
+};
 
 static int __init gpiomux_init(void)
 {
@@ -2709,6 +2848,11 @@
 		machine_is_msm8960_liquid() || machine_is_msm8960_cdp())
 		msm_gpiomux_install(hap_lvl_shft_config,
 			ARRAY_SIZE(hap_lvl_shft_config));
+
+	if (PLATFORM_IS_CHARM25())
+		msm_gpiomux_install(mdm_configs,
+			ARRAY_SIZE(mdm_configs));
+
 	return 0;
 }
 
@@ -3921,6 +4065,8 @@
 #endif
 	&msm_rpm_log_device,
 	&msm_rpm_stat_device,
+	&msm_device_tz_log,
+
 #ifdef CONFIG_MSM_QDSS
 	&msm_etb_device,
 	&msm_tpiu_device,
@@ -4837,6 +4983,9 @@
 				msm_pm_data);
 	change_memory_power = &msm8960_change_memory_power;
 	BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_TZ, NULL));
+
+	if (PLATFORM_IS_CHARM25())
+		platform_add_devices(mdm_devices, ARRAY_SIZE(mdm_devices));
 }
 
 MACHINE_START(MSM8960_SIM, "QCT MSM8960 SIMULATOR")
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 8f733a9..0d2bd82 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -1085,8 +1085,8 @@
 		return -ENOTSUPP;
 	}
 
-	if ((machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) &&
-			!pmic_id_notif_supported) {
+	if ((machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa() ||
+			machine_is_msm8x60_ffa()) && !pmic_id_notif_supported) {
 		pr_debug("%s: USB_ID is not routed to PMIC"
 			"on V2 ffa\n", __func__);
 		return -ENOTSUPP;
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 95b69e6..85de532 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -26,6 +26,7 @@
 #include <linux/power_supply.h>
 #include <linux/input/rmi_platformdata.h>
 #include <linux/input/rmi_i2c.h>
+#include <linux/regulator/consumer.h>
 #include <asm/mach/mmc.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -52,6 +53,7 @@
 #include "pm.h"
 #include "timer.h"
 #include "pm-boot.h"
+#include "board-msm7x27a-regulator.h"
 
 #define PMEM_KERNEL_EBI1_SIZE	0x3A000
 #define MSM_PMEM_AUDIO_SIZE	0x5B000
@@ -2505,10 +2507,27 @@
 	},
 };
 
+static struct platform_device msm_proccomm_regulator_dev = {
+	.name   = PROCCOMM_REGULATOR_DEV_NAME,
+	.id     = -1,
+	.dev    = {
+		.platform_data = &msm7x27a_proccomm_regulator_data
+	}
+};
+
+static void __init msm7627a_init_regulators(void)
+{
+	int rc = platform_device_register(&msm_proccomm_regulator_dev);
+	if (rc)
+		pr_err("%s: could not register regulator device: %d\n",
+				__func__, rc);
+}
+
 #define UART1DM_RX_GPIO		45
 static void __init msm_qrd1_init(void)
 {
 	msm7x2x_misc_init();
+	msm7627a_init_regulators();
 	msm_device_i2c_init();
 	msm7627a_init_mmc();
 
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index af48067..0a300ad 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -182,6 +182,22 @@
 	},
 };
 
+#define SHARED_IMEM_TZ_BASE 0x2a03f720
+static struct resource tzlog_resources[] = {
+	{
+		.start = SHARED_IMEM_TZ_BASE,
+		.end = SHARED_IMEM_TZ_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device msm_device_tz_log = {
+	.name		= "tz_log",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(tzlog_resources),
+	.resource	= tzlog_resources,
+};
+
 static struct resource resources_uart_gsbi2[] = {
 	{
 		.start	= MSM8960_GSBI2_UARTDM_IRQ,
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 88fd169..012eb85 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -145,6 +145,31 @@
 	},
 };
 
+static struct resource resources_hsusb_host[] = {
+	{
+		.start  = MSM9615_HSUSB_PHYS,
+		.end    = MSM9615_HSUSB_PHYS + MSM9615_HSUSB_PHYS - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.start  = USB1_HS_IRQ,
+		.end    = USB1_HS_IRQ,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static u64 dma_mask = DMA_BIT_MASK(32);
+struct platform_device msm_device_hsusb_host = {
+	.name           = "msm_hsusb_host",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(resources_hsusb_host),
+	.resource       = resources_hsusb_host,
+	.dev            = {
+		.dma_mask               = &dma_mask,
+		.coherent_dma_mask      = 0xffffffff,
+	},
+};
+
 static struct resource resources_uart_gsbi4[] = {
 	{
 		.start	= GSBI4_UARTDM_IRQ,
diff --git a/arch/arm/mach-msm/devices-msm8x60.h b/arch/arm/mach-msm/devices-msm8x60.h
index 1d5dee1..a2f6a1f 100644
--- a/arch/arm/mach-msm/devices-msm8x60.h
+++ b/arch/arm/mach-msm/devices-msm8x60.h
@@ -58,7 +58,7 @@
 extern struct platform_device msm_device_vidc;
 
 extern struct platform_device msm_charm_modem;
-
+extern struct platform_device msm_device_tz_log;
 #ifdef CONFIG_HW_RANDOM_MSM
 extern struct platform_device msm_device_rng;
 #endif
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index aab93f4..8f57f88 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -115,7 +115,8 @@
 #ifdef CONFIG_ARCH_MSM_KRAIT
 	ldr	r0, =SCM_SVC_BOOT
 	ldr	r1, =SCM_CMD_TERMINATE_PC
-	ldr	r2, =0
+	ldr	r2, =msm_pm_flush_l2_flag
+	ldr	r2, [r2]
 	bl	scm_call_atomic1
 #else
 	wfi
diff --git a/arch/arm/mach-msm/include/mach/barriers.h b/arch/arm/mach-msm/include/mach/barriers.h
index 919186b..2d4792c 100644
--- a/arch/arm/mach-msm/include/mach/barriers.h
+++ b/arch/arm/mach-msm/include/mach/barriers.h
@@ -10,6 +10,8 @@
  * GNU General Public License for more details.
  *
  */
+#include <mach/memory.h>
+
 #define mb() do \
 	{ \
 		dsb();\
diff --git a/arch/arm/mach-msm/include/mach/mdm2.h b/arch/arm/mach-msm/include/mach/mdm2.h
new file mode 100644
index 0000000..acfa38a
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/mdm2.h
@@ -0,0 +1,21 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ARCH_ARM_MACH_MSM_MDM2_H
+#define _ARCH_ARM_MACH_MSM_MDM2_H
+
+struct mdm_platform_data {
+	char *mdm_version;
+};
+
+#endif
+
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
new file mode 100644
index 0000000..0737a81
--- /dev/null
+++ b/arch/arm/mach-msm/mdm2.c
@@ -0,0 +1,176 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/ioctl.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/debugfs.h>
+#include <linux/completion.h>
+#include <linux/workqueue.h>
+#include <linux/clk.h>
+#include <linux/mfd/pmic8058.h>
+#include <asm/mach-types.h>
+#include <asm/uaccess.h>
+#include <mach/mdm2.h>
+#include <mach/restart.h>
+#include <mach/subsystem_notif.h>
+#include <mach/subsystem_restart.h>
+#include <linux/msm_charm.h>
+#include "msm_watchdog.h"
+#include "devices.h"
+#include "clock.h"
+#include "mdm_private.h"
+
+#define MDM_MODEM_TIMEOUT	6000
+#define MDM_HOLD_TIME		4000
+#define MDM_MODEM_DELTA		100
+#define IFLINE_UP			1
+#define IFLINE_DOWN			0
+
+static int mdm_debug_on;
+static int ifline_status = IFLINE_UP;
+static struct mdm_callbacks mdm_cb;
+
+#define MDM_DBG(...)	do { if (mdm_debug_on) \
+					pr_info(__VA_ARGS__); \
+			} while (0);
+
+static void power_on_mdm(struct mdm_modem_drv *mdm_drv)
+{
+	/* Remove hsic driver before powering on the modem. */
+	if (ifline_status == IFLINE_UP) {
+		MDM_DBG("%s: Removing hsic device\n", __func__);
+		platform_device_del(&msm_device_hsic_host);
+		ifline_status = IFLINE_DOWN;
+	}
+
+	/* Pull both ERR_FATAL and RESET low */
+	MDM_DBG("Pulling PWR and RESET gpio's low\n");
+	gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 0);
+	gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 0);
+	/* Wait for them to settle. */
+	usleep(1000);
+
+	/* Deassert RESET first and wait for ir to settle. */
+	MDM_DBG("%s: Pulling RESET gpio high\n", __func__);
+	gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 1);
+	usleep(1000);
+
+	/* Pull PWR gpio high and wait for it to settle. */
+	MDM_DBG("%s: Powering on mdm modem\n", __func__);
+	gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 1);
+	usleep(1000);
+
+	/* Add back hsic device after modem power up */
+	MDM_DBG("%s: Adding hsic device\n", __func__);
+	platform_device_add(&msm_device_hsic_host);
+	ifline_status = IFLINE_UP;
+
+	msleep(200);
+}
+
+static void power_down_mdm(struct mdm_modem_drv *mdm_drv)
+{
+	int i;
+
+	for (i = MDM_MODEM_TIMEOUT; i > 0; i -= MDM_MODEM_DELTA) {
+		pet_watchdog();
+		msleep(MDM_MODEM_DELTA);
+		if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
+			break;
+	}
+
+	if (i <= 0) {
+		pr_err("%s: MDM2AP_STATUS never went low.\n",
+			 __func__);
+		gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 0);
+
+		for (i = MDM_HOLD_TIME; i > 0; i -= MDM_MODEM_DELTA) {
+			pet_watchdog();
+			msleep(MDM_MODEM_DELTA);
+		}
+	}
+	/* Also remove the hsic device on 9k power down. */
+	MDM_DBG("%s: Removing hsic device\n", __func__);
+	if (ifline_status == IFLINE_UP) {
+		platform_device_del(&msm_device_hsic_host);
+		ifline_status = IFLINE_DOWN;
+	}
+}
+
+static void normal_boot_done(struct mdm_modem_drv *mdm_drv)
+{
+}
+
+static void debug_state_changed(int value)
+{
+	mdm_debug_on = value;
+}
+
+static int __init mdm_modem_probe(struct platform_device *pdev)
+{
+	/* Instantiate driver object. */
+	mdm_cb.power_on_mdm_cb = power_on_mdm;
+	mdm_cb.power_down_mdm_cb = power_down_mdm;
+	mdm_cb.normal_boot_done_cb = normal_boot_done;
+	mdm_cb.debug_state_changed_cb = debug_state_changed;
+	return mdm_common_create(pdev, &mdm_cb);
+}
+
+static int __devexit mdm_modem_remove(struct platform_device *pdev)
+{
+	return mdm_common_modem_remove(pdev);
+}
+
+static void mdm_modem_shutdown(struct platform_device *pdev)
+{
+	mdm_common_modem_shutdown(pdev);
+}
+
+static struct platform_driver mdm_modem_driver = {
+	.remove         = mdm_modem_remove,
+	.shutdown	= mdm_modem_shutdown,
+	.driver         = {
+		.name = "mdm2_modem",
+		.owner = THIS_MODULE
+	},
+};
+
+static int __init mdm_modem_init(void)
+{
+	return platform_driver_probe(&mdm_modem_driver, mdm_modem_probe);
+}
+
+static void __exit mdm_modem_exit(void)
+{
+	platform_driver_unregister(&mdm_modem_driver);
+}
+
+module_init(mdm_modem_init);
+module_exit(mdm_modem_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("mdm modem driver");
+MODULE_VERSION("2.0");
+MODULE_ALIAS("mdm_modem");
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
new file mode 100644
index 0000000..1262ce3
--- /dev/null
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -0,0 +1,505 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/ioctl.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/debugfs.h>
+#include <linux/completion.h>
+#include <linux/workqueue.h>
+#include <linux/clk.h>
+#include <linux/mfd/pmic8058.h>
+#include <asm/mach-types.h>
+#include <asm/uaccess.h>
+#include <mach/mdm2.h>
+#include <mach/restart.h>
+#include <mach/subsystem_notif.h>
+#include <mach/subsystem_restart.h>
+#include <linux/msm_charm.h>
+#include "msm_watchdog.h"
+#include "mdm_private.h"
+
+#define MDM_MODEM_TIMEOUT	6000
+#define MDM_MODEM_DELTA	100
+
+static int mdm_debug_on;
+static struct workqueue_struct *mdm_queue;
+
+#define EXTERNAL_MODEM "external_modem"
+
+#define MDM_DBG(...)	do { if (mdm_debug_on) \
+					pr_info(__VA_ARGS__); \
+			} while (0);
+
+static struct mdm_modem_drv *mdm_drv;
+
+DECLARE_COMPLETION(mdm_needs_reload);
+DECLARE_COMPLETION(mdm_boot);
+DECLARE_COMPLETION(mdm_ram_dumps);
+
+static int first_boot = 1;
+
+long mdm_modem_ioctl(struct file *filp, unsigned int cmd,
+				unsigned long arg)
+{
+	int status, ret = 0;
+
+	if (_IOC_TYPE(cmd) != CHARM_CODE) {
+		pr_err("%s: invalid ioctl code\n", __func__);
+		return -EINVAL;
+	}
+
+	MDM_DBG("%s: Entering ioctl cmd = %d\n", __func__, _IOC_NR(cmd));
+	switch (cmd) {
+	case WAKE_CHARM:
+		MDM_DBG("%s: Powering on\n", __func__);
+		mdm_drv->power_on_mdm_cb(mdm_drv);
+		break;
+	case CHECK_FOR_BOOT:
+		if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
+			put_user(1, (unsigned long __user *) arg);
+		else
+			put_user(0, (unsigned long __user *) arg);
+		break;
+	case NORMAL_BOOT_DONE:
+		MDM_DBG("%s: check if mdm is booted up\n", __func__);
+		get_user(status, (unsigned long __user *) arg);
+		if (status)
+			mdm_drv->mdm_boot_status = -EIO;
+		else
+			mdm_drv->mdm_boot_status = 0;
+		mdm_drv->mdm_ready = 1;
+
+		if (mdm_drv->normal_boot_done_cb != NULL)
+			mdm_drv->normal_boot_done_cb(mdm_drv);
+
+		if (!first_boot)
+			complete(&mdm_boot);
+		else
+			first_boot = 0;
+		break;
+	case RAM_DUMP_DONE:
+		MDM_DBG("%s: mdm done collecting RAM dumps\n", __func__);
+		get_user(status, (unsigned long __user *) arg);
+		if (status)
+			mdm_drv->mdm_ram_dump_status = -EIO;
+		else
+			mdm_drv->mdm_ram_dump_status = 0;
+		complete(&mdm_ram_dumps);
+		break;
+	case WAIT_FOR_RESTART:
+		MDM_DBG("%s: wait for mdm to need images reloaded\n",
+				__func__);
+		ret = wait_for_completion_interruptible(&mdm_needs_reload);
+		if (!ret)
+			put_user(mdm_drv->boot_type,
+					 (unsigned long __user *) arg);
+		INIT_COMPLETION(mdm_needs_reload);
+		break;
+	default:
+		pr_err("%s: invalid ioctl cmd = %d\n", __func__, _IOC_NR(cmd));
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static void mdm_fatal_fn(struct work_struct *work)
+{
+	MDM_DBG("%s: Reseting the mdm due to an errfatal\n", __func__);
+	subsystem_restart(EXTERNAL_MODEM);
+}
+
+static DECLARE_WORK(mdm_fatal_work, mdm_fatal_fn);
+
+static void mdm_status_fn(struct work_struct *work)
+{
+	MDM_DBG("%s: Reseting the mdm because status changed\n", __func__);
+	subsystem_restart(EXTERNAL_MODEM);
+}
+
+static DECLARE_WORK(mdm_status_work, mdm_status_fn);
+
+static void mdm_disable_irqs(void)
+{
+	disable_irq_nosync(mdm_drv->mdm_errfatal_irq);
+	disable_irq_nosync(mdm_drv->mdm_status_irq);
+
+}
+
+static irqreturn_t mdm_errfatal(int irq, void *dev_id)
+{
+	MDM_DBG("%s: mdm got errfatal interrupt\n", __func__);
+	if (mdm_drv->mdm_ready &&
+		(gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 1)) {
+		MDM_DBG("%s: scheduling work now\n", __func__);
+		queue_work(mdm_queue, &mdm_fatal_work);
+	}
+	return IRQ_HANDLED;
+}
+
+static int mdm_modem_open(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static const struct file_operations mdm_modem_fops = {
+	.owner		= THIS_MODULE,
+	.open		= mdm_modem_open,
+	.unlocked_ioctl	= mdm_modem_ioctl,
+};
+
+
+static struct miscdevice mdm_modem_misc = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "mdm",
+	.fops	= &mdm_modem_fops
+};
+
+static int mdm_panic_prep(struct notifier_block *this,
+				unsigned long event, void *ptr)
+{
+	int i;
+
+	MDM_DBG("%s: setting AP2MDM_ERRFATAL high for a non graceful reset\n",
+			 __func__);
+	mdm_disable_irqs();
+	gpio_set_value(mdm_drv->ap2mdm_errfatal_gpio, 1);
+
+	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
+		gpio_set_value(mdm_drv->ap2mdm_wakeup_gpio, 1);
+
+	for (i = MDM_MODEM_TIMEOUT; i > 0; i -= MDM_MODEM_DELTA) {
+		pet_watchdog();
+		mdelay(MDM_MODEM_DELTA);
+		if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
+			break;
+	}
+	if (i <= 0)
+		pr_err("%s: MDM2AP_STATUS never went low\n", __func__);
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block mdm_panic_blk = {
+	.notifier_call  = mdm_panic_prep,
+};
+
+static irqreturn_t mdm_status_change(int irq, void *dev_id)
+{
+	MDM_DBG("%s: mdm sent status change interrupt\n", __func__);
+	if ((gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
+		 && mdm_drv->mdm_ready) {
+		MDM_DBG("%s: scheduling work now\n", __func__);
+		queue_work(mdm_queue, &mdm_status_work);
+	} else if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 1) {
+		MDM_DBG("%s: mdm is now ready\n", __func__);
+	}
+	return IRQ_HANDLED;
+}
+
+static int mdm_subsys_shutdown(const struct subsys_data *crashed_subsys)
+{
+	mdm_drv->mdm_ready = 0;
+	gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 1);
+	mdm_drv->power_down_mdm_cb(mdm_drv);
+	return 0;
+}
+
+static int mdm_subsys_powerup(const struct subsys_data *crashed_subsys)
+{
+	mdm_drv->power_on_mdm_cb(mdm_drv);
+	mdm_drv->boot_type = CHARM_NORMAL_BOOT;
+	complete(&mdm_needs_reload);
+	wait_for_completion(&mdm_boot);
+	pr_info("%s: mdm modem has been restarted\n", __func__);
+	INIT_COMPLETION(mdm_boot);
+	return mdm_drv->mdm_boot_status;
+}
+
+static int mdm_subsys_ramdumps(int want_dumps,
+				const struct subsys_data *crashed_subsys)
+{
+	mdm_drv->mdm_ram_dump_status = 0;
+	if (want_dumps) {
+		mdm_drv->boot_type = CHARM_RAM_DUMPS;
+		complete(&mdm_needs_reload);
+		wait_for_completion(&mdm_ram_dumps);
+		INIT_COMPLETION(mdm_ram_dumps);
+		gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 1);
+		mdm_drv->power_down_mdm_cb(mdm_drv);
+	}
+	return mdm_drv->mdm_ram_dump_status;
+}
+
+static struct subsys_data mdm_subsystem = {
+	.shutdown = mdm_subsys_shutdown,
+	.ramdump = mdm_subsys_ramdumps,
+	.powerup = mdm_subsys_powerup,
+	.name = EXTERNAL_MODEM,
+};
+
+static int mdm_debug_on_set(void *data, u64 val)
+{
+	mdm_debug_on = val;
+	if (mdm_drv->debug_state_changed_cb)
+		mdm_drv->debug_state_changed_cb(mdm_debug_on);
+	return 0;
+}
+
+static int mdm_debug_on_get(void *data, u64 *val)
+{
+	*val = mdm_debug_on;
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(mdm_debug_on_fops,
+			mdm_debug_on_get,
+			mdm_debug_on_set, "%llu\n");
+
+static int mdm_debugfs_init(void)
+{
+	struct dentry *dent;
+
+	dent = debugfs_create_dir("mdm_dbg", 0);
+	if (IS_ERR(dent))
+		return PTR_ERR(dent);
+
+	debugfs_create_file("debug_on", 0644, dent, NULL,
+			&mdm_debug_on_fops);
+	return 0;
+}
+
+static void mdm_modem_initialize_data(struct platform_device  *pdev,
+				struct mdm_callbacks *p_mdm_cb)
+{
+	struct resource *pres;
+
+	/* MDM2AP_ERRFATAL */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"MDM2AP_ERRFATAL");
+	if (pres)
+		mdm_drv->mdm2ap_errfatal_gpio = pres->start;
+
+	/* AP2MDM_ERRFATAL */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"AP2MDM_ERRFATAL");
+	if (pres)
+		mdm_drv->ap2mdm_errfatal_gpio = pres->start;
+
+	/* MDM2AP_STATUS */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"MDM2AP_STATUS");
+	if (pres)
+		mdm_drv->mdm2ap_status_gpio = pres->start;
+
+	/* AP2MDM_STATUS */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"AP2MDM_STATUS");
+	if (pres)
+		mdm_drv->ap2mdm_status_gpio = pres->start;
+
+	/* MDM2AP_WAKEUP */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"MDM2AP_WAKEUP");
+	if (pres)
+		mdm_drv->mdm2ap_wakeup_gpio = pres->start;
+
+	/* AP2MDM_WAKEUP */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"AP2MDM_WAKEUP");
+	if (pres)
+		mdm_drv->ap2mdm_wakeup_gpio = pres->start;
+
+	/* AP2MDM_PMIC_RESET_N */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"AP2MDM_PMIC_RESET_N");
+	if (pres)
+		mdm_drv->ap2mdm_pmic_reset_n_gpio = pres->start;
+
+	/* AP2MDM_KPDPWR_N */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"AP2MDM_KPDPWR_N");
+	if (pres)
+		mdm_drv->ap2mdm_kpdpwr_n_gpio = pres->start;
+
+	mdm_drv->boot_type                  = CHARM_NORMAL_BOOT;
+
+	mdm_drv->power_on_mdm_cb            = p_mdm_cb->power_on_mdm_cb;
+	mdm_drv->power_down_mdm_cb          = p_mdm_cb->power_down_mdm_cb;
+	mdm_drv->normal_boot_done_cb        = p_mdm_cb->normal_boot_done_cb;
+	mdm_drv->debug_state_changed_cb     = p_mdm_cb->debug_state_changed_cb;
+}
+
+int mdm_common_create(struct platform_device  *pdev,
+					  struct mdm_callbacks *p_mdm_cb)
+{
+	int ret = -1, irq;
+
+	mdm_drv = kzalloc(sizeof(struct mdm_modem_drv), GFP_KERNEL);
+	if (mdm_drv == NULL) {
+		pr_err("%s: kzalloc fail.\n", __func__);
+		goto alloc_err;
+	}
+
+	mdm_modem_initialize_data(pdev, p_mdm_cb);
+	if (mdm_drv->debug_state_changed_cb)
+		mdm_drv->debug_state_changed_cb(mdm_debug_on);
+
+	gpio_request(mdm_drv->ap2mdm_status_gpio, "AP2MDM_STATUS");
+	gpio_request(mdm_drv->ap2mdm_errfatal_gpio, "AP2MDM_ERRFATAL");
+	gpio_request(mdm_drv->ap2mdm_kpdpwr_n_gpio, "AP2MDM_KPDPWR_N");
+	gpio_request(mdm_drv->ap2mdm_pmic_reset_n_gpio, "AP2MDM_PMIC_RESET_N");
+	gpio_request(mdm_drv->mdm2ap_status_gpio, "MDM2AP_STATUS");
+	gpio_request(mdm_drv->mdm2ap_errfatal_gpio, "MDM2AP_ERRFATAL");
+
+	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
+		gpio_request(mdm_drv->ap2mdm_wakeup_gpio, "AP2MDM_WAKEUP");
+
+	gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 1);
+	gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 0);
+
+	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
+		gpio_direction_output(mdm_drv->ap2mdm_wakeup_gpio, 0);
+
+	gpio_direction_input(mdm_drv->mdm2ap_status_gpio);
+	gpio_direction_input(mdm_drv->mdm2ap_errfatal_gpio);
+
+	mdm_queue = create_singlethread_workqueue("mdm_queue");
+	if (!mdm_queue) {
+		pr_err("%s: could not create workqueue. All mdm "
+				"functionality will be disabled\n",
+			__func__);
+		ret = -ENOMEM;
+		goto fatal_err;
+	}
+
+	atomic_notifier_chain_register(&panic_notifier_list, &mdm_panic_blk);
+	mdm_debugfs_init();
+
+	/* Register subsystem handlers */
+	ssr_register_subsystem(&mdm_subsystem);
+
+	/* ERR_FATAL irq. */
+	irq = MSM_GPIO_TO_INT(mdm_drv->mdm2ap_errfatal_gpio);
+	if (irq < 0) {
+		pr_err("%s: could not get MDM2AP_ERRFATAL IRQ resource. "
+			"error=%d No IRQ will be generated on errfatal.",
+			__func__, irq);
+		goto errfatal_err;
+	}
+	ret = request_irq(irq, mdm_errfatal,
+		IRQF_TRIGGER_RISING , "mdm errfatal", NULL);
+
+	if (ret < 0) {
+		pr_err("%s: MDM2AP_ERRFATAL IRQ#%d request failed with error=%d"
+			". No IRQ will be generated on errfatal.",
+			__func__, irq, ret);
+		goto errfatal_err;
+	}
+	mdm_drv->mdm_errfatal_irq = irq;
+
+errfatal_err:
+
+	/* status irq */
+	irq = MSM_GPIO_TO_INT(mdm_drv->mdm2ap_status_gpio);
+	if (irq < 0) {
+		pr_err("%s: could not get MDM2AP_STATUS IRQ resource. "
+			"error=%d No IRQ will be generated on status change.",
+			__func__, irq);
+		goto status_err;
+	}
+
+	ret = request_threaded_irq(irq, NULL, mdm_status_change,
+		IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+		"mdm status", NULL);
+
+	if (ret < 0) {
+		pr_err("%s: MDM2AP_STATUS IRQ#%d request failed with error=%d"
+			". No IRQ will be generated on status change.",
+			__func__, irq, ret);
+		goto status_err;
+	}
+	mdm_drv->mdm_status_irq = irq;
+
+status_err:
+	pr_info("%s: Registering mdm modem\n", __func__);
+	return misc_register(&mdm_modem_misc);
+
+fatal_err:
+	gpio_free(mdm_drv->ap2mdm_status_gpio);
+	gpio_free(mdm_drv->ap2mdm_errfatal_gpio);
+	gpio_free(mdm_drv->ap2mdm_kpdpwr_n_gpio);
+	gpio_free(mdm_drv->ap2mdm_pmic_reset_n_gpio);
+	gpio_free(mdm_drv->mdm2ap_status_gpio);
+	gpio_free(mdm_drv->mdm2ap_errfatal_gpio);
+
+	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
+		gpio_free(mdm_drv->ap2mdm_wakeup_gpio);
+
+	kfree(mdm_drv);
+	ret = -ENODEV;
+
+alloc_err:
+	return ret;
+}
+
+int mdm_common_modem_remove(struct platform_device *pdev)
+{
+	int ret;
+
+	gpio_free(mdm_drv->ap2mdm_status_gpio);
+	gpio_free(mdm_drv->ap2mdm_errfatal_gpio);
+	gpio_free(mdm_drv->ap2mdm_kpdpwr_n_gpio);
+	gpio_free(mdm_drv->ap2mdm_pmic_reset_n_gpio);
+	gpio_free(mdm_drv->mdm2ap_status_gpio);
+	gpio_free(mdm_drv->mdm2ap_errfatal_gpio);
+
+	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
+		gpio_free(mdm_drv->ap2mdm_wakeup_gpio);
+
+	kfree(mdm_drv);
+
+	ret = misc_deregister(&mdm_modem_misc);
+	return ret;
+}
+
+void mdm_common_modem_shutdown(struct platform_device *pdev)
+{
+	MDM_DBG("%s: setting AP2MDM_STATUS low for a graceful restart\n",
+		__func__);
+
+	mdm_disable_irqs();
+
+	gpio_set_value(mdm_drv->ap2mdm_status_gpio, 0);
+
+	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
+		gpio_set_value(mdm_drv->ap2mdm_wakeup_gpio, 1);
+
+	mdm_drv->power_down_mdm_cb(mdm_drv);
+
+	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
+		gpio_set_value(mdm_drv->ap2mdm_wakeup_gpio, 0);
+}
+
diff --git a/arch/arm/mach-msm/mdm_private.h b/arch/arm/mach-msm/mdm_private.h
new file mode 100644
index 0000000..701eb7a
--- /dev/null
+++ b/arch/arm/mach-msm/mdm_private.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ARCH_ARM_MACH_MSM_MDM_PRIVATE_H
+#define _ARCH_ARM_MACH_MSM_MDM_PRIVATE_H
+
+struct mdm_modem_drv;
+
+/* Private mdm2 data structure */
+struct mdm_modem_drv {
+	unsigned mdm2ap_errfatal_gpio;
+	unsigned ap2mdm_errfatal_gpio;
+	unsigned mdm2ap_status_gpio;
+	unsigned ap2mdm_status_gpio;
+	unsigned mdm2ap_wakeup_gpio;
+	unsigned ap2mdm_wakeup_gpio;
+	unsigned ap2mdm_pmic_reset_n_gpio;
+	unsigned ap2mdm_kpdpwr_n_gpio;
+
+	int mdm_errfatal_irq;
+	int mdm_status_irq;
+	int mdm_ready;
+	int mdm_boot_status;
+	int mdm_ram_dump_status;
+	enum charm_boot_type boot_type;
+	int mdm_debug_on;
+
+	void (*power_on_mdm_cb)(struct mdm_modem_drv *mdm_drv);
+	void (*normal_boot_done_cb)(struct mdm_modem_drv *mdm_drv);
+	void (*power_down_mdm_cb)(struct mdm_modem_drv *mdm_drv);
+	void (*debug_state_changed_cb)(int value);
+};
+
+struct mdm_callbacks {
+	void (*power_on_mdm_cb)(struct mdm_modem_drv *mdm_drv);
+	void (*normal_boot_done_cb)(struct mdm_modem_drv *mdm_drv);
+	void (*power_down_mdm_cb)(struct mdm_modem_drv *mdm_drv);
+	void (*debug_state_changed_cb)(int value);
+};
+
+int mdm_common_create(struct platform_device  *pdev,
+					  struct mdm_callbacks *mdm_cb);
+int mdm_common_modem_remove(struct platform_device *pdev);
+void mdm_common_modem_shutdown(struct platform_device *pdev);
+void mdm_common_set_debug_state(int value);
+
+#endif
+
diff --git a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
index b1d2ee8..492fa0e 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
@@ -82,7 +82,8 @@
 	unsigned long subframe_pkt_addr;
 	unsigned long subframe_pkt_size;
 	unsigned short *frame_header_pkt;
-	int i, num_addr, skip, start_pos = 0, xdim_pos = 1, ydim_pos = 2;
+	int i, num_addr, col_addr = 0, skip;
+	int start_pos = 0, xdim_pos = 1, ydim_pos = 2;
 	unsigned short *frame_buffer_high, *frame_buffer_low;
 	unsigned long frame_buffer_size;
 	unsigned short frame_buffer_size_high, frame_buffer_size_low;
@@ -133,9 +134,10 @@
 		skip = 0;
 		start_pos = 5;
 	   } else {
-	       num_addr = 33;
+	       num_addr = 16;
 	       skip = 0;
 	       start_pos = 6;
+	       col_addr = 17;
 	   }
 		break;
 	case 0x8201: /* h.264 vld in arm */
@@ -216,6 +218,29 @@
 					NULL, NULL, NULL, NULL))
 			return -EINVAL;
 	}
+	if (col_addr) {
+		frame_buffer_high += 2;
+		frame_buffer_low += 2;
+		/* Patch the Co-located buffers.*/
+		frame_buffer_size =  (72 * frame_header_pkt[xdim_pos] *
+					frame_header_pkt[ydim_pos]) >> 16;
+		ptr_to_high_low_short((void *)frame_buffer_size,
+					&frame_buffer_size_high,
+					&frame_buffer_size_low);
+		for (i = 0; i < col_addr; i++) {
+			if (frame_buffer_high && frame_buffer_low) {
+				if (pmem_fixup_high_low(frame_buffer_high,
+						frame_buffer_low,
+						frame_buffer_size_high,
+						frame_buffer_size_low,
+						module,
+						NULL, NULL, NULL, NULL))
+					return -EINVAL;
+			}
+			frame_buffer_high += 2;
+			frame_buffer_low += 2;
+		}
+	}
 	/*Flush the cached pmem subframe packet before sending to DSP*/
 	if (filp) {
 		pmem_addr.vaddr = subframe_pkt_addr;
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils.c b/arch/arm/mach-msm/qdsp6v2/audio_utils.c
index 65a2c54..f9445d8 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils.c
@@ -661,6 +661,7 @@
 	q6asm_audio_client_free(audio->ac);
 	mutex_unlock(&audio->lock);
 	kfree(audio->enc_cfg);
+	kfree(audio->codec_cfg);
 	kfree(audio);
 	return 0;
 }
diff --git a/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c b/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
index 16258eb..f978554 100644
--- a/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
+++ b/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
@@ -43,7 +43,7 @@
 struct lpa_if {
 	struct mutex lock;
 	struct msm_audio_config cfg;
-	struct audio_buffer audio_buf[2];
+	struct audio_buffer audio_buf[6];
 	int cpu_buf;		/* next buffer the CPU will touch */
 	int dma_buf;		/* next buffer the DMA will touch */
 	u8 *buffer;
@@ -52,6 +52,7 @@
 	wait_queue_head_t wait;
 	u32 config;
 	u32 dma_period_sz;
+	unsigned int num_periods;
 };
 
 static struct lpa_if  *lpa_if_ptr;
@@ -85,9 +86,11 @@
 
 		pr_debug("dma_buf %d  used %d\n", lpa_if->dma_buf,
 			lpa_if->audio_buf[lpa_if->dma_buf].used);
+		lpa_if->dma_buf++;
+		lpa_if->dma_buf = lpa_if->dma_buf % lpa_if->cfg.buffer_count;
 
-		lpa_if->dma_buf ^= 1;
-
+		if (lpa_if->dma_buf == lpa_if->cpu_buf)
+			pr_err("Err:both dma_buf and cpu_buf are on same index\n");
 		wake_up(&lpa_if->wait);
 	}
 	return IRQ_HANDLED;
@@ -114,7 +117,7 @@
 
 	dma_params.src_start = lpa_if->buffer_phys;
 	dma_params.buffer = lpa_if->buffer;
-	dma_params.buffer_size = lpa_if->dma_period_sz * 2;
+	dma_params.buffer_size = lpa_if->dma_period_sz * lpa_if->num_periods;
 	dma_params.period_size = lpa_if->dma_period_sz;
 	dma_params.channels = 2;
 
@@ -143,7 +146,7 @@
 {
 	struct lpa_if *lpa_if = file->private_data;
 	int rc = 0;
-
+	unsigned int i;
 	pr_debug("cmd %u\n", cmd);
 
 	mutex_lock(&lpa_if->lock);
@@ -188,25 +191,28 @@
 			pr_debug("%s:failed to copy from user\n", __func__);
 			rc = -EFAULT;
 		}
-		if ((lpa_if->dma_period_sz * 2) > DMA_ALLOC_BUF_SZ) {
+		if ((lpa_if->dma_period_sz * lpa_if->num_periods) >
+			DMA_ALLOC_BUF_SZ) {
 			pr_err("Dma buffer size greater than allocated size\n");
 			return -EINVAL;
 		}
 		pr_debug("Dma_period_sz %d\n", lpa_if->dma_period_sz);
-		lpa_if->cfg.buffer_count = 2;
-		lpa_if->cfg.buffer_size = lpa_if->dma_period_sz * 2;
+		if (lpa_if->dma_period_sz < (2 * SZ_4K))
+			lpa_if->num_periods = 6;
+		pr_debug("No. of Periods %d\n", lpa_if->num_periods);
 
-		lpa_if->audio_buf[0].phys = lpa_if->buffer_phys;
-		lpa_if->audio_buf[0].data = lpa_if->buffer;
-		lpa_if->audio_buf[0].size = lpa_if->dma_period_sz;
-		lpa_if->audio_buf[0].used = 0;
+		lpa_if->cfg.buffer_count = lpa_if->num_periods;
+		lpa_if->cfg.buffer_size = lpa_if->dma_period_sz *
+						lpa_if->num_periods;
 
-		lpa_if->audio_buf[1].phys =
-				lpa_if->buffer_phys + lpa_if->dma_period_sz;
-		lpa_if->audio_buf[1].data =
-				lpa_if->buffer + lpa_if->dma_period_sz;
-		lpa_if->audio_buf[1].size = lpa_if->dma_period_sz;
-		lpa_if->audio_buf[1].used = 0;
+		for (i = 0; i < lpa_if->cfg.buffer_count; i++) {
+			lpa_if->audio_buf[i].phys =
+				lpa_if->buffer_phys + i * lpa_if->dma_period_sz;
+			lpa_if->audio_buf[i].data =
+				lpa_if->buffer + i * lpa_if->dma_period_sz;
+			lpa_if->audio_buf[i].size = lpa_if->dma_period_sz;
+			lpa_if->audio_buf[i].used = 0;
+		}
 		break;
 	default:
 		pr_err("UnKnown Ioctl\n");
@@ -225,8 +231,9 @@
 
 	file->private_data = lpa_if_ptr;
 	dma_buf_index = 0;
-	lpa_if_ptr->cpu_buf = 0;
+	lpa_if_ptr->cpu_buf = 2;
 	lpa_if_ptr->dma_buf = 0;
+	lpa_if_ptr->num_periods = 4;
 
 	core_req_bus_bandwith(AUDIO_IF_BUS_ID, 100000, 0);
 	mb();
@@ -234,6 +241,17 @@
 	return 0;
 }
 
+static inline int rt_policy(int policy)
+{
+	if (unlikely(policy == SCHED_FIFO) || unlikely(policy == SCHED_RR))
+		return 1;
+	return 0;
+}
+
+static inline int task_has_rt_policy(struct task_struct *p)
+{
+	return rt_policy(p->policy);
+}
 static ssize_t lpa_if_write(struct file *file, const char __user *buf,
 		size_t count, loff_t *pos)
 {
@@ -241,7 +259,19 @@
 	struct audio_buffer *ab;
 	const char __user *start = buf;
 	int xfer, rc;
+	struct sched_param s = { .sched_priority = 1 };
+	int old_prio = current->rt_priority;
+	int old_policy = current->policy;
+	int cap_nice = cap_raised(current_cap(), CAP_SYS_NICE);
 
+	 /* just for this write, set us real-time */
+	if (!task_has_rt_policy(current)) {
+		struct cred *new = prepare_creds();
+		cap_raise(new->cap_effective, CAP_SYS_NICE);
+		commit_creds(new);
+		if ((sched_setscheduler(current, SCHED_RR, &s)) < 0)
+			pr_err("sched_setscheduler failed\n");
+	}
 	mutex_lock(&lpa_if->lock);
 
 	if (dma_buf_index < 2) {
@@ -299,12 +329,23 @@
 
 		pr_debug("xfer %d, size %d, used %d cpu_buf %d\n",
 			xfer, ab->size, ab->used, lpa_if->cpu_buf);
-
-		lpa_if->cpu_buf ^= 1;
+		lpa_if->cpu_buf++;
+		lpa_if->cpu_buf = lpa_if->cpu_buf % lpa_if->cfg.buffer_count;
 	}
 	rc = buf - start;
 end:
 	mutex_unlock(&lpa_if->lock);
+	/* restore old scheduling policy */
+	if (!rt_policy(old_policy)) {
+		struct sched_param v = { .sched_priority = old_prio };
+		if ((sched_setscheduler(current, old_policy, &v)) < 0)
+			pr_err("sched_setscheduler failed\n");
+		if (likely(!cap_nice)) {
+			struct cred *new = prepare_creds();
+			cap_lower(new->cap_effective, CAP_SYS_NICE);
+			commit_creds(new);
+		}
+	}
 	return rc;
 }
 
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 3e6a7e5..9fe9eea6 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -65,10 +65,6 @@
 static ssize_t msm_rpmrs_resource_attr_store(struct kobject *kobj,
 	struct kobj_attribute *attr, const char *buf, size_t count);
 
-static  void *msm_rpmrs_l2_counter_addr;
-static  int msm_rpmrs_l2_reset_count;
-#define L2_PC_COUNTER_ADDR 0x660
-
 #define MSM_RPMRS_MAX_RS_REGISTER_COUNT 2
 
 #define RPMRS_ATTR(_name) \
@@ -509,11 +505,6 @@
 	switch (limits->l2_cache) {
 	case MSM_RPMRS_L2_CACHE_HSFS_OPEN:
 		lpm = MSM_SPM_L2_MODE_POWER_COLLAPSE;
-		/* Increment the counter for TZ to init L2  on warmboot */
-		/* Barrier in msm_spm_l2_set_low_power_mode */
-		BUG_ON(!msm_rpmrs_l2_counter_addr);
-		writel_relaxed(++msm_rpmrs_l2_reset_count,
-				msm_rpmrs_l2_counter_addr);
 		msm_pm_set_l2_flush_flag(1);
 		break;
 	case MSM_RPMRS_L2_CACHE_GDHS:
@@ -540,9 +531,6 @@
 {
 	msm_spm_l2_set_low_power_mode(MSM_SPM_MODE_DISABLED, notify_rpm);
 	msm_pm_set_l2_flush_flag(0);
-	if (!collapsed && (limits->l2_cache == MSM_RPMRS_L2_CACHE_HSFS_OPEN))
-		writel_relaxed(--msm_rpmrs_l2_reset_count,
-				msm_rpmrs_l2_counter_addr);
 }
 #else
 static int msm_rpmrs_flush_L2(struct msm_rpmrs_limits *limits, int notify_rpm)
@@ -1059,13 +1047,9 @@
 }
 early_initcall(msm_rpmrs_early_init);
 
-static int __init msm_rpmrs_l2_counter_init(void)
+static int __init msm_rpmrs_l2_init(void)
 {
 	if (cpu_is_msm8960() || cpu_is_msm8930()) {
-		msm_rpmrs_l2_counter_addr = MSM_IMEM_BASE + L2_PC_COUNTER_ADDR;
-		writel_relaxed(msm_rpmrs_l2_reset_count,
-				msm_rpmrs_l2_counter_addr);
-		mb();
 
 		msm_pm_set_l2_flush_flag(0);
 
@@ -1073,6 +1057,7 @@
 			msm_spm_l2_cache_beyond_limits;
 		msm_rpmrs_l2_cache.aggregate = NULL;
 		msm_rpmrs_l2_cache.restore = NULL;
+
 		register_hotcpu_notifier(&rpmrs_cpu_notifier);
 
 	} else if (cpu_is_msm9615()) {
@@ -1082,4 +1067,4 @@
 	}
 	return 0;
 }
-early_initcall(msm_rpmrs_l2_counter_init);
+early_initcall(msm_rpmrs_l2_init);
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 7c7a822..4744f1f 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -63,7 +63,6 @@
 	int i;
 
 	int blocking_write;
-	int needed_space;
 	int is_open;
 	unsigned ch_size;
 	uint open_modem_wait;
@@ -155,7 +154,7 @@
 	smd_pkt_devp->is_open = 0;
 
 	wake_up(&smd_pkt_devp->ch_read_wait_queue);
-	wake_up_interruptible(&smd_pkt_devp->ch_write_wait_queue);
+	wake_up(&smd_pkt_devp->ch_write_wait_queue);
 	wake_up_interruptible(&smd_pkt_devp->ch_opened_wait_queue);
 }
 
@@ -305,7 +304,7 @@
 		       size_t count,
 		       loff_t *ppos)
 {
-	int r = 0;
+	int r = 0, bytes_written;
 	struct smd_pkt_dev *smd_pkt_devp;
 	DEFINE_WAIT(write_wait);
 
@@ -317,84 +316,56 @@
 	if (!smd_pkt_devp || !smd_pkt_devp->ch)
 		return -EINVAL;
 
-	if (count > smd_pkt_devp->ch_size)
-		return -EINVAL;
-
 	if (smd_pkt_devp->do_reset_notification) {
 		/* notify client that a reset occurred */
 		return notify_reset(smd_pkt_devp);
 	}
 
-	if (smd_pkt_devp->blocking_write) {
-		for (;;) {
-			mutex_lock(&smd_pkt_devp->tx_lock);
-			if (smd_pkt_devp->has_reset) {
-				smd_disable_read_intr(smd_pkt_devp->ch);
-				mutex_unlock(&smd_pkt_devp->tx_lock);
-				return notify_reset(smd_pkt_devp);
-			}
-			if (signal_pending(current)) {
-				smd_disable_read_intr(smd_pkt_devp->ch);
-				mutex_unlock(&smd_pkt_devp->tx_lock);
-				return -ERESTARTSYS;
-			}
-
-			prepare_to_wait(&smd_pkt_devp->ch_write_wait_queue,
-					&write_wait, TASK_INTERRUPTIBLE);
-			smd_enable_read_intr(smd_pkt_devp->ch);
-			if (smd_write_avail(smd_pkt_devp->ch) < count) {
-				if (!smd_pkt_devp->needed_space ||
-				    count < smd_pkt_devp->needed_space)
-					smd_pkt_devp->needed_space = count;
-				mutex_unlock(&smd_pkt_devp->tx_lock);
-				schedule();
-			} else
-				break;
-		}
-		finish_wait(&smd_pkt_devp->ch_write_wait_queue, &write_wait);
-		smd_disable_read_intr(smd_pkt_devp->ch);
-		if (smd_pkt_devp->has_reset) {
-			mutex_unlock(&smd_pkt_devp->tx_lock);
-			return notify_reset(smd_pkt_devp);
-		}
-		if (signal_pending(current)) {
-			mutex_unlock(&smd_pkt_devp->tx_lock);
-			return -ERESTARTSYS;
-		}
-	} else {
-		if (smd_pkt_devp->has_reset)
-			return notify_reset(smd_pkt_devp);
-		if (signal_pending(current))
-			return -ERESTARTSYS;
-
-		mutex_lock(&smd_pkt_devp->tx_lock);
+	mutex_lock(&smd_pkt_devp->tx_lock);
+	if (!smd_pkt_devp->blocking_write) {
 		if (smd_write_avail(smd_pkt_devp->ch) < count) {
 			D(KERN_ERR "%s: Not enough space to write\n",
-				    __func__);
+				   __func__);
 			mutex_unlock(&smd_pkt_devp->tx_lock);
 			return -ENOMEM;
 		}
 	}
 
-	D_DUMP_BUFFER("write: ", count, buf);
-
-	smd_pkt_devp->needed_space = 0;
-
-	r = smd_write_user_buffer(smd_pkt_devp->ch, buf, count);
-	if (r != count) {
+	r = smd_write_start(smd_pkt_devp->ch, count);
+	if (r < 0) {
 		mutex_unlock(&smd_pkt_devp->tx_lock);
-		if (smd_pkt_devp->has_reset)
-			return notify_reset(smd_pkt_devp);
-
-		printk(KERN_ERR "ERROR:%s:%i:%s: "
-		       "smd_write(ch,buf,count = %i) ret %i.\n",
-		       __FILE__,
-		       __LINE__,
-		       __func__,
-		       count,
-		       r);
+		pr_err("%s: Error %d @ smd_write_start\n", __func__, r);
 		return r;
 	}
+
+	bytes_written = 0;
+	do {
+		prepare_to_wait(&smd_pkt_devp->ch_write_wait_queue,
+				&write_wait, TASK_UNINTERRUPTIBLE);
+		if (!smd_write_avail(smd_pkt_devp->ch) &&
+		    !smd_pkt_devp->has_reset) {
+			smd_enable_read_intr(smd_pkt_devp->ch);
+			schedule();
+		}
+		finish_wait(&smd_pkt_devp->ch_write_wait_queue, &write_wait);
+		smd_disable_read_intr(smd_pkt_devp->ch);
+
+		if (smd_pkt_devp->has_reset) {
+			mutex_unlock(&smd_pkt_devp->tx_lock);
+			return notify_reset(smd_pkt_devp);
+		} else {
+			r = smd_write_segment(smd_pkt_devp->ch,
+					      (void *)(buf + bytes_written),
+					      (count - bytes_written), 1);
+			if (r < 0) {
+				mutex_unlock(&smd_pkt_devp->tx_lock);
+				if (smd_pkt_devp->has_reset)
+					return notify_reset(smd_pkt_devp);
+			}
+			bytes_written += r;
+		}
+	} while (bytes_written != count);
+	smd_write_end(smd_pkt_devp->ch);
 	mutex_unlock(&smd_pkt_devp->tx_lock);
 
 	D(KERN_ERR "%s: just wrote %i bytes\n",
@@ -451,11 +422,11 @@
 		return;
 
 	sz = smd_write_avail(smd_pkt_devp->ch);
-	if (sz >= smd_pkt_devp->needed_space) {
+	if (sz) {
 		D(KERN_ERR "%s: %d bytes Write Space available\n",
 			    __func__, sz);
 		smd_disable_read_intr(smd_pkt_devp->ch);
-		wake_up_interruptible(&smd_pkt_devp->ch_write_wait_queue);
+		wake_up(&smd_pkt_devp->ch_write_wait_queue);
 	}
 }
 
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index 6f151cb..b9086e3 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -98,7 +98,15 @@
 static void buf_req_retry(unsigned long param)
 {
 	struct smd_tty_info *info = (struct smd_tty_info *)param;
-	tasklet_hi_schedule(&info->tty_tsklt);
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->reset_lock, flags);
+	if (info->is_open) {
+		spin_unlock_irqrestore(&info->reset_lock, flags);
+		tasklet_hi_schedule(&info->tty_tsklt);
+		return;
+	}
+	spin_unlock_irqrestore(&info->reset_lock, flags);
 }
 
 static void smd_tty_read(unsigned long param)
@@ -163,6 +171,12 @@
 
 	switch (event) {
 	case SMD_EVENT_DATA:
+		spin_lock_irqsave(&info->reset_lock, flags);
+		if (!info->is_open) {
+			spin_unlock_irqrestore(&info->reset_lock, flags);
+			break;
+		}
+		spin_unlock_irqrestore(&info->reset_lock, flags);
 		/* There may be clients (tty framework) that are blocked
 		 * waiting for space to write data, so if a possible read
 		 * interrupt came in wake anyone waiting and disable the
@@ -323,12 +337,16 @@
 static void smd_tty_close(struct tty_struct *tty, struct file *f)
 {
 	struct smd_tty_info *info = tty->driver_data;
+	unsigned long flags;
 
 	if (info == 0)
 		return;
 
 	mutex_lock(&smd_tty_lock);
 	if (--info->open_count == 0) {
+		spin_lock_irqsave(&info->reset_lock, flags);
+		info->is_open = 0;
+		spin_unlock_irqrestore(&info->reset_lock, flags);
 		if (info->tty) {
 			tasklet_kill(&info->tty_tsklt);
 			wake_lock_destroy(&info->wake_lock);
@@ -386,8 +404,15 @@
 static void smd_tty_unthrottle(struct tty_struct *tty)
 {
 	struct smd_tty_info *info = tty->driver_data;
-	tasklet_hi_schedule(&info->tty_tsklt);
-	return;
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->reset_lock, flags);
+	if (info->is_open) {
+		spin_unlock_irqrestore(&info->reset_lock, flags);
+		tasklet_hi_schedule(&info->tty_tsklt);
+		return;
+	}
+	spin_unlock_irqrestore(&info->reset_lock, flags);
 }
 
 /*
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 96a4563..c4bc76c 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -31,6 +31,7 @@
 	HW_PLATFORM_FLUID   = 3,
 	HW_PLATFORM_SVLTE_FFA	= 4,
 	HW_PLATFORM_SVLTE_SURF	= 5,
+	HW_PLATFORM_LIQUID  = 9,
 	/* Dragonboard platform id is assigned as 10 in CDT */
 	HW_PLATFORM_DRAGON	= 10,
 	HW_PLATFORM_INVALID
@@ -41,6 +42,7 @@
 	[HW_PLATFORM_SURF] = "Surf",
 	[HW_PLATFORM_FFA] = "FFA",
 	[HW_PLATFORM_FLUID] = "Fluid",
+	[HW_PLATFORM_LIQUID] = "Liquid",
 	[HW_PLATFORM_SVLTE_FFA] = "SVLTE_FFA",
 	[HW_PLATFORM_SVLTE_SURF] = "SLVTE_SURF",
 	[HW_PLATFORM_DRAGON] = "Dragon"
diff --git a/arch/arm/mach-msm/tz_log.c b/arch/arm/mach-msm/tz_log.c
new file mode 100644
index 0000000..8d7196b
--- /dev/null
+++ b/arch/arm/mach-msm/tz_log.c
@@ -0,0 +1,559 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/debugfs.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+
+#define DEBUG_MAX_RW_BUF 4096
+
+/*
+ * Preprocessor Definitions and Constants
+ */
+#define TZBSP_CPU_COUNT 0x02
+/*
+ * Number of VMID Tables
+ */
+#define TZBSP_DIAG_NUM_OF_VMID 16
+/*
+ * VMID Description length
+ */
+#define TZBSP_DIAG_VMID_DESC_LEN 7
+/*
+ * Number of Interrupts
+ */
+#define TZBSP_DIAG_INT_NUM  32
+/*
+ * Length of descriptive name associated with Interrupt
+ */
+#define TZBSP_MAX_INT_DESC 16
+/*
+ * VMID Table
+ */
+struct tzdbg_vmid_t {
+	uint8_t vmid; /* Virtual Machine Identifier */
+	uint8_t desc[TZBSP_DIAG_VMID_DESC_LEN];	/* ASCII Text */
+};
+/*
+ * Boot Info Table
+ */
+struct tzdbg_boot_info_t {
+	uint32_t entry_cnt;	/* Warmboot entry CPU Counter */
+	uint32_t exit_cnt;	/* Warmboot exit CPU Counter */
+	uint32_t warm_jmp_addr;	/* Last Warmboot Jump Address */
+	uint32_t spare;	/* Reserved for future use. */
+};
+/*
+ * Reset Info Table
+ */
+struct tzdbg_reset_info_t {
+	uint32_t reset_type;	/* Reset Reason */
+	uint32_t reset_cnt;	/* Number of resets occured/CPU */
+};
+/*
+ * Interrupt Info Table
+ */
+struct tzdbg_int_t {
+	/*
+	 * Type of Interrupt/exception
+	 */
+	uint16_t int_info;
+	/*
+	 * Availability of the slot
+	 */
+	uint8_t avail;
+	/*
+	 * Reserved for future use
+	 */
+	uint8_t spare;
+	/*
+	 * Interrupt # for IRQ and FIQ
+	 */
+	uint32_t int_num;
+	/*
+	 * ASCII text describing type of interrupt e.g:
+	 * Secure Timer, EBI XPU. This string is always null terminated,
+	 * supporting at most TZBSP_MAX_INT_DESC characters.
+	 * Any additional characters are truncated.
+	 */
+	uint8_t int_desc[TZBSP_MAX_INT_DESC];
+	uint64_t int_count[TZBSP_CPU_COUNT]; /* # of times seen per CPU */
+};
+/*
+ * Diagnostic Table
+ */
+struct tzdbg_t {
+	uint32_t magic_num;
+	uint32_t version;
+	/*
+	 * Number of CPU's
+	 */
+	uint32_t cpu_count;
+	/*
+	 * Offset of VMID Table
+	 */
+	uint32_t vmid_info_off;
+	/*
+	 * Offset of Boot Table
+	 */
+	uint32_t boot_info_off;
+	/*
+	 * Offset of Reset info Table
+	 */
+	uint32_t reset_info_off;
+	/*
+	 * Offset of Interrupt info Table
+	 */
+	uint32_t int_info_off;
+	/*
+	 * Ring Buffer Offset
+	 */
+	uint32_t ring_off;
+	/*
+	 * Ring Buffer Length
+	 */
+	uint32_t ring_len;
+	/*
+	 * VMID to EE Mapping
+	 */
+	struct tzdbg_vmid_t vmid_info[TZBSP_DIAG_NUM_OF_VMID];
+	/*
+	 * Boot Info
+	 */
+	struct tzdbg_boot_info_t  boot_info[TZBSP_CPU_COUNT];
+	/*
+	 * Reset Info
+	 */
+	struct tzdbg_reset_info_t reset_info[TZBSP_CPU_COUNT];
+	uint32_t num_interrupts;
+	struct tzdbg_int_t  int_info[TZBSP_DIAG_INT_NUM];
+	/*
+	 * We need at least 2K for the ring buffer
+	 */
+	uint8_t *ring_buffer;	/* TZ Ring Buffer */
+};
+
+/*
+ * Enumeration order for VMID's
+ */
+enum tzdbg_stats_type {
+	TZDBG_BOOT = 0,
+	TZDBG_RESET,
+	TZDBG_INTERRUPT,
+	TZDBG_VMID,
+	TZDBG_GENERAL,
+	TZDBG_LOG,
+	TZDBG_STATS_MAX,
+};
+
+struct tzdbg_stat {
+	char *name;
+	char *data;
+};
+
+struct tzdbg {
+	void __iomem *virt_iobase;
+	struct tzdbg_t *diag_buf;
+	char *disp_buf;
+	int debug_tz[TZDBG_STATS_MAX];
+	struct tzdbg_stat stat[TZDBG_STATS_MAX];
+};
+
+static struct tzdbg tzdbg = {
+
+	.stat[TZDBG_BOOT].name = "boot",
+	.stat[TZDBG_RESET].name = "reset",
+	.stat[TZDBG_INTERRUPT].name = "interrupt",
+	.stat[TZDBG_VMID].name = "vmid",
+	.stat[TZDBG_GENERAL].name = "general",
+	.stat[TZDBG_LOG].name = "log",
+};
+
+
+/*
+ * Debugfs data structure and functions
+ */
+
+static int _disp_tz_general_stats(void)
+{
+	int len = 0;
+
+	len += snprintf(tzdbg.disp_buf + len, DEBUG_MAX_RW_BUF - 1,
+			"   Version        : 0x%x\n"
+			"   Magic Number   : 0x%x\n"
+			"   Number of CPU  : %d\n",
+			tzdbg.diag_buf->version,
+			tzdbg.diag_buf->magic_num,
+			tzdbg.diag_buf->cpu_count);
+	tzdbg.stat[TZDBG_GENERAL].data = tzdbg.disp_buf;
+	return len;
+}
+
+static int _disp_tz_vmid_stats(void)
+{
+	int i, num_vmid;
+	int len = 0;
+	struct tzdbg_vmid_t *ptr;
+
+	ptr = (struct tzdbg_vmid_t *)((unsigned char *)tzdbg.diag_buf +
+					tzdbg.diag_buf->vmid_info_off);
+	num_vmid = ((tzdbg.diag_buf->boot_info_off -
+				tzdbg.diag_buf->vmid_info_off)/
+					(sizeof(struct tzdbg_vmid_t)));
+
+	for (i = 0; i < num_vmid; i++) {
+		if (ptr->vmid < 0xFF) {
+			len += snprintf(tzdbg.disp_buf + len,
+				(DEBUG_MAX_RW_BUF - 1) - len,
+				"   0x%x        %s\n",
+				(uint32_t)ptr->vmid, (uint8_t *)ptr->desc);
+		}
+		if (len > (DEBUG_MAX_RW_BUF - 1)) {
+			pr_warn("%s: Cannot fit all info into the buffer\n",
+								__func__);
+			break;
+		}
+		ptr++;
+	}
+
+	tzdbg.stat[TZDBG_VMID].data = tzdbg.disp_buf;
+	return len;
+}
+
+static int _disp_tz_boot_stats(void)
+{
+	int i;
+	int len = 0;
+	struct tzdbg_boot_info_t *ptr;
+
+	ptr = (struct tzdbg_boot_info_t *)((unsigned char *)tzdbg.diag_buf +
+					tzdbg.diag_buf->boot_info_off);
+
+	for (i = 0; i < tzdbg.diag_buf->cpu_count; i++) {
+		len += snprintf(tzdbg.disp_buf + len,
+				(DEBUG_MAX_RW_BUF - 1) - len,
+				"  CPU #: %d\n"
+				"     Warmboot jump address     : 0x%x\n"
+				"     Warmboot entry CPU counter: 0x%x\n"
+				"     Warmboot exit CPU counter : 0x%x\n",
+				i, ptr->warm_jmp_addr, ptr->entry_cnt,
+				ptr->exit_cnt);
+
+		if (len > (DEBUG_MAX_RW_BUF - 1)) {
+			pr_warn("%s: Cannot fit all info into the buffer\n",
+								__func__);
+			break;
+		}
+		ptr++;
+	}
+	tzdbg.stat[TZDBG_BOOT].data = tzdbg.disp_buf;
+	return len;
+}
+
+static int _disp_tz_reset_stats(void)
+{
+	int i;
+	int len = 0;
+	struct tzdbg_reset_info_t *ptr;
+
+	ptr = (struct tzdbg_reset_info_t *)((unsigned char *)tzdbg.diag_buf +
+					tzdbg.diag_buf->reset_info_off);
+
+	for (i = 0; i < tzdbg.diag_buf->cpu_count; i++) {
+		len += snprintf(tzdbg.disp_buf + len,
+				(DEBUG_MAX_RW_BUF - 1) - len,
+				"  CPU #: %d\n"
+				"     Reset Type (reason)       : 0x%x\n"
+				"     Reset counter             : 0x%x\n",
+				i, ptr->reset_type, ptr->reset_cnt);
+
+		if (len > (DEBUG_MAX_RW_BUF - 1)) {
+			pr_warn("%s: Cannot fit all info into the buffer\n",
+								__func__);
+			break;
+		}
+
+		ptr++;
+	}
+	tzdbg.stat[TZDBG_RESET].data = tzdbg.disp_buf;
+	return len;
+}
+
+static int _disp_tz_interrupt_stats(void)
+{
+	int i, j, int_info_size;
+	int len = 0;
+	int *num_int;
+	unsigned char *ptr;
+	struct tzdbg_int_t *tzdbg_ptr;
+
+	num_int = (uint32_t *)((unsigned char *)tzdbg.diag_buf +
+			(tzdbg.diag_buf->int_info_off - sizeof(uint32_t)));
+	ptr = ((unsigned char *)tzdbg.diag_buf +
+					tzdbg.diag_buf->int_info_off);
+	int_info_size = ((tzdbg.diag_buf->ring_off -
+				tzdbg.diag_buf->int_info_off)/(*num_int));
+
+	for (i = 0; i < (*num_int); i++) {
+		tzdbg_ptr = (struct tzdbg_int_t *)ptr;
+		len += snprintf(tzdbg.disp_buf + len,
+				(DEBUG_MAX_RW_BUF - 1) - len,
+				"     Interrupt Number          : 0x%x\n"
+				"     Type of Interrupt         : 0x%x\n"
+				"     Description of interrupt  : %s\n",
+				tzdbg_ptr->int_num,
+				(uint32_t)tzdbg_ptr->int_info,
+				(uint8_t *)tzdbg_ptr->int_desc);
+		for (j = 0; j < tzdbg.diag_buf->cpu_count; j++) {
+			len += snprintf(tzdbg.disp_buf + len,
+				(DEBUG_MAX_RW_BUF - 1) - len,
+				"     int_count on CPU # %d      : %u\n",
+				(uint32_t)j,
+				(uint32_t)tzdbg_ptr->int_count[j]);
+		}
+		len += snprintf(tzdbg.disp_buf + len, DEBUG_MAX_RW_BUF - 1,
+									"\n");
+
+		if (len > (DEBUG_MAX_RW_BUF - 1)) {
+			pr_warn("%s: Cannot fit all info into the buffer\n",
+								__func__);
+			break;
+		}
+
+		ptr += int_info_size;
+	}
+	tzdbg.stat[TZDBG_INTERRUPT].data = tzdbg.disp_buf;
+	return len;
+}
+
+static int _disp_tz_log_stats(void)
+{
+	int len = 0;
+	unsigned char *ptr;
+
+	ptr = (unsigned char *)tzdbg.diag_buf +
+					tzdbg.diag_buf->ring_off;
+	len += snprintf(tzdbg.disp_buf, (DEBUG_MAX_RW_BUF - 1) - len,
+							"%s\n", ptr);
+
+	tzdbg.stat[TZDBG_LOG].data = tzdbg.disp_buf;
+	return len;
+}
+
+static ssize_t tzdbgfs_read(struct file *file, char __user *buf,
+	size_t count, loff_t *offp)
+{
+	int len = 0;
+	int *tz_id =  file->private_data;
+
+	memcpy_fromio((void *)tzdbg.diag_buf, tzdbg.virt_iobase,
+						DEBUG_MAX_RW_BUF);
+	switch (*tz_id) {
+	case TZDBG_BOOT:
+		len = _disp_tz_boot_stats();
+		break;
+	case TZDBG_RESET:
+		len = _disp_tz_reset_stats();
+		break;
+	case TZDBG_INTERRUPT:
+		len = _disp_tz_interrupt_stats();
+		break;
+	case TZDBG_GENERAL:
+		len = _disp_tz_general_stats();
+		break;
+	case TZDBG_VMID:
+		len = _disp_tz_vmid_stats();
+		break;
+	case TZDBG_LOG:
+		len = _disp_tz_log_stats();
+		break;
+	default:
+		break;
+	}
+
+	if (len > count)
+		len = count;
+
+	return simple_read_from_buffer(buf, len, offp,
+				tzdbg.stat[(*tz_id)].data, len);
+}
+
+static int tzdbgfs_open(struct inode *inode, struct file *pfile)
+{
+	pfile->private_data = inode->i_private;
+	return 0;
+}
+
+const struct file_operations tzdbg_fops = {
+	.owner   = THIS_MODULE,
+	.read    = tzdbgfs_read,
+	.open    = tzdbgfs_open,
+};
+
+static int  tzdbgfs_init(struct platform_device *pdev)
+{
+	int rc = 0;
+	int i;
+	struct dentry           *dent_dir;
+	struct dentry           *dent;
+
+	dent_dir = debugfs_create_dir("tzdbg", NULL);
+	if (dent_dir == NULL) {
+		dev_err(&pdev->dev, "tzdbg debugfs_create_dir failed\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < TZDBG_STATS_MAX; i++) {
+		tzdbg.debug_tz[i] = i;
+		dent = debugfs_create_file(tzdbg.stat[i].name,
+				S_IRUGO, dent_dir,
+				&tzdbg.debug_tz[i], &tzdbg_fops);
+		if (dent == NULL) {
+			dev_err(&pdev->dev, "TZ debugfs_create_file failed\n");
+			rc = -ENOMEM;
+			goto err;
+		}
+	}
+	tzdbg.disp_buf = kzalloc(DEBUG_MAX_RW_BUF, GFP_KERNEL);
+	if (tzdbg.disp_buf == NULL) {
+		pr_err("%s: Can't Allocate memory for tzdbg.disp_buf\n",
+			__func__);
+
+		goto err;
+	}
+	platform_set_drvdata(pdev, dent_dir);
+	return 0;
+err:
+	debugfs_remove_recursive(dent_dir);
+
+	return rc;
+}
+
+static void tzdbgfs_exit(struct platform_device *pdev)
+{
+	struct dentry           *dent_dir;
+
+	kzfree(tzdbg.disp_buf);
+	dent_dir = platform_get_drvdata(pdev);
+	debugfs_remove_recursive(dent_dir);
+}
+
+/*
+ * Driver functions
+ */
+static int __devinit tz_log_probe(struct platform_device *pdev)
+{
+	struct resource *resource;
+	void __iomem *virt_iobase;
+	uint32_t tzdiag_phy_iobase;
+	uint32_t *ptr = NULL;
+
+	/*
+	 * Get address that stores the physical location of 4KB
+	 * diagnostic data
+	 */
+	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!resource) {
+		dev_err(&pdev->dev,
+				"%s: ERROR Missing MEM resource\n", __func__);
+		return -ENXIO;
+	};
+	/*
+	 * Map address that stores the physical location of 4KB
+	 * diagnostic data
+	 */
+	virt_iobase = devm_ioremap_nocache(&pdev->dev, resource->start,
+				resource->end - resource->start + 1);
+	if (!virt_iobase) {
+		dev_err(&pdev->dev,
+			"%s: ERROR could not ioremap: start=%p, len=%u\n",
+			__func__, (void *) resource->start,
+			(resource->end - resource->start + 1));
+		return -ENXIO;
+	}
+	/*
+	 * Retrieve the address of 4KB diagnostic data
+	 */
+	tzdiag_phy_iobase = readl_relaxed(virt_iobase);
+
+	/*
+	 * Map the 4KB diagnostic information area
+	 */
+	tzdbg.virt_iobase = devm_ioremap_nocache(&pdev->dev,
+				tzdiag_phy_iobase, DEBUG_MAX_RW_BUF);
+
+	if (!tzdbg.virt_iobase) {
+		dev_err(&pdev->dev,
+			"%s: ERROR could not ioremap: start=%p, len=%u\n",
+			__func__, (void *) tzdiag_phy_iobase, DEBUG_MAX_RW_BUF);
+		return -ENXIO;
+	}
+
+	ptr = kzalloc(DEBUG_MAX_RW_BUF, GFP_KERNEL);
+	if (ptr == NULL) {
+		pr_err("%s: Can't Allocate memory: ptr\n",
+			__func__);
+		return -ENXIO;
+	}
+
+	tzdbg.diag_buf = (struct tzdbg_t *)ptr;
+
+	if (tzdbgfs_init(pdev))
+		goto err;
+
+	return 0;
+err:
+	kfree(tzdbg.diag_buf);
+	return -ENXIO;
+}
+
+
+static int __devexit tz_log_remove(struct platform_device *pdev)
+{
+	kzfree(tzdbg.diag_buf);
+	tzdbgfs_exit(pdev);
+
+	return 0;
+}
+
+static struct platform_driver tz_log_driver = {
+	.probe		= tz_log_probe,
+	.remove		= __devexit_p(tz_log_remove),
+	.driver		= {
+		.name = "tz_log",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init tz_log_init(void)
+{
+	return platform_driver_register(&tz_log_driver);
+}
+
+static void __exit tz_log_exit(void)
+{
+	platform_driver_unregister(&tz_log_driver);
+}
+
+module_init(tz_log_init);
+module_exit(tz_log_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TZ Log driver");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform:tz_log");
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 2ef5c61..18b7334 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -21,6 +21,7 @@
 #include <mach/scm.h>
 #include <mach/subsystem_restart.h>
 #include <mach/subsystem_notif.h>
+#include <mach/peripheral-loader.h>
 #include "smd_private.h"
 #include "ramdump.h"
 
@@ -35,10 +36,14 @@
 static void *riva_ramdump_dev;
 static int riva_crash;
 static int ss_restart_inprogress;
+static int enable_riva_ssr;
 
 static void riva_smsm_cb_fn(struct work_struct *work)
 {
-	panic(MODULE_NAME ": SMSM reset request received from Riva");
+	if (!enable_riva_ssr)
+		panic(MODULE_NAME ": SMSM reset request received from Riva");
+	else
+		subsystem_restart("riva");
 }
 
 static void smsm_state_cb_hdlr(void *data, uint32_t old_state,
@@ -74,13 +79,13 @@
 /* Subsystem handlers */
 static int riva_shutdown(const struct subsys_data *subsys)
 {
-	/* TODO for phase 3 */
+	pil_force_shutdown("wcnss");
 	return 0;
 }
 
 static int riva_powerup(const struct subsys_data *subsys)
 {
-	/* TODO for phase 3 */
+	pil_force_boot("wcnss");
 	return 0;
 }
 
@@ -118,6 +123,23 @@
 	.crash_shutdown = riva_crash_shutdown
 };
 
+static int enable_riva_ssr_set(const char *val, struct kernel_param *kp)
+{
+	int ret;
+
+	ret = param_set_int(val, kp);
+	if (ret)
+		return ret;
+
+	if (enable_riva_ssr)
+		pr_info(MODULE_NAME ": Subsystem restart activated for riva.\n");
+
+	return 0;
+}
+
+module_param_call(enable_riva_ssr, enable_riva_ssr_set, param_get_int,
+			&enable_riva_ssr, S_IRUGO | S_IWUSR);
+
 static int __init riva_restart_init(void)
 {
 	return ssr_register_subsystem(&riva_8960);
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 2c6957d..baf3170 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1131,3 +1131,4 @@
 msm7625a_surf		MACH_MSM7625A_SURF	MSM7625A_SURF		3772
 msm8627_cdp		MACH_MSM8627_CDP	MSM8627_CDP		3861
 msm8627_mtp		MACH_MSM8627_MTP	MSM8627_MTP		3862
+msm8625_rumi3		MACH_MSM8625_RUMI3	MSM8625_RUMI3		3871
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index 696a7bd..edf5c27 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -19,7 +19,6 @@
 #include <linux/sched.h>
 #include <linux/uaccess.h>
 #include <linux/clk.h>
-#include <mach/clk.h>
 #include <linux/android_pmem.h>
 #include <linux/msm_rotator.h>
 #include <linux/io.h>
@@ -1339,7 +1338,7 @@
 				goto error_imem_clk;
 			}
 			if (pdata->rotator_clks[i].clk_rate)
-				clk_set_min_rate(msm_rotator_dev->imem_clk,
+				clk_set_rate(msm_rotator_dev->imem_clk,
 					pdata->rotator_clks[i].clk_rate);
 		}
 		if (pdata->rotator_clks[i].clk_type == ROTATOR_PCLK) {
@@ -1355,7 +1354,7 @@
 			}
 
 			if (pdata->rotator_clks[i].clk_rate)
-				clk_set_min_rate(msm_rotator_dev->pclk,
+				clk_set_rate(msm_rotator_dev->pclk,
 					pdata->rotator_clks[i].clk_rate);
 		}
 
@@ -1372,7 +1371,7 @@
 			}
 
 			if (pdata->rotator_clks[i].clk_rate)
-				clk_set_min_rate(msm_rotator_dev->core_clk,
+				clk_set_rate(msm_rotator_dev->core_clk,
 					pdata->rotator_clks[i].clk_rate);
 		}
 	}
diff --git a/drivers/crypto/msm/qce40.c b/drivers/crypto/msm/qce40.c
index 60a5aff..d725851 100644
--- a/drivers/crypto/msm/qce40.c
+++ b/drivers/crypto/msm/qce40.c
@@ -208,6 +208,7 @@
 
 static int _init_ce_engine(struct qce_device *pce_dev)
 {
+	int status;
 	/* Reset ce */
 	clk_reset(pce_dev->ce_core_clk, CLK_RESET_ASSERT);
 	clk_reset(pce_dev->ce_core_clk, CLK_RESET_DEASSERT);
@@ -224,6 +225,11 @@
 	config_ce_engine(pce_dev);
 
 	/*
+	 * Clear ACCESS_VIOL bit in CRYPTO_STATUS REGISTER
+	*/
+	status = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
+	*((uint32_t *)(pce_dev->ce_dm.buffer.status)) = status & (~0x40000);
+	/*
 	* Ensure ce configuration is completed.
 	*/
 	mb();
@@ -474,12 +480,20 @@
 		}
 	}
 
-	if (creq->mode == QCE_MODE_CCM)
+	switch (creq->mode) {
+	case QCE_MODE_CCM:
 		pce_dev->ce_dm.chan_ce_out_cmd->cmdptr =
-						cmdptrlist->aead_ce_out;
-	else
+					cmdptrlist->aead_ce_out;
+		break;
+	case QCE_MODE_ECB:
 		pce_dev->ce_dm.chan_ce_out_cmd->cmdptr =
-						cmdptrlist->cipher_ce_out;
+					cmdptrlist->cipher_ce_out;
+		break;
+	default:
+		pce_dev->ce_dm.chan_ce_out_cmd->cmdptr =
+					cmdptrlist->cipher_ce_out_get_iv;
+		break;
+	}
 
 	return 0;
 }
@@ -1330,21 +1344,6 @@
 	pscmd->src = GET_PHYS_ADDR(pce_dev->ce_dm.buffer.encr_cntr_iv);
 	pscmd++;
 
-	pce_dev->ce_dm.cmdlist.get_cipher_aes_iv = pscmd;
-	pscmd->cmd = CMD_LC | CMD_SRC_SWAP_BYTES |
-				CMD_SRC_SWAP_SHORTS | CMD_MODE_SINGLE;
-	pscmd->src = (unsigned) (CRYPTO_CNTR0_IV0_REG + pce_dev->phy_iobase);
-	pscmd->len = CRYPTO_REG_SIZE * 4;
-	pscmd->dst = GET_PHYS_ADDR(pce_dev->ce_dm.buffer.encr_cntr_iv);
-	pscmd++;
-
-	pce_dev->ce_dm.cmdlist.get_cipher_aes_xts_iv = pscmd;
-	pscmd->cmd = CMD_LC | CMD_MODE_SINGLE;
-	pscmd->src = (unsigned) (CRYPTO_CNTR0_IV0_REG + pce_dev->phy_iobase);
-	pscmd->len = CRYPTO_REG_SIZE * 4;
-	pscmd->dst = GET_PHYS_ADDR(pce_dev->ce_dm.buffer.encr_cntr_iv);
-	pscmd++;
-
 	pce_dev->ce_dm.cmdlist.set_cipher_des_iv = pscmd;
 	pscmd->cmd = CMD_LC | CMD_SRC_SWAP_BYTES |
 				CMD_SRC_SWAP_SHORTS | CMD_MODE_SINGLE;
@@ -1353,11 +1352,11 @@
 	pscmd->src = GET_PHYS_ADDR(pce_dev->ce_dm.buffer.encr_cntr_iv);
 	pscmd++;
 
-	pce_dev->ce_dm.cmdlist.get_cipher_des_iv = pscmd;
+	pce_dev->ce_dm.cmdlist.get_cipher_iv = pscmd;
 	pscmd->cmd = CMD_LC | CMD_SRC_SWAP_BYTES |
 				CMD_SRC_SWAP_SHORTS | CMD_MODE_SINGLE;
 	pscmd->src = (unsigned) (CRYPTO_CNTR0_IV0_REG + pce_dev->phy_iobase);
-	pscmd->len = CRYPTO_REG_SIZE * 2;
+	pscmd->len = CRYPTO_REG_SIZE * 4;
 	pscmd->dst = GET_PHYS_ADDR(pce_dev->ce_dm.buffer.encr_cntr_iv);
 	pscmd++;
 
@@ -1613,6 +1612,14 @@
 	pscmd->dst = GET_PHYS_ADDR(pce_dev->ce_dm.buffer.status);
 	pscmd++;
 
+	/* CLEAR STATUS COMMAND LIST */
+	pce_dev->ce_dm.cmdlist.clear_status = pscmd;
+	pscmd->cmd = CMD_LC | CMD_MODE_SINGLE | CMD_OCU;
+	pscmd->dst = (unsigned) (CRYPTO_STATUS_REG + pce_dev->phy_iobase);
+	pscmd->len = CRYPTO_REG_SIZE;
+	pscmd->src = GET_PHYS_ADDR(pce_dev->ce_dm.buffer.status);
+	pscmd++;
+
 	/* SET GO_PROC REGISTERS COMMAND LIST */
 	pce_dev->ce_dm.cmdlist.set_go_proc = pscmd;
 	pscmd->cmd = CMD_LC | CMD_MODE_SINGLE;
@@ -1693,8 +1700,7 @@
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->reset_auth_cfg);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->set_cipher_mask);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->set_go_proc);
-	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->ce_data_in);
-	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->get_cipher_aes_iv);
+	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->ce_data_in);
 
 	cmd_ptr_vaddr = (uint32_t *) ALIGN(((unsigned int) cmd_ptr_vaddr), 16);
 	cmdptrlist->cipher_aes_256_cbc_ctr = QCE_SET_CMD_PTR(cmd_ptr_vaddr);
@@ -1706,8 +1712,7 @@
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->reset_auth_cfg);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->set_cipher_mask);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->set_go_proc);
-	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->ce_data_in);
-	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->get_cipher_aes_iv);
+	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->ce_data_in);
 
 	cmd_ptr_vaddr = (uint32_t *) ALIGN(((unsigned int) cmd_ptr_vaddr), 16);
 	cmdptrlist->cipher_aes_128_ecb = QCE_SET_CMD_PTR(cmd_ptr_vaddr);
@@ -1743,8 +1748,7 @@
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->set_cipher_xts_du_size);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->set_cipher_mask);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->set_go_proc);
-	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->ce_data_in);
-	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->get_cipher_aes_xts_iv);
+	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->ce_data_in);
 
 	cmd_ptr_vaddr = (uint32_t *) ALIGN(((unsigned int) cmd_ptr_vaddr), 16);
 	cmdptrlist->cipher_aes_256_xts = QCE_SET_CMD_PTR(cmd_ptr_vaddr);
@@ -1758,8 +1762,7 @@
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->set_cipher_xts_du_size);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->set_cipher_mask);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->set_go_proc);
-	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->ce_data_in);
-	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->get_cipher_aes_xts_iv);
+	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->ce_data_in);
 
 	cmd_ptr_vaddr = (uint32_t *)ALIGN(((unsigned int) cmd_ptr_vaddr), 16);
 	cmdptrlist->cipher_des_cbc = QCE_SET_CMD_PTR(cmd_ptr_vaddr);
@@ -1770,8 +1773,7 @@
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->set_cipher_des_iv);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->reset_auth_cfg);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->set_go_proc);
-	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->ce_data_in);
-	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->get_cipher_des_iv);
+	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->ce_data_in);
 
 	cmd_ptr_vaddr = (uint32_t *)ALIGN(((unsigned int) cmd_ptr_vaddr), 16);
 	cmdptrlist->cipher_des_ecb = QCE_SET_CMD_PTR(cmd_ptr_vaddr);
@@ -1792,8 +1794,7 @@
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->set_cipher_des_iv);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->reset_auth_cfg);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->set_go_proc);
-	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->ce_data_in);
-	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->get_cipher_des_iv);
+	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->ce_data_in);
 
 	cmd_ptr_vaddr = (uint32_t *) ALIGN(((unsigned int) cmd_ptr_vaddr), 16);
 	cmdptrlist->cipher_3des_ecb = QCE_SET_CMD_PTR(cmd_ptr_vaddr);
@@ -1810,6 +1811,14 @@
 
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->ce_data_out);
 	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->get_status_ocu);
+
+	cmd_ptr_vaddr = (uint32_t *) ALIGN(((unsigned int) cmd_ptr_vaddr), 16);
+	cmdptrlist->cipher_ce_out_get_iv = QCE_SET_CMD_PTR(cmd_ptr_vaddr);
+
+	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->ce_data_out);
+	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_cipher_iv);
+	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->get_status_ocu);
+
 	*pvaddr = (unsigned char *) cmd_ptr_vaddr;
 
 	return 0;
@@ -2008,6 +2017,7 @@
 	cmdptrlist->probe_ce_hw = QCE_SET_CMD_PTR(cmd_ptr_vaddr);
 
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_hw_version);
+	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->clear_status);
 	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->get_status_ocu);
 
 	*pvaddr = (unsigned char *) cmd_ptr_vaddr;
diff --git a/drivers/crypto/msm/qce40.h b/drivers/crypto/msm/qce40.h
index c9fbb17..809ba7f 100644
--- a/drivers/crypto/msm/qce40.h
+++ b/drivers/crypto/msm/qce40.h
@@ -117,6 +117,7 @@
 /* CE Command lists */
 struct ce_cmdlists {
 	dmov_s *get_hw_version;
+	dmov_s *clear_status;
 	dmov_s *get_status_ocu;
 
 	dmov_s *set_cipher_cfg;
@@ -132,10 +133,8 @@
 
 	dmov_s *set_cipher_aes_iv;
 	dmov_s *set_cipher_aes_xts_iv;
-	dmov_s *get_cipher_aes_iv;
-	dmov_s *get_cipher_aes_xts_iv;
 	dmov_s *set_cipher_des_iv;
-	dmov_s *get_cipher_des_iv;
+	dmov_s *get_cipher_iv;
 
 	dmov_s *set_cipher_mask;
 
@@ -195,6 +194,7 @@
 	uint32_t aead_aes_256_ccm;
 
 	uint32_t cipher_ce_out;
+	uint32_t cipher_ce_out_get_iv;
 	uint32_t aead_ce_out;
 };
 
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 4138e06..d485cd2 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -837,6 +837,12 @@
 	return status;
 }
 
+static inline void adreno_poke(struct kgsl_device *device)
+{
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	adreno_regwrite(device, REG_CP_RB_WPTR, adreno_dev->ringbuffer.wptr);
+}
+
 /* Caller must hold the device mutex. */
 int adreno_idle(struct kgsl_device *device, unsigned int timeout)
 {
@@ -855,6 +861,7 @@
 retry:
 	if (rb->flags & KGSL_FLAGS_STARTED) {
 		do {
+			adreno_poke(device);
 			GSL_RB_GET_READPTR(rb, &rb->rptr);
 			if (time_after(jiffies, wait_time)) {
 				KGSL_DRV_ERR(device, "rptr: %x, wptr: %x\n",
@@ -1028,7 +1035,7 @@
 			kgsl_sharedmem_readl(&device->memstore, &ref_ts,
 				KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts));
 			mb();
-			if (timestamp_cmp(ref_ts, timestamp)) {
+			if (timestamp_cmp(ref_ts, timestamp) >= 0) {
 				kgsl_sharedmem_writel(&device->memstore,
 				KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts),
 				timestamp);
@@ -1083,57 +1090,74 @@
 	static uint io_cnt;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+	int retries;
+	unsigned int msecs_first;
+	unsigned int msecs_part;
 
 	/* Don't wait forever, set a max value for now */
 	if (msecs == -1)
 		msecs = adreno_dev->wait_timeout;
 
-	if (timestamp != adreno_dev->ringbuffer.timestamp &&
-		timestamp_cmp(timestamp,
-		adreno_dev->ringbuffer.timestamp)) {
+	if (timestamp_cmp(timestamp, adreno_dev->ringbuffer.timestamp) > 0) {
 		KGSL_DRV_ERR(device, "Cannot wait for invalid ts: %x, "
 			"rb->timestamp: %x\n",
 			timestamp, adreno_dev->ringbuffer.timestamp);
 		status = -EINVAL;
 		goto done;
 	}
-	if (!kgsl_check_timestamp(device, timestamp)) {
-		io_cnt = (io_cnt + 1) % 100;
-		if (io_cnt < pwr->pwrlevels[pwr->active_pwrlevel].io_fraction)
-			io = 0;
-		mutex_unlock(&device->mutex);
-		/* We need to make sure that the process is placed in wait-q
-		 * before its condition is called */
-		status = kgsl_wait_event_interruptible_timeout(
-				device->wait_queue,
-				kgsl_check_interrupt_timestamp(device,
-					timestamp),
-				msecs_to_jiffies(msecs), io);
-		mutex_lock(&device->mutex);
 
-		if (status > 0)
-			status = 0;
-		else if (status == 0) {
-			if (!kgsl_check_timestamp(device, timestamp)) {
-				status = -ETIMEDOUT;
-				KGSL_DRV_ERR(device,
-					"Device hang detected while waiting "
-					"for timestamp: %x, last "
-					"submitted(rb->timestamp): %x, wptr: "
-					"%x\n", timestamp,
-					adreno_dev->ringbuffer.timestamp,
-					adreno_dev->ringbuffer.wptr);
-				if (!adreno_dump_and_recover(device)) {
-					/* wait for idle after recovery as the
-					 * timestamp that this process wanted
-					 * to wait on may be invalid */
-					if (!adreno_idle(device,
-						KGSL_TIMEOUT_DEFAULT))
-						status = 0;
-				}
+	/* Keep the first timeout as 100msecs before rewriting
+	 * the WPTR. Less visible impact if the WPTR has not
+	 * been updated properly.
+	 */
+	msecs_first = (msecs <= 100) ? ((msecs + 4) / 5) : 100;
+	msecs_part = (msecs - msecs_first + 3) / 4;
+	for (retries = 0; retries < 5; retries++) {
+		if (!kgsl_check_timestamp(device, timestamp)) {
+			adreno_poke(device);
+			io_cnt = (io_cnt + 1) % 100;
+			if (io_cnt <
+				pwr->pwrlevels[pwr->active_pwrlevel].
+					io_fraction)
+				io = 0;
+			mutex_unlock(&device->mutex);
+			/* We need to make sure that the process is
+			 * placed in wait-q before its condition is called
+			 */
+			status = kgsl_wait_event_interruptible_timeout(
+					device->wait_queue,
+					kgsl_check_interrupt_timestamp(device,
+						timestamp),
+					msecs_to_jiffies(retries ?
+						msecs_part : msecs_first), io);
+			mutex_lock(&device->mutex);
+
+			if (status > 0) {
+				status = 0;
+				goto done;
 			}
 		}
 	}
+	if (!kgsl_check_timestamp(device, timestamp)) {
+		status = -ETIMEDOUT;
+		KGSL_DRV_ERR(device,
+			"Device hang detected while waiting "
+			"for timestamp: %x, last "
+			"submitted(rb->timestamp): %x, wptr: "
+			"%x\n", timestamp,
+			adreno_dev->ringbuffer.timestamp,
+			adreno_dev->ringbuffer.wptr);
+		if (!adreno_dump_and_recover(device)) {
+			/* wait for idle after recovery as the
+			 * timestamp that this process wanted
+			 * to wait on may be invalid */
+			if (!adreno_idle(device,
+				KGSL_TIMEOUT_DEFAULT))
+				status = 0;
+		}
+	} else {
+		status = 0;
+	}
 
 done:
 	return (int)status;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index a0a4056..53b9e8a 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -20,6 +20,7 @@
 #include <linux/android_pmem.h>
 #include <linux/vmalloc.h>
 #include <linux/pm_runtime.h>
+#include <linux/genlock.h>
 
 #include <linux/ashmem.h>
 #include <linux/major.h>
@@ -47,6 +48,63 @@
 
 static struct ion_client *kgsl_ion_client;
 
+#ifdef CONFIG_GENLOCK
+
+/**
+ * kgsl_add_event - Add a new timstamp event for the KGSL device
+ * @device - KGSL device for the new event
+ * @ts - the timestamp to trigger the event on
+ * @cb - callback function to call when the timestamp expires
+ * @priv - private data for the specific event type
+ *
+ * @returns - 0 on success or error code on failure
+ */
+
+static int kgsl_add_event(struct kgsl_device *device, u32 ts,
+	void (*cb)(struct kgsl_device *, void *, u32), void *priv)
+{
+	struct kgsl_event *event;
+	struct list_head *n;
+	unsigned int cur = device->ftbl->readtimestamp(device,
+		KGSL_TIMESTAMP_RETIRED);
+
+	if (cb == NULL)
+		return -EINVAL;
+
+	/* Check to see if the requested timestamp has already fired */
+
+	if (timestamp_cmp(cur, ts) >= 0) {
+		cb(device, priv, cur);
+		return 0;
+	}
+
+	event = kzalloc(sizeof(*event), GFP_KERNEL);
+	if (event == NULL)
+		return -ENOMEM;
+
+	event->timestamp = ts;
+	event->priv = priv;
+	event->func = cb;
+
+	/* Add the event in order to the list */
+
+	for (n = device->events.next ; n != &device->events; n = n->next) {
+		struct kgsl_event *e =
+			list_entry(n, struct kgsl_event, list);
+
+		if (timestamp_cmp(e->timestamp, ts) > 0) {
+			list_add(&event->list, n->prev);
+			break;
+		}
+	}
+
+	if (n == &device->events)
+		list_add_tail(&event->list, &device->events);
+
+	return 0;
+}
+#endif
+
 static inline struct kgsl_mem_entry *
 kgsl_mem_entry_create(void)
 {
@@ -205,6 +263,7 @@
 	struct kgsl_device *device = container_of(work, struct kgsl_device,
 		ts_expired_ws);
 	struct kgsl_mem_entry *entry, *entry_tmp;
+	struct kgsl_event *event, *event_tmp;
 	uint32_t ts_processed;
 
 	mutex_lock(&device->mutex);
@@ -215,13 +274,25 @@
 
 	/* Flush the freememontimestamp queue */
 	list_for_each_entry_safe(entry, entry_tmp, &device->memqueue, list) {
-		if (!timestamp_cmp(ts_processed, entry->free_timestamp))
+		if (timestamp_cmp(ts_processed, entry->free_timestamp) < 0)
 			break;
 
 		list_del(&entry->list);
 		kgsl_mem_entry_put(entry);
 	}
 
+	/* Process expired events */
+	list_for_each_entry_safe(event, event_tmp, &device->events, list) {
+		if (timestamp_cmp(ts_processed, event->timestamp) < 0)
+			break;
+
+		if (event->func)
+			event->func(device, event->priv, ts_processed);
+
+		list_del(&event->list);
+		kfree(event);
+	}
+
 	mutex_unlock(&device->mutex);
 }
 
@@ -303,7 +374,7 @@
 	ts_processed = device->ftbl->readtimestamp(device,
 		KGSL_TIMESTAMP_RETIRED);
 
-	return timestamp_cmp(ts_processed, timestamp);
+	return (timestamp_cmp(ts_processed, timestamp) >= 0);
 }
 EXPORT_SYMBOL(kgsl_check_timestamp);
 
@@ -1676,6 +1747,114 @@
 	return result;
 }
 
+#ifdef CONFIG_GENLOCK
+struct kgsl_genlock_event_priv {
+	struct genlock_handle *handle;
+	struct genlock *lock;
+};
+
+/**
+ * kgsl_genlock_event_cb - Event callback for a genlock timestamp event
+ * @device - The KGSL device that expired the timestamp
+ * @priv - private data for the event
+ * @timestamp - the timestamp that triggered the event
+ *
+ * Release a genlock lock following the expiration of a timestamp
+ */
+
+static void kgsl_genlock_event_cb(struct kgsl_device *device,
+	void *priv, u32 timestamp)
+{
+	struct kgsl_genlock_event_priv *ev = priv;
+	int ret;
+
+	ret = genlock_lock(ev->handle, GENLOCK_UNLOCK, 0, 0);
+	if (ret)
+		KGSL_CORE_ERR("Error while unlocking genlock: %d\n", ret);
+
+	genlock_put_handle(ev->handle);
+
+	kfree(ev);
+}
+
+/**
+ * kgsl_add_genlock-event - Create a new genlock event
+ * @device - KGSL device to create the event on
+ * @timestamp - Timestamp to trigger the event
+ * @data - User space buffer containing struct kgsl_genlock_event_priv
+ * @len - length of the userspace buffer
+ * @returns 0 on success or error code on error
+ *
+ * Attack to a genlock handle and register an event to release the
+ * genlock lock when the timestamp expires
+ */
+
+static int kgsl_add_genlock_event(struct kgsl_device *device,
+	u32 timestamp, void __user *data, int len)
+{
+	struct kgsl_genlock_event_priv *event;
+	struct kgsl_timestamp_event_genlock priv;
+	int ret;
+
+	if (len !=  sizeof(priv))
+		return -EINVAL;
+
+	if (copy_from_user(&priv, data, sizeof(priv)))
+		return -EFAULT;
+
+	event = kzalloc(sizeof(*event), GFP_KERNEL);
+
+	if (event == NULL)
+		return -ENOMEM;
+
+	event->handle = genlock_get_handle_fd(priv.handle);
+
+	if (IS_ERR(event->handle)) {
+		int ret = PTR_ERR(event->handle);
+		kfree(event);
+		return ret;
+	}
+
+	ret = kgsl_add_event(device, timestamp, kgsl_genlock_event_cb, event);
+	if (ret)
+		kfree(event);
+
+	return ret;
+}
+#else
+static long kgsl_add_genlock_event(struct kgsl_device *device,
+	u32 timestamp, void __user *data, int len)
+{
+	return -EINVAL;
+}
+#endif
+
+/**
+ * kgsl_ioctl_timestamp_event - Register a new timestamp event from userspace
+ * @dev_priv - pointer to the private device structure
+ * @cmd - the ioctl cmd passed from kgsl_ioctl
+ * @data - the user data buffer from kgsl_ioctl
+ * @returns 0 on success or error code on failure
+ */
+
+static long kgsl_ioctl_timestamp_event(struct kgsl_device_private *dev_priv,
+		unsigned int cmd, void *data)
+{
+	struct kgsl_timestamp_event *param = data;
+	int ret;
+
+	switch (param->type) {
+	case KGSL_TIMESTAMP_EVENT_GENLOCK:
+		ret = kgsl_add_genlock_event(dev_priv->device,
+			param->timestamp, param->priv, param->len);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
 typedef long (*kgsl_ioctl_func_t)(struct kgsl_device_private *,
 	unsigned int, void *);
 
@@ -1717,6 +1896,8 @@
 			kgsl_ioctl_cff_syncmem, 0),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_CFF_USER_EVENT,
 			kgsl_ioctl_cff_user_event, 0),
+	KGSL_IOCTL_FUNC(IOCTL_KGSL_TIMESTAMP_EVENT,
+			kgsl_ioctl_timestamp_event, 0),
 };
 
 static long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
@@ -2021,6 +2202,7 @@
 	INIT_WORK(&device->ts_expired_ws, kgsl_timestamp_expired);
 
 	INIT_LIST_HEAD(&device->memqueue);
+	INIT_LIST_HEAD(&device->events);
 
 	ret = kgsl_mmu_init(device);
 	if (ret != 0)
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index b5c24f0..3bb722d 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -184,10 +184,14 @@
 	return 0;
 }
 
-static inline bool timestamp_cmp(unsigned int new, unsigned int old)
+static inline int timestamp_cmp(unsigned int new, unsigned int old)
 {
 	int ts_diff = new - old;
-	return (ts_diff >= 0) || (ts_diff < -20000);
+
+	if (ts_diff == 0)
+		return 0;
+
+	return ((ts_diff > 0) || (ts_diff < -20000)) ? 1 : -1;
 }
 
 static inline void
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index fd203ef..c88f16ef 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -118,6 +118,14 @@
 	int              mpu_range;
 };
 
+struct kgsl_event {
+	uint32_t timestamp;
+	void (*func)(struct kgsl_device *, void *, u32);
+	void *priv;
+	struct list_head list;
+};
+
+
 struct kgsl_device {
 	struct device *dev;
 	const char *name;
@@ -165,6 +173,7 @@
 	struct kgsl_pwrscale pwrscale;
 	struct kobject pwrscale_kobj;
 	struct work_struct ts_expired_ws;
+	struct list_head events;
 };
 
 struct kgsl_context {
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 9e14247..cdb9c23 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -378,7 +378,8 @@
 	int status = 0;
 	struct z180_device *z180_dev = Z180_DEVICE(device);
 
-	if (z180_dev->current_timestamp > z180_dev->timestamp)
+	if (timestamp_cmp(z180_dev->current_timestamp,
+		z180_dev->timestamp) > 0)
 		status = z180_wait(device, z180_dev->current_timestamp,
 					timeout);
 
@@ -644,15 +645,10 @@
 
 static unsigned int z180_isidle(struct kgsl_device *device)
 {
-	int status = false;
 	struct z180_device *z180_dev = Z180_DEVICE(device);
 
-	int timestamp = z180_dev->timestamp;
-
-	if (timestamp == z180_dev->current_timestamp)
-		status = true;
-
-	return status;
+	return (timestamp_cmp(z180_dev->timestamp,
+		z180_dev->current_timestamp) == 0) ? true : false;
 }
 
 static int z180_suspend_context(struct kgsl_device *device)
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index 49bc46c..5976424 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -2745,6 +2745,7 @@
 {
 	struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
 	int retval = 0;
+	int size = 0, cnt = 0;
 	unsigned char value;
 	unsigned char xfr_buf[XFR_REG_NUM];
 	unsigned char tx_data[XFR_REG_NUM];
@@ -2961,6 +2962,110 @@
 		SET_REG_FIELD(radio->registers[IOCTRL], ctrl->value,
 					IOC_ANTENNA_OFFSET, IOC_ANTENNA_MASK);
 		break;
+	case V4L2_CID_PRIVATE_TAVARUA_ON_CHANNEL_THRESHOLD:
+		size = 0x04;
+		/* Poking the value of ON Channel Threshold value */
+		xfr_buf[0] = (XFR_POKE_MODE | (size << 1));
+		xfr_buf[1] = ON_CHANNEL_TH_MSB;
+		xfr_buf[2] = ON_CHANNEL_TH_LSB;
+		/* Data to be poked into the register */
+		xfr_buf[3] = (ctrl->value & 0xFF000000) >> 24;
+		xfr_buf[4] = (ctrl->value & 0x00FF0000) >> 16;
+		xfr_buf[5] = (ctrl->value & 0x0000FF00) >> 8;
+		xfr_buf[6] = (ctrl->value & 0x000000FF);
+
+		for (cnt = 3; cnt < 7; cnt++) {
+			FMDBG("On-channel data to be poked is : %d",
+				(int)xfr_buf[cnt]);
+		}
+
+		retval = tavarua_write_registers(radio, XFRCTRL,
+				xfr_buf, size+3);
+		if (retval < 0) {
+			FMDBG("Failed to write\n");
+			return retval;
+		}
+		/*Wait for the XFR interrupt */
+		msleep(TAVARUA_DELAY*15);
+
+		for (cnt = 0; cnt < 5; cnt++) {
+			xfr_buf[cnt] = 0;
+			radio->registers[XFRDAT0+cnt] = 0x0;
+		}
+
+		/* Peeking Regs 0x88C2-0x88C4 */
+		size = 0x04;
+		xfr_buf[0] = (XFR_PEEK_MODE | (size << 1));
+		xfr_buf[1] = ON_CHANNEL_TH_MSB;
+		xfr_buf[2] = ON_CHANNEL_TH_LSB;
+		retval = tavarua_write_registers(radio, XFRCTRL, xfr_buf, 3);
+		if (retval < 0) {
+			pr_err("%s: Failed to write\n", __func__);
+			return retval;
+		}
+		/*Wait for the XFR interrupt */
+		msleep(TAVARUA_DELAY*10);
+		retval = tavarua_read_registers(radio, XFRDAT0, 4);
+		if (retval < 0) {
+			pr_err("%s: On Ch. DET: Read failure\n", __func__);
+			return retval;
+		}
+		for (cnt = 0; cnt < 4; cnt++)
+			FMDBG("On-Channel data set is : 0x%x\t",
+				(int)radio->registers[XFRDAT0+cnt]);
+		break;
+	case V4L2_CID_PRIVATE_TAVARUA_OFF_CHANNEL_THRESHOLD:
+		size = 0x04;
+		/* Poking the value of OFF Channel Threshold value */
+		xfr_buf[0] = (XFR_POKE_MODE | (size << 1));
+		xfr_buf[1] = OFF_CHANNEL_TH_MSB;
+		xfr_buf[2] = OFF_CHANNEL_TH_LSB;
+		/* Data to be poked into the register */
+		xfr_buf[3] = (ctrl->value & 0xFF000000) >> 24;
+		xfr_buf[4] = (ctrl->value & 0x00FF0000) >> 16;
+		xfr_buf[5] = (ctrl->value & 0x0000FF00) >> 8;
+		xfr_buf[6] = (ctrl->value & 0x000000FF);
+
+		for (cnt = 3; cnt < 7; cnt++) {
+			FMDBG("Off-channel data to be poked is : %d",
+				(int)xfr_buf[cnt]);
+		}
+
+		retval = tavarua_write_registers(radio, XFRCTRL,
+				xfr_buf, size+3);
+		if (retval < 0) {
+			pr_err("%s: Failed to write\n", __func__);
+			return retval;
+		}
+		/*Wait for the XFR interrupt */
+		msleep(TAVARUA_DELAY*10);
+
+		for (cnt = 0; cnt < 5; cnt++) {
+			xfr_buf[cnt] = 0;
+			radio->registers[XFRDAT0+cnt] = 0x0;
+		}
+
+		/* Peeking Regs 0x88C2-0x88C4 */
+		size = 0x04;
+		xfr_buf[0] = (XFR_PEEK_MODE | (size << 1));
+		xfr_buf[1] = OFF_CHANNEL_TH_MSB;
+		xfr_buf[2] = OFF_CHANNEL_TH_LSB;
+		retval = tavarua_write_registers(radio, XFRCTRL, xfr_buf, 3);
+		if (retval < 0) {
+			pr_err("%s: Failed to write\n", __func__);
+			return retval;
+		}
+		/*Wait for the XFR interrupt */
+		msleep(TAVARUA_DELAY*10);
+		retval = tavarua_read_registers(radio, XFRDAT0, 4);
+		if (retval < 0) {
+			pr_err("%s: Off Ch. DET: Read failure\n", __func__);
+			return retval;
+		}
+		for (cnt = 0; cnt < 4; cnt++)
+			FMDBG("Off-channel data set is : 0x%x\t",
+				(int)radio->registers[XFRDAT0+cnt]);
+		break;
 	/* TX Controls */
 
 	case V4L2_CID_RDS_TX_PTY: {
diff --git a/drivers/media/video/msm/actuators/imx074_act.c b/drivers/media/video/msm/actuators/imx074_act.c
index f267f80..e01d2c7 100644
--- a/drivers/media/video/msm/actuators/imx074_act.c
+++ b/drivers/media/video/msm/actuators/imx074_act.c
@@ -12,7 +12,6 @@
  */
 
 #include "msm_actuator.h"
-#include "msm_logging.h"
 #include "msm_camera_i2c.h"
 
 #define	IMX074_TOTAL_STEPS_NEAR_TO_FAR			41
diff --git a/drivers/media/video/msm/actuators/msm_actuator.c b/drivers/media/video/msm/actuators/msm_actuator.c
index 7f570e6..f0023d7 100644
--- a/drivers/media/video/msm/actuators/msm_actuator.c
+++ b/drivers/media/video/msm/actuators/msm_actuator.c
@@ -11,10 +11,6 @@
  */
 
 #include "msm_actuator.h"
-#include "msm_logging.h"
-
-LDECVAR(a_profstarttime);
-LDECVAR(a_profendtime);
 
 int32_t msm_actuator_write_focus(
 	struct msm_actuator_ctrl_t *a_ctrl,
diff --git a/drivers/media/video/msm/actuators/msm_actuator.h b/drivers/media/video/msm/actuators/msm_actuator.h
index d612dad..6fad8dd 100644
--- a/drivers/media/video/msm/actuators/msm_actuator.h
+++ b/drivers/media/video/msm/actuators/msm_actuator.h
@@ -18,6 +18,24 @@
 #include <media/msm_camera.h>
 #include "msm_camera_i2c.h"
 
+#ifdef LERROR
+#undef LERROR
+#endif
+
+#ifdef LINFO
+#undef LINFO
+#endif
+
+#define LERROR(fmt, args...) pr_err(fmt, ##args)
+
+#define CONFIG_MSM_CAMERA_ACT_DBG 0
+
+#if CONFIG_MSM_CAMERA_ACT_DBG
+#define LINFO(fmt, args...) printk(fmt, ##args)
+#else
+#define LINFO(fmt, args...) CDBG(fmt, ##args)
+#endif
+
 struct msm_actuator_ctrl_t;
 
 struct region_params_t {
diff --git a/drivers/media/video/msm/msm_io_vfe31.c b/drivers/media/video/msm/msm_io_vfe31.c
index 1cd731c..f770ce9 100644
--- a/drivers/media/video/msm/msm_io_vfe31.c
+++ b/drivers/media/video/msm/msm_io_vfe31.c
@@ -111,11 +111,6 @@
 static struct clk *camio_jpeg_clk;
 static struct clk *camio_jpeg_pclk;
 static struct clk *camio_vpe_clk;
-static struct vreg *vreg_gp2;
-static struct vreg *vreg_lvsw1;
-static struct vreg *vreg_gp6;
-static struct vreg *vreg_gp16;
-static struct regulator *fs_vfe;
 static struct regulator *fs_vpe;
 static struct msm_camera_io_ext camio_ext;
 static struct msm_camera_io_clk camio_clk;
@@ -123,6 +118,17 @@
 void __iomem *camifpadbase, *csibase;
 static uint32_t vpe_clk_rate;
 
+static struct regulator_bulk_data regs[] = {
+	{ .supply = "gp2",  .min_uV = 2600000, .max_uV = 2600000 },
+	{ .supply = "lvsw1" },
+	{ .supply = "fs_vfe" },
+	/* sn12m0pz regulators */
+	{ .supply = "gp6",  .min_uV = 3050000, .max_uV = 3100000 },
+	{ .supply = "gp16", .min_uV = 1200000, .max_uV = 1200000 },
+};
+
+static int reg_count;
+
 void msm_io_w(u32 data, void __iomem *addr)
 {
 	CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
@@ -201,135 +207,54 @@
 
 static void msm_camera_vreg_enable(struct platform_device *pdev)
 {
-	vreg_gp2 = vreg_get(NULL, "gp2");
-	if (IS_ERR(vreg_gp2)) {
-		pr_err("%s: VREG GP2 get failed %ld\n", __func__,
-			PTR_ERR(vreg_gp2));
-		vreg_gp2 = NULL;
+	int count, rc;
+
+	struct device *dev = &pdev->dev;
+
+	/* Use gp6 and gp16 if and only if dev name matches. */
+	if (!strncmp(pdev->name, "msm_camera_sn12m0pz", 20))
+		count = ARRAY_SIZE(regs);
+	else
+		count = ARRAY_SIZE(regs) - 2;
+
+	rc = regulator_bulk_get(dev, count, regs);
+
+	if (rc) {
+		dev_err(dev, "%s: could not get regulators: %d\n",
+				__func__, rc);
 		return;
 	}
 
-	if (vreg_set_level(vreg_gp2, 2600)) {
-		pr_err("%s: VREG GP2 set failed\n", __func__);
-		goto gp2_put;
+	rc = regulator_bulk_set_voltage(count, regs);
+
+	if (rc) {
+		dev_err(dev, "%s: could not set voltages: %d\n",
+				__func__, rc);
+		goto reg_free;
 	}
 
-	if (vreg_enable(vreg_gp2)) {
-		pr_err("%s: VREG GP2 enable failed\n", __func__);
-		goto gp2_put;
+	rc = regulator_bulk_enable(count, regs);
+
+	if (rc) {
+		dev_err(dev, "%s: could not enable regulators: %d\n",
+				__func__, rc);
+		goto reg_free;
 	}
 
-	vreg_lvsw1 = vreg_get(NULL, "lvsw1");
-	if (IS_ERR(vreg_lvsw1)) {
-		pr_err("%s: VREG LVSW1 get failed %ld\n", __func__,
-			PTR_ERR(vreg_lvsw1));
-		vreg_lvsw1 = NULL;
-		goto gp2_disable;
-		}
-	if (vreg_set_level(vreg_lvsw1, 1800)) {
-		pr_err("%s: VREG LVSW1 set failed\n", __func__);
-		goto lvsw1_put;
-	}
-	if (vreg_enable(vreg_lvsw1)) {
-		pr_err("%s: VREG LVSW1 enable failed\n", __func__);
-		goto lvsw1_put;
-	}
-
-	if (!strcmp(pdev->name, "msm_camera_sn12m0pz")) {
-		vreg_gp6 = vreg_get(NULL, "gp6");
-		if (IS_ERR(vreg_gp6)) {
-			pr_err("%s: VREG GP6 get failed %ld\n", __func__,
-				PTR_ERR(vreg_gp6));
-			vreg_gp6 = NULL;
-			goto lvsw1_disable;
-		}
-
-		if (vreg_set_level(vreg_gp6, 3050)) {
-			pr_err("%s: VREG GP6 set failed\n", __func__);
-			goto gp6_put;
-		}
-
-		if (vreg_enable(vreg_gp6)) {
-			pr_err("%s: VREG GP6 enable failed\n", __func__);
-			goto gp6_put;
-		}
-		vreg_gp16 = vreg_get(NULL, "gp16");
-		if (IS_ERR(vreg_gp16)) {
-			pr_err("%s: VREG GP16 get failed %ld\n", __func__,
-				PTR_ERR(vreg_gp16));
-			vreg_gp16 = NULL;
-			goto gp6_disable;
-		}
-
-		if (vreg_set_level(vreg_gp16, 1200)) {
-			pr_err("%s: VREG GP16 set failed\n", __func__);
-			goto gp16_put;
-		}
-
-		if (vreg_enable(vreg_gp16)) {
-			pr_err("%s: VREG GP16 enable failed\n", __func__);
-			goto gp16_put;
-		}
-	}
-
-	fs_vfe = regulator_get(NULL, "fs_vfe");
-	if (IS_ERR(fs_vfe)) {
-		pr_err("%s: Regulator FS_VFE get failed %ld\n", __func__,
-			PTR_ERR(fs_vfe));
-		fs_vfe = NULL;
-	} else if (regulator_enable(fs_vfe)) {
-		pr_err("%s: Regulator FS_VFE enable failed\n", __func__);
-		regulator_put(fs_vfe);
-	}
-
+	reg_count = count;
 	return;
 
-gp16_put:
-	vreg_put(vreg_gp16);
-	vreg_gp16 = NULL;
-gp6_disable:
-	 vreg_disable(vreg_gp6);
-gp6_put:
-	vreg_put(vreg_gp6);
-	vreg_gp6 = NULL;
-lvsw1_disable:
-	vreg_disable(vreg_lvsw1);
-lvsw1_put:
-	vreg_put(vreg_lvsw1);
-	vreg_lvsw1 = NULL;
-gp2_disable:
-	vreg_disable(vreg_gp2);
-gp2_put:
-	vreg_put(vreg_gp2);
-	vreg_gp2 = NULL;
+reg_free:
+	regulator_bulk_free(count, regs);
+	return;
 }
 
+
 static void msm_camera_vreg_disable(void)
 {
-	if (vreg_gp2) {
-		vreg_disable(vreg_gp2);
-		vreg_put(vreg_gp2);
-		vreg_gp2 = NULL;
-	}
-	if (vreg_lvsw1) {
-		vreg_disable(vreg_lvsw1);
-		vreg_put(vreg_lvsw1);
-		vreg_lvsw1 = NULL;
-	}
-	if (vreg_gp6) {
-		vreg_disable(vreg_gp6);
-		vreg_put(vreg_gp6);
-		vreg_gp6 = NULL;
-	}
-	if (vreg_gp16) {
-		vreg_disable(vreg_gp16);
-		vreg_put(vreg_gp16);
-		vreg_gp16 = NULL;
-	}
-	if (fs_vfe) {
-		regulator_disable(fs_vfe);
-		regulator_put(fs_vfe);
-	}
+	regulator_bulk_disable(reg_count, regs);
+	regulator_bulk_free(reg_count, regs);
+	reg_count = 0;
 }
 
 int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
diff --git a/drivers/media/video/msm/msm_logging.h b/drivers/media/video/msm/msm_logging.h
deleted file mode 100644
index 5e1547c..0000000
--- a/drivers/media/video/msm/msm_logging.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __MSM_LOGGING_H
-#define __MSM_LOGGING_H
-
-#include <linux/time.h>
-
-#ifdef MSM_LOG_LEVEL_ERROR
-#undef MSM_LOG_LEVEL_ERROR
-#endif
-
-#ifdef MSM_LOG_LEVEL_PROFILE
-#undef MSM_LOG_LEVEL_PROFILE
-#endif
-
-#ifdef MSM_LOG_LEVEL_ALL
-#undef MSM_LOG_LEVEL_ALL
-#endif
-
-/* MSM_LOG_LEVEL_ERROR - prints only error logs
- * MSM_LOG_LEVEL_PROFILE - prints all profile and error logs
- * MSM_LOG_LEVEL_ALL - prints all logs */
-
-#define MSM_LOG_LEVEL_ERROR
-/* #define MSM_LOG_LEVEL_PROFILE */
-/* #define MSM_LOG_LEVEL_ALL */
-
-#ifdef LINFO
-#undef LINFO
-#endif
-
-#ifdef LERROR
-#undef LERROR
-#endif
-
-#ifdef LPROFSTART
-#undef LPROFSTART
-#endif
-
-#ifdef LPROFEND
-#undef LPROFEND
-#endif
-
-#if defined(MSM_LOG_LEVEL_ERROR)
-#define LDECVAR(VAR)
-#define LINFO(fmt, args...) pr_debug(fmt, ##args)
-#define LERROR(fmt, args...) pr_err(fmt, ##args)
-#define LPROFSTART(START) do {} while (0)
-#define LPROFEND(START, END) do {} while (0)
-#elif defined(MSM_LOG_LEVEL_PROFILE)
-#define LDECVAR(VAR) \
-	static struct timespec VAR
-#define LINFO(fmt, args...) do {} while (0)
-#define LERROR(fmt, args...) pr_err(fmt, ##args)
-#define LPROFSTART(START) \
-	START = current_kernel_time()
-#define LPROFEND(START, END) \
-	do { \
-		END = current_kernel_time(); \
-		pr_info("profile start time in ns: %lu\n", \
-			(START.tv_sec * NSEC_PER_SEC) + \
-			START.tv_nsec); \
-		pr_info("profile end time in ns: %lu\n", \
-			(END.tv_sec * NSEC_PER_SEC) + \
-			END.tv_nsec); \
-		pr_info("profile diff time in ns: %lu\n", \
-			((END.tv_sec - START.tv_sec) * NSEC_PER_SEC) + \
-			(END.tv_nsec - START.tv_nsec)); \
-		START = END; \
-	} while (0)
-
-#elif defined(MSM_LOG_LEVEL_ALL)
-#define LDECVAR(VAR) \
-	static struct timespec VAR
-#define LINFO(fmt, args...) pr_debug(fmt, ##args)
-#define LERROR(fmt, args...) pr_err(fmt, ##args)
-#define LPROFSTART(START) \
-	START = current_kernel_time()
-#define LPROFEND(START, END) \
-	do { \
-		END = current_kernel_time(); \
-		pr_info("profile start time in ns: %lu\n", \
-			(START.tv_sec * NSEC_PER_SEC) + \
-			START.tv_nsec); \
-		pr_info("profile end time in ns: %lu\n", \
-			(END.tv_sec * NSEC_PER_SEC) + \
-			END.tv_nsec); \
-		pr_info("profile diff time in ns: %lu\n", \
-			((END.tv_sec - START.tv_sec) * NSEC_PER_SEC) + \
-			(END.tv_nsec - START.tv_nsec)); \
-		START = END; \
-	} while (0)
-#else
-#define LDECVAR(VAR)
-#define LINFO(fmt, args...) do {} while (0)
-#define LERROR(fmt, args...) do {} while (0)
-#define LPROFSTART(START) do {} while (0)
-#define LPROFEND(START, END) do {} while (0)
-#endif
-#endif
diff --git a/drivers/media/video/msm/sensors/imx074_v4l2.c b/drivers/media/video/msm/sensors/imx074_v4l2.c
index 99cc2d4..2923e5d 100644
--- a/drivers/media/video/msm/sensors/imx074_v4l2.c
+++ b/drivers/media/video/msm/sensors/imx074_v4l2.c
@@ -315,12 +315,6 @@
 	.sensor_stop_stream = msm_sensor_stop_stream,
 	.sensor_group_hold_on = msm_sensor_group_hold_on,
 	.sensor_group_hold_off = msm_sensor_group_hold_off,
-	.sensor_get_prev_lines_pf = msm_sensor_get_prev_lines_pf,
-	.sensor_get_prev_pixels_pl = msm_sensor_get_prev_pixels_pl,
-	.sensor_get_pict_lines_pf = msm_sensor_get_pict_lines_pf,
-	.sensor_get_pict_pixels_pl = msm_sensor_get_pict_pixels_pl,
-	.sensor_get_pict_max_exp_lc = msm_sensor_get_pict_max_exp_lc,
-	.sensor_get_pict_fps = msm_sensor_get_pict_fps,
 	.sensor_set_fps = msm_sensor_set_fps,
 	.sensor_write_exp_gain = msm_sensor_write_exp_gain1,
 	.sensor_write_snapshot_exp_gain = msm_sensor_write_exp_gain1,
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 76ade6c..7eb3160 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -100,54 +100,6 @@
 		s_ctrl->msm_sensor_reg->default_data_type);
 }
 
-uint16_t msm_sensor_get_prev_lines_pf(struct msm_sensor_ctrl_t *s_ctrl)
-{
-	return s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->prev_res].frame_length_lines;
-}
-
-uint16_t msm_sensor_get_prev_pixels_pl(struct msm_sensor_ctrl_t *s_ctrl)
-{
-	return s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->prev_res].line_length_pclk;
-}
-
-uint16_t msm_sensor_get_pict_lines_pf(struct msm_sensor_ctrl_t *s_ctrl)
-{
-	return s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->pict_res].frame_length_lines;
-}
-
-uint16_t msm_sensor_get_pict_pixels_pl(struct msm_sensor_ctrl_t *s_ctrl)
-{
-	return s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->pict_res].line_length_pclk;
-}
-
-uint32_t msm_sensor_get_pict_max_exp_lc(struct msm_sensor_ctrl_t *s_ctrl)
-{
-	return s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->prev_res].frame_length_lines * 24;
-}
-
-void msm_sensor_get_pict_fps(struct msm_sensor_ctrl_t *s_ctrl,
-			uint16_t fps, uint16_t *pfps)
-{
-	uint32_t divider, d1, d2;
-	d1 = s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->prev_res].frame_length_lines * Q10 /
-		s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->pict_res].frame_length_lines;
-
-	d2 = s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->prev_res].line_length_pclk * Q10 /
-		s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->pict_res].line_length_pclk;
-
-	divider = d1 * d2 / Q10;
-	*pfps = (uint16_t) (fps * divider / Q10);
-}
-
 int32_t msm_sensor_set_fps(struct msm_sensor_ctrl_t *s_ctrl,
 						struct fps_cfg *fps)
 {
@@ -268,15 +220,6 @@
 {
 	int32_t rc = 0;
 	if (s_ctrl->curr_res != res) {
-		switch (mode) {
-		case SENSOR_PREVIEW_MODE:
-			s_ctrl->prev_res = res;
-			break;
-		case SENSOR_SNAPSHOT_MODE:
-		case SENSOR_RAW_SNAPSHOT_MODE:
-			s_ctrl->pict_res = res;
-			break;
-		}
 		s_ctrl->curr_frame_length_lines =
 			s_ctrl->msm_sensor_reg->
 			output_settings[res].frame_length_lines;
@@ -298,27 +241,16 @@
 			int mode, struct sensor_init_cfg *init_info)
 {
 	int32_t rc = 0;
-	s_ctrl->fps = 30*Q8;
 	s_ctrl->fps_divider = Q10;
 	s_ctrl->cam_mode = MSM_SENSOR_MODE_INVALID;
 
 	CDBG("%s: %d\n", __func__, __LINE__);
 	if (mode != s_ctrl->cam_mode) {
-		if (init_info->prev_res >=
-			s_ctrl->msm_sensor_reg->num_conf ||
-			init_info->pict_res >=
-			s_ctrl->msm_sensor_reg->num_conf) {
-			CDBG("Resolution does not exist");
-			return -EINVAL;
-		}
-
-		s_ctrl->prev_res = init_info->prev_res;
-		s_ctrl->pict_res = init_info->pict_res;
 		s_ctrl->curr_res = MSM_SENSOR_INVALID_RES;
 		s_ctrl->cam_mode = mode;
 
 		rc = s_ctrl->func_tbl->sensor_setting(s_ctrl,
-			MSM_SENSOR_REG_INIT, s_ctrl->prev_res);
+			MSM_SENSOR_REG_INIT, 0);
 	}
 	return rc;
 }
@@ -349,109 +281,6 @@
 	CDBG("msm_sensor_config: cfgtype = %d\n",
 	cdata.cfgtype);
 		switch (cdata.cfgtype) {
-		case CFG_GET_PICT_FPS:
-			if (s_ctrl->func_tbl->
-			sensor_get_pict_fps == NULL) {
-				rc = -EFAULT;
-				break;
-			}
-			s_ctrl->func_tbl->
-			sensor_get_pict_fps(
-				s_ctrl,
-				cdata.cfg.gfps.prevfps,
-				&(cdata.cfg.gfps.pictfps));
-
-			if (copy_to_user((void *)argp,
-				&cdata,
-				sizeof(struct sensor_cfg_data)))
-				rc = -EFAULT;
-			break;
-
-		case CFG_GET_PREV_L_PF:
-			if (s_ctrl->func_tbl->
-			sensor_get_prev_lines_pf == NULL) {
-				rc = -EFAULT;
-				break;
-			}
-			cdata.cfg.prevl_pf =
-				s_ctrl->func_tbl->
-				sensor_get_prev_lines_pf
-				(s_ctrl);
-
-			if (copy_to_user((void *)argp,
-				&cdata,
-				sizeof(struct sensor_cfg_data)))
-				rc = -EFAULT;
-			break;
-
-		case CFG_GET_PREV_P_PL:
-			if (s_ctrl->func_tbl->
-			sensor_get_prev_pixels_pl == NULL) {
-				rc = -EFAULT;
-				break;
-			}
-			cdata.cfg.prevp_pl =
-				s_ctrl->func_tbl->
-				sensor_get_prev_pixels_pl
-				(s_ctrl);
-
-			if (copy_to_user((void *)argp,
-				&cdata,
-				sizeof(struct sensor_cfg_data)))
-				rc = -EFAULT;
-			break;
-
-		case CFG_GET_PICT_L_PF:
-			if (s_ctrl->func_tbl->
-			sensor_get_pict_lines_pf == NULL) {
-				rc = -EFAULT;
-				break;
-			}
-			cdata.cfg.pictl_pf =
-				s_ctrl->func_tbl->
-				sensor_get_pict_lines_pf
-				(s_ctrl);
-
-			if (copy_to_user((void *)argp,
-				&cdata,
-				sizeof(struct sensor_cfg_data)))
-				rc = -EFAULT;
-			break;
-
-		case CFG_GET_PICT_P_PL:
-			if (s_ctrl->func_tbl->
-			sensor_get_pict_pixels_pl == NULL) {
-				rc = -EFAULT;
-				break;
-			}
-			cdata.cfg.pictp_pl =
-				s_ctrl->func_tbl->
-				sensor_get_pict_pixels_pl
-				(s_ctrl);
-
-			if (copy_to_user((void *)argp,
-				&cdata,
-				sizeof(struct sensor_cfg_data)))
-				rc = -EFAULT;
-			break;
-
-		case CFG_GET_PICT_MAX_EXP_LC:
-			if (s_ctrl->func_tbl->
-			sensor_get_pict_max_exp_lc == NULL) {
-				rc = -EFAULT;
-				break;
-			}
-			cdata.cfg.pict_max_exp_lc =
-				s_ctrl->func_tbl->
-				sensor_get_pict_max_exp_lc
-				(s_ctrl);
-
-			if (copy_to_user((void *)argp,
-				&cdata,
-				sizeof(struct sensor_cfg_data)))
-				rc = -EFAULT;
-			break;
-
 		case CFG_SET_FPS:
 		case CFG_SET_PICT_FPS:
 			if (s_ctrl->func_tbl->
@@ -506,30 +335,9 @@
 					cdata.rs);
 			break;
 
-		case CFG_PWR_DOWN:
-			break;
-
-		case CFG_MOVE_FOCUS:
-			break;
-
-		case CFG_SET_DEFAULT_FOCUS:
-			break;
-
-		case CFG_GET_AF_MAX_STEPS:
-			cdata.max_steps = 32;
-			if (copy_to_user((void *)argp,
-				&cdata,
-				sizeof(struct sensor_cfg_data)))
-				rc = -EFAULT;
-			break;
-
 		case CFG_SET_EFFECT:
 			break;
 
-
-		case CFG_SEND_WB_INFO:
-			break;
-
 		case CFG_SENSOR_INIT:
 			if (s_ctrl->func_tbl->
 			sensor_mode_init == NULL) {
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/video/msm/sensors/msm_sensor.h
index 1121170..e4dc34f 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.h
+++ b/drivers/media/video/msm/sensors/msm_sensor.h
@@ -99,18 +99,6 @@
 	void (*sensor_group_hold_on) (struct msm_sensor_ctrl_t *);
 	void (*sensor_group_hold_off) (struct msm_sensor_ctrl_t *);
 
-	uint16_t (*sensor_get_prev_lines_pf)
-		(struct msm_sensor_ctrl_t *);
-	uint16_t (*sensor_get_prev_pixels_pl)
-		(struct msm_sensor_ctrl_t *);
-	uint16_t (*sensor_get_pict_lines_pf)
-		(struct msm_sensor_ctrl_t *);
-	uint16_t (*sensor_get_pict_pixels_pl)
-		(struct msm_sensor_ctrl_t *);
-	uint32_t (*sensor_get_pict_max_exp_lc)
-		(struct msm_sensor_ctrl_t *);
-	void (*sensor_get_pict_fps) (struct msm_sensor_ctrl_t *,
-			uint16_t, uint16_t *);
 	int32_t (*sensor_set_fps) (struct msm_sensor_ctrl_t *,
 			struct fps_cfg *);
 	int32_t (*sensor_write_exp_gain) (struct msm_sensor_ctrl_t *,
@@ -153,10 +141,7 @@
 	uint16_t curr_line_length_pclk;
 	uint16_t curr_frame_length_lines;
 
-	uint16_t fps;
 	uint32_t fps_divider;
-	enum msm_sensor_resolution_t prev_res;
-	enum msm_sensor_resolution_t pict_res;
 	enum msm_sensor_resolution_t curr_res;
 	enum msm_sensor_cam_mode_t cam_mode;
 
@@ -176,13 +161,6 @@
 void msm_sensor_group_hold_on(struct msm_sensor_ctrl_t *s_ctrl);
 void msm_sensor_group_hold_off(struct msm_sensor_ctrl_t *s_ctrl);
 
-uint16_t msm_sensor_get_prev_lines_pf(struct msm_sensor_ctrl_t *s_ctrl);
-uint16_t msm_sensor_get_prev_pixels_pl(struct msm_sensor_ctrl_t *s_ctrl);
-uint16_t msm_sensor_get_pict_lines_pf(struct msm_sensor_ctrl_t *s_ctrl);
-uint16_t msm_sensor_get_pict_pixels_pl(struct msm_sensor_ctrl_t *s_ctrl);
-uint32_t msm_sensor_get_pict_max_exp_lc(struct msm_sensor_ctrl_t *s_ctrl);
-void msm_sensor_get_pict_fps(struct msm_sensor_ctrl_t *s_ctrl,
-			uint16_t fps, uint16_t *pfps);
 int32_t msm_sensor_set_fps(struct msm_sensor_ctrl_t *s_ctrl,
 			struct fps_cfg   *fps);
 int32_t msm_sensor_write_exp_gain1(struct msm_sensor_ctrl_t *s_ctrl,
diff --git a/drivers/media/video/msm/sensors/ov2720.c b/drivers/media/video/msm/sensors/ov2720.c
index bdad57c..5938406 100644
--- a/drivers/media/video/msm/sensors/ov2720.c
+++ b/drivers/media/video/msm/sensors/ov2720.c
@@ -477,12 +477,6 @@
 	.sensor_stop_stream = msm_sensor_stop_stream,
 	.sensor_group_hold_on = msm_sensor_group_hold_on,
 	.sensor_group_hold_off = msm_sensor_group_hold_off,
-	.sensor_get_prev_lines_pf = msm_sensor_get_prev_lines_pf,
-	.sensor_get_prev_pixels_pl = msm_sensor_get_prev_pixels_pl,
-	.sensor_get_pict_lines_pf = msm_sensor_get_pict_lines_pf,
-	.sensor_get_pict_pixels_pl = msm_sensor_get_pict_pixels_pl,
-	.sensor_get_pict_max_exp_lc = msm_sensor_get_pict_max_exp_lc,
-	.sensor_get_pict_fps = msm_sensor_get_pict_fps,
 	.sensor_set_fps = msm_sensor_set_fps,
 	.sensor_write_exp_gain = ov2720_write_exp_gain,
 	.sensor_write_snapshot_exp_gain = ov2720_write_exp_gain,
diff --git a/drivers/mfd/pm8018-core.c b/drivers/mfd/pm8018-core.c
index 528f232..8d89568 100644
--- a/drivers/mfd/pm8018-core.c
+++ b/drivers/mfd/pm8018-core.c
@@ -29,6 +29,7 @@
 #define REG_HWREV_2		0x0E8  /* PMIC4 revision 2 */
 
 #define REG_MPP_BASE		0x050
+#define REG_IRQ_BASE		0x1BB
 
 #define REG_RTC_BASE		0x11D
 
@@ -237,6 +238,7 @@
 
 	if (pdata->irq_pdata) {
 		pdata->irq_pdata->irq_cdata.nirqs = PM8018_NR_IRQS;
+		pdata->irq_pdata->irq_cdata.base_addr = REG_IRQ_BASE;
 		irq_base = pdata->irq_pdata->irq_base;
 		irq_chip = pm8xxx_irq_init(pmic->dev, pdata->irq_pdata);
 
diff --git a/drivers/mfd/pm8821-core.c b/drivers/mfd/pm8821-core.c
index ed29785..8a556bd 100644
--- a/drivers/mfd/pm8821-core.c
+++ b/drivers/mfd/pm8821-core.c
@@ -26,6 +26,7 @@
 #define REG_HWREV_2		0x0E8  /* PMIC4 revision 2 */
 
 #define REG_MPP_BASE		0x050
+#define REG_IRQ_BASE		0x1BB
 
 #define PM8821_VERSION_MASK	0xFFF0
 #define PM8821_VERSION_VALUE	0x07F0
@@ -150,6 +151,7 @@
 
 	if (pdata->irq_pdata) {
 		pdata->irq_pdata->irq_cdata.nirqs = PM8821_NR_IRQS;
+		pdata->irq_pdata->irq_cdata.base_addr = REG_IRQ_BASE;
 		irq_base = pdata->irq_pdata->irq_base;
 		irq_chip = pm8xxx_irq_init(pmic->dev, pdata->irq_pdata);
 
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index b72ceb3..d225dfa 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -27,6 +27,7 @@
 #define REG_HWREV_2		0x0E8  /* PMIC4 revision 2 */
 
 #define REG_MPP_BASE		0x050
+#define REG_IRQ_BASE		0x1BB
 
 #define REG_TEMP_ALARM_CTRL	0x1B
 #define REG_TEMP_ALARM_PWM	0x9B
@@ -368,6 +369,7 @@
 
 	if (pdata->irq_pdata) {
 		pdata->irq_pdata->irq_cdata.nirqs = PM8921_NR_IRQS;
+		pdata->irq_pdata->irq_cdata.base_addr = REG_IRQ_BASE;
 		irq_base = pdata->irq_pdata->irq_base;
 		irq_chip = pm8xxx_irq_init(pmic->dev, pdata->irq_pdata);
 
diff --git a/drivers/mfd/pm8xxx-irq.c b/drivers/mfd/pm8xxx-irq.c
index c6221b8..5864b85 100644
--- a/drivers/mfd/pm8xxx-irq.c
+++ b/drivers/mfd/pm8xxx-irq.c
@@ -24,17 +24,15 @@
 
 /* PMIC8xxx IRQ */
 
-#define	SSBI_REG_ADDR_IRQ_BASE		0x1BB
-
-#define	SSBI_REG_ADDR_IRQ_ROOT		(SSBI_REG_ADDR_IRQ_BASE + 0)
-#define	SSBI_REG_ADDR_IRQ_M_STATUS1	(SSBI_REG_ADDR_IRQ_BASE + 1)
-#define	SSBI_REG_ADDR_IRQ_M_STATUS2	(SSBI_REG_ADDR_IRQ_BASE + 2)
-#define	SSBI_REG_ADDR_IRQ_M_STATUS3	(SSBI_REG_ADDR_IRQ_BASE + 3)
-#define	SSBI_REG_ADDR_IRQ_M_STATUS4	(SSBI_REG_ADDR_IRQ_BASE + 4)
-#define	SSBI_REG_ADDR_IRQ_BLK_SEL	(SSBI_REG_ADDR_IRQ_BASE + 5)
-#define	SSBI_REG_ADDR_IRQ_IT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 6)
-#define	SSBI_REG_ADDR_IRQ_CONFIG	(SSBI_REG_ADDR_IRQ_BASE + 7)
-#define	SSBI_REG_ADDR_IRQ_RT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 8)
+#define SSBI_REG_ADDR_IRQ_ROOT(base)		(base + 0)
+#define SSBI_REG_ADDR_IRQ_M_STATUS1(base)	(base + 1)
+#define SSBI_REG_ADDR_IRQ_M_STATUS2(base)	(base + 2)
+#define SSBI_REG_ADDR_IRQ_M_STATUS3(base)	(base + 3)
+#define SSBI_REG_ADDR_IRQ_M_STATUS4(base)	(base + 4)
+#define SSBI_REG_ADDR_IRQ_BLK_SEL(base)		(base + 5)
+#define SSBI_REG_ADDR_IRQ_IT_STATUS(base)	(base + 6)
+#define SSBI_REG_ADDR_IRQ_CONFIG(base)		(base + 7)
+#define SSBI_REG_ADDR_IRQ_RT_STATUS(base)	(base + 8)
 
 #define	PM_IRQF_LVL_SEL			0x01	/* level select */
 #define	PM_IRQF_MASK_FE			0x02	/* mask falling edge */
@@ -50,6 +48,7 @@
 struct pm_irq_chip {
 	struct device		*dev;
 	spinlock_t		pm_irq_lock;
+	unsigned int		base_addr;
 	unsigned int		devirq;
 	unsigned int		irq_base;
 	unsigned int		num_irqs;
@@ -60,13 +59,14 @@
 
 static int pm8xxx_read_root_irq(const struct pm_irq_chip *chip, u8 *rp)
 {
-	return pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_ROOT, rp);
+	return pm8xxx_readb(chip->dev,
+			SSBI_REG_ADDR_IRQ_ROOT(chip->base_addr), rp);
 }
 
 static int pm8xxx_read_master_irq(const struct pm_irq_chip *chip, u8 m, u8 *bp)
 {
 	return pm8xxx_readb(chip->dev,
-			SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp);
+			SSBI_REG_ADDR_IRQ_M_STATUS1(chip->base_addr) + m, bp);
 }
 
 static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, u8 bp, u8 *ip)
@@ -74,13 +74,15 @@
 	int	rc;
 
 	spin_lock(&chip->pm_irq_lock);
-	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
+	rc = pm8xxx_writeb(chip->dev,
+			SSBI_REG_ADDR_IRQ_BLK_SEL(chip->base_addr), bp);
 	if (rc) {
 		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
 		goto bail;
 	}
 
-	rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
+	rc = pm8xxx_readb(chip->dev,
+			SSBI_REG_ADDR_IRQ_IT_STATUS(chip->base_addr), ip);
 	if (rc)
 		pr_err("Failed Reading Status rc=%d\n", rc);
 bail:
@@ -93,17 +95,20 @@
 	int	rc;
 
 	spin_lock(&chip->pm_irq_lock);
-	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
+	rc = pm8xxx_writeb(chip->dev,
+			SSBI_REG_ADDR_IRQ_BLK_SEL(chip->base_addr), bp);
 	if (rc) {
 		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
 		goto bail;
 	}
 
-	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp);
+	rc = pm8xxx_writeb(chip->dev,
+			SSBI_REG_ADDR_IRQ_CONFIG(chip->base_addr), cp);
 	if (rc)
 		pr_err("Failed Configuring IRQ rc=%d\n", rc);
 
-	rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, r);
+	rc = pm8xxx_readb(chip->dev,
+			SSBI_REG_ADDR_IRQ_CONFIG(chip->base_addr), r);
 	if (rc)
 		pr_err("Failed reading IRQ rc=%d\n", rc);
 bail:
@@ -116,14 +121,16 @@
 	int	rc;
 
 	spin_lock(&chip->pm_irq_lock);
-	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
+	rc = pm8xxx_writeb(chip->dev,
+			SSBI_REG_ADDR_IRQ_BLK_SEL(chip->base_addr), bp);
 	if (rc) {
 		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
 		goto bail;
 	}
 
 	cp |= PM_IRQF_WRITE;
-	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp);
+	rc = pm8xxx_writeb(chip->dev,
+			SSBI_REG_ADDR_IRQ_CONFIG(chip->base_addr), cp);
 	if (rc)
 		pr_err("Failed Configuring IRQ rc=%d\n", rc);
 bail:
@@ -335,14 +342,16 @@
 
 	spin_lock_irqsave(&chip->pm_irq_lock, flags);
 
-	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
+	rc = pm8xxx_writeb(chip->dev,
+			SSBI_REG_ADDR_IRQ_BLK_SEL(chip->base_addr), block);
 	if (rc) {
 		pr_err("Failed Selecting block irq=%d pmirq=%d blk=%d rc=%d\n",
 			irq, pmirq, block, rc);
 		goto bail_out;
 	}
 
-	rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
+	rc = pm8xxx_readb(chip->dev,
+			SSBI_REG_ADDR_IRQ_RT_STATUS(chip->base_addr), &bits);
 	if (rc) {
 		pr_err("Failed Configuring irq=%d pmirq=%d blk=%d rc=%d\n",
 			irq, pmirq, block, rc);
@@ -388,6 +397,7 @@
 	chip->devirq = devirq;
 	chip->irq_base = pdata->irq_base;
 	chip->num_irqs = pdata->irq_cdata.nirqs;
+	chip->base_addr = pdata->irq_cdata.base_addr;
 	chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
 	chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
 	spin_lock_init(&chip->pm_irq_lock);
diff --git a/drivers/mfd/pmic8058.c b/drivers/mfd/pmic8058.c
index 77e393e..ae721e4 100644
--- a/drivers/mfd/pmic8058.c
+++ b/drivers/mfd/pmic8058.c
@@ -25,6 +25,7 @@
 #include <linux/msm_adc.h>
 
 #define REG_MPP_BASE			0x50
+#define REG_IRQ_BASE			0x1BB
 
 /* PMIC8058 Revision */
 #define PM8058_REG_REV			0x002  /* PMIC4 revision */
@@ -901,6 +902,7 @@
 
 	if (pdata->irq_pdata) {
 		pdata->irq_pdata->irq_cdata.nirqs = PM8058_NR_IRQS;
+		pdata->irq_pdata->irq_cdata.base_addr = REG_IRQ_BASE;
 		irq_base = pdata->irq_pdata->irq_base;
 		irq_chip = pm8xxx_irq_init(pmic->dev, pdata->irq_pdata);
 
diff --git a/drivers/mfd/wcd9310-core.c b/drivers/mfd/wcd9310-core.c
index 8eca7aa..aabc2cc 100644
--- a/drivers/mfd/wcd9310-core.c
+++ b/drivers/mfd/wcd9310-core.c
@@ -22,10 +22,25 @@
 #include <linux/gpio.h>
 #include <linux/debugfs.h>
 #include <linux/regulator/consumer.h>
+#include <linux/i2c.h>
 #include <sound/soc.h>
 
 #define TABLA_SLIM_GLA_MAX_RETRIES 5
 #define TABLA_REGISTER_START_OFFSET 0x800
+
+#define MAX_TABLA_DEVICE	4
+#define TABLA_I2C_MODE	0x03
+
+struct tabla_i2c {
+	struct i2c_client *client;
+	struct i2c_msg xfer_msg[2];
+	struct mutex xfer_lock;
+	int mod_id;
+};
+
+struct tabla_i2c tabla_modules[MAX_TABLA_DEVICE];
+static int tabla_intf;
+
 static int tabla_read(struct tabla *tabla, unsigned short reg,
 		       int bytes, void *dest, bool interface_reg)
 {
@@ -566,6 +581,214 @@
 	kfree(tabla->supplies);
 }
 
+int tabla_get_intf_type(void)
+{
+	return tabla_intf;
+}
+EXPORT_SYMBOL_GPL(tabla_get_intf_type);
+
+struct tabla_i2c *get_i2c_tabla_device_info(u16 reg)
+{
+	u16 mask = 0x0f00;
+	int value = 0;
+	struct tabla_i2c *tabla = NULL;
+	value = ((reg & mask) >> 8) & 0x000f;
+	switch (value) {
+	case 0:
+		tabla = &tabla_modules[0];
+		break;
+	case 1:
+		tabla = &tabla_modules[1];
+		break;
+	case 2:
+		tabla = &tabla_modules[2];
+		break;
+	case 3:
+		tabla = &tabla_modules[3];
+		break;
+	default:
+		break;
+	}
+	return tabla;
+}
+
+int tabla_i2c_write_device(u16 reg, u8 *value,
+				u32 bytes)
+{
+
+	struct i2c_msg *msg;
+	int ret = 0;
+	u8 reg_addr = 0;
+	u8 data[bytes + 1];
+	struct tabla_i2c *tabla;
+
+	tabla = get_i2c_tabla_device_info(reg);
+	if (tabla->client == NULL) {
+		pr_err("failed to get device info\n");
+		return -ENODEV;
+	}
+	reg_addr = (u8)reg;
+	msg = &tabla->xfer_msg[0];
+	msg->addr = tabla->client->addr;
+	msg->len = bytes + 1;
+	msg->flags = 0;
+	data[0] = reg;
+	data[1] = *value;
+	msg->buf = data;
+	ret = i2c_transfer(tabla->client->adapter, tabla->xfer_msg, 1);
+	/* Try again if the write fails */
+	if (ret != 1) {
+		ret = i2c_transfer(tabla->client->adapter,
+						tabla->xfer_msg, 1);
+		if (ret != 1) {
+			pr_err("failed to write the device\n");
+			return ret;
+		}
+	}
+	pr_debug("write sucess register = %x val = %x\n", reg, data[1]);
+	return 0;
+}
+
+
+int tabla_i2c_read_device(unsigned short reg,
+				  int bytes, unsigned char *dest)
+{
+	struct i2c_msg *msg;
+	int ret = 0;
+	u8 reg_addr = 0;
+	struct tabla_i2c *tabla;
+	u8 i = 0;
+
+	tabla = get_i2c_tabla_device_info(reg);
+	if (tabla->client == NULL) {
+		pr_err("failed to get device info\n");
+		return -ENODEV;
+	}
+	for (i = 0; i < bytes; i++) {
+		reg_addr = (u8)reg++;
+		msg = &tabla->xfer_msg[0];
+		msg->addr = tabla->client->addr;
+		msg->len = 1;
+		msg->flags = 0;
+		msg->buf = &reg_addr;
+
+		msg = &tabla->xfer_msg[1];
+		msg->addr = tabla->client->addr;
+		msg->len = 1;
+		msg->flags = I2C_M_RD;
+		msg->buf = dest++;
+		ret = i2c_transfer(tabla->client->adapter, tabla->xfer_msg, 2);
+
+		/* Try again if read fails first time */
+		if (ret != 2) {
+			ret = i2c_transfer(tabla->client->adapter,
+							tabla->xfer_msg, 2);
+			if (ret != 2) {
+				pr_err("failed to read tabla register\n");
+				return ret;
+			}
+		}
+	}
+	return 0;
+}
+
+int tabla_i2c_read(struct tabla *tabla, unsigned short reg,
+			int bytes, void *dest, bool interface_reg)
+{
+	return tabla_i2c_read_device(reg, bytes, dest);
+}
+
+int tabla_i2c_write(struct tabla *tabla, unsigned short reg,
+			 int bytes, void *src, bool interface_reg)
+{
+	return tabla_i2c_write_device(reg, src, bytes);
+}
+
+static int __devinit tabla_i2c_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct tabla *tabla;
+	struct tabla_pdata *pdata = client->dev.platform_data;
+	int val = 0;
+	int ret = 0;
+	static int device_id;
+
+	if (device_id > 0) {
+		tabla_modules[device_id++].client = client;
+		pr_info("probe for other slaves devices of tabla\n");
+		return ret;
+	}
+
+	tabla = kzalloc(sizeof(struct tabla), GFP_KERNEL);
+	if (tabla == NULL) {
+		pr_err("%s: error, allocation failed\n", __func__);
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	if (!pdata) {
+		dev_dbg(&client->dev, "no platform data?\n");
+		ret = -EINVAL;
+		goto fail;
+	}
+	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
+		dev_dbg(&client->dev, "can't talk I2C?\n");
+		ret = -EIO;
+		goto fail;
+	}
+	tabla->dev = &client->dev;
+	tabla->reset_gpio = pdata->reset_gpio;
+
+	ret = tabla_enable_supplies(tabla);
+	if (ret) {
+		pr_err("%s: Fail to enable Tabla supplies\n", __func__);
+		goto err_tabla;
+	}
+
+	usleep_range(5, 5);
+	ret = tabla_reset(tabla);
+	if (ret) {
+		pr_err("%s: Resetting Tabla failed\n", __func__);
+		goto err_supplies;
+	}
+	tabla_modules[device_id++].client = client;
+
+	tabla->read_dev = tabla_i2c_read;
+	tabla->write_dev = tabla_i2c_write;
+	tabla->irq = pdata->irq;
+	tabla->irq_base = pdata->irq_base;
+
+	/*read the tabla status before initializing the device type*/
+	ret = tabla_read(tabla, TABLA_A_CHIP_STATUS, 1, &val, 0);
+	if ((ret < 0) || (val != TABLA_I2C_MODE)) {
+		pr_err("failed to read the tabla status\n");
+		goto err_device_init;
+	}
+
+	ret = tabla_device_init(tabla, tabla->irq);
+	if (ret) {
+		pr_err("%s: error, initializing device failed\n", __func__);
+		goto err_device_init;
+	}
+	tabla_intf = TABLA_INTERFACE_TYPE_I2C;
+
+	return ret;
+err_device_init:
+	tabla_free_reset(tabla);
+err_supplies:
+	tabla_disable_supplies(tabla);
+err_tabla:
+	kfree(tabla);
+fail:
+	return ret;
+}
+
+static int __devexit tabla_i2c_remove(struct i2c_client *client)
+{
+	pr_debug("exit\n");
+	return 0;
+}
+
 static int tabla_slim_probe(struct slim_device *slim)
 {
 	struct tabla *tabla;
@@ -600,7 +823,7 @@
 
 	ret = tabla_enable_supplies(tabla);
 	if (ret) {
-		pr_info("%s: Fail to enable Tabla supplies\n", __func__);
+		pr_err("%s: Fail to enable Tabla supplies\n", __func__);
 		goto err_tabla;
 	}
 	usleep_range(5, 5);
@@ -661,6 +884,7 @@
 		break;
 	}
 	tabla_inf_la = tabla->slim_slave->laddr;
+	tabla_intf = TABLA_INTERFACE_TYPE_SLIMBUS;
 
 	ret = tabla_device_init(tabla, tabla->irq);
 	if (ret) {
@@ -744,9 +968,33 @@
 	.id_table = slimtest2x_id,
 };
 
+#define TABLA_I2C_TOP_LEVEL 0
+#define TABLA_I2C_ANALOG       1
+#define TABLA_I2C_DIGITAL_1    2
+#define TABLA_I2C_DIGITAL_2    3
+
+static struct i2c_device_id tabla_id_table[] = {
+	{"tabla top level", TABLA_I2C_TOP_LEVEL},
+	{"tabla analog", TABLA_I2C_TOP_LEVEL},
+	{"tabla digital1", TABLA_I2C_TOP_LEVEL},
+	{"tabla digital2", TABLA_I2C_TOP_LEVEL},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, tabla_id_table);
+
+static struct i2c_driver tabla_i2c_driver = {
+	.driver                 = {
+		.owner          =       THIS_MODULE,
+		.name           =       "tabla-i2c-core",
+	},
+	.id_table               =       tabla_id_table,
+	.probe                  =       tabla_i2c_probe,
+	.remove                 =       __devexit_p(tabla_i2c_remove),
+};
+
 static int __init tabla_init(void)
 {
-	int ret1, ret2;
+	int ret1, ret2, ret3;
 
 	ret1 = slim_driver_register(&tabla_slim_driver);
 	if (ret1 != 0)
@@ -756,7 +1004,11 @@
 	if (ret2 != 0)
 		pr_err("Failed to register tabla2x SB driver: %d\n", ret2);
 
-	return (ret1 && ret2) ? -1 : 0;
+	ret3 = i2c_add_driver(&tabla_i2c_driver);
+	if (ret3 != 0)
+		pr_err("failed to add the I2C driver\n");
+
+	return (ret1 && ret2 && ret3) ? -1 : 0;
 }
 module_init(tabla_init);
 
diff --git a/drivers/mfd/wcd9310-irq.c b/drivers/mfd/wcd9310-irq.c
index bc7841e..9cc4761 100644
--- a/drivers/mfd/wcd9310-irq.c
+++ b/drivers/mfd/wcd9310-irq.c
@@ -110,11 +110,19 @@
 				(i >= TABLA_IRQ_MBHC_REMOVAL)) {
 				tabla_reg_write(tabla, TABLA_A_INTR_CLEAR0 +
 					BIT_BYTE(i), BYTE_BIT_MASK(i));
+				if (tabla_get_intf_type() ==
+					TABLA_INTERFACE_TYPE_I2C)
+					tabla_reg_write(tabla,
+						TABLA_A_INTR_MODE, 0x02);
 				handle_nested_irq(tabla->irq_base + i);
 			} else {
 				handle_nested_irq(tabla->irq_base + i);
 				tabla_reg_write(tabla, TABLA_A_INTR_CLEAR0 +
 					BIT_BYTE(i), BYTE_BIT_MASK(i));
+				if (tabla_get_intf_type() ==
+					TABLA_INTERFACE_TYPE_I2C)
+					tabla_reg_write(tabla,
+						TABLA_A_INTR_MODE, 0x02);
 			}
 			break;
 		}
diff --git a/drivers/misc/pmem.c b/drivers/misc/pmem.c
index b94de48..692849a 100644
--- a/drivers/misc/pmem.c
+++ b/drivers/misc/pmem.c
@@ -1970,6 +1970,13 @@
 	if (!file)
 		return -EBADF;
 
+	/*
+	 * check that the vaddr passed for flushing is valid
+	 * so that you don't crash the kernel
+	 */
+	if (!pmem_addr->vaddr)
+		return -EINVAL;
+
 	data = file->private_data;
 	id = get_id(file);
 
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 4c6c8b8..6b856b2 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1646,6 +1646,9 @@
 				 * without the need of sending dummy CMD52.
 				 */
 				host->curr.wait_for_auto_prog_done = 1;
+		} else if (mrq->cmd->opcode == MMC_WRITE_BLOCK &&
+				host->sdcc_version) {
+			host->curr.wait_for_auto_prog_done = 1;
 		}
 	}
 
@@ -4286,7 +4289,6 @@
 			enable_irq(host->core_irqres->start);
 			host->sdcc_irq_disabled = 0;
 		}
-		wake_lock_timeout(&host->sdio_wlock, 1);
 	}
 	spin_unlock_irqrestore(&host->lock, flags);
 	return 0;
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 2019913..580da82 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -374,7 +374,12 @@
 
 static inline int msmsdcc_lpm_disable(struct mmc_host *mmc)
 {
-	return msmsdcc_sdio_al_lpm(mmc, false);
+	struct msmsdcc_host *host = mmc_priv(mmc);
+	int ret;
+
+	ret = msmsdcc_sdio_al_lpm(mmc, false);
+	wake_unlock(&host->sdio_wlock);
+	return ret;
 }
 #endif
 
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index af44f45..552ed82 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -19,6 +19,7 @@
 #include <linux/mfd/pm8xxx/pm8921-charger.h>
 #include <linux/mfd/pm8xxx/pm8921-bms.h>
 #include <linux/mfd/pm8xxx/pm8921-adc.h>
+#include <linux/mfd/pm8xxx/ccadc.h>
 #include <linux/mfd/pm8xxx/core.h>
 #include <linux/interrupt.h>
 #include <linux/power_supply.h>
@@ -937,10 +938,28 @@
 	return (int)result.physical;
 }
 
+static unsigned int voltage_based_capacity(struct pm8921_chg_chip *chip)
+{
+	unsigned int current_voltage = get_prop_battery_mvolts(chip);
+	unsigned int low_voltage = chip->min_voltage;
+	unsigned int high_voltage = chip->max_voltage;
+
+	if (current_voltage <= low_voltage)
+		return 0;
+	else if (current_voltage >= high_voltage)
+		return 100;
+	else
+		return (current_voltage - low_voltage) * 100
+		    / (high_voltage - low_voltage);
+}
+
 static int get_prop_batt_capacity(struct pm8921_chg_chip *chip)
 {
 	int percent_soc = pm8921_bms_get_percent_charge();
 
+	if (percent_soc == -ENXIO)
+		percent_soc = voltage_based_capacity(chip);
+
 	if (percent_soc <= 10)
 		pr_warn("low battery charge = %d%%\n", percent_soc);
 
@@ -952,6 +971,10 @@
 	int result_ma, rc;
 
 	rc = pm8921_bms_get_battery_current(&result_ma);
+	if (rc == -ENXIO) {
+		rc = pm8xxx_ccadc_get_battery_current(&result_ma);
+	}
+
 	if (rc) {
 		pr_err("unable to get batt current rc = %d\n", rc);
 		return rc;
@@ -1020,6 +1043,13 @@
 	int fsm_state = pm_chg_get_fsm_state(chip);
 	int i;
 
+	if (chip->ext) {
+		if (chip->ext_charge_done)
+			return POWER_SUPPLY_STATUS_FULL;
+		if (chip->ext_charging)
+			return POWER_SUPPLY_STATUS_CHARGING;
+	}
+
 	for (i = 0; i < ARRAY_SIZE(map); i++)
 		if (map[i].fsm_state == fsm_state)
 			batt_state = map[i].batt_state;
@@ -1337,6 +1367,7 @@
 		notify_usb_of_the_plugin_event(usb_present);
 		chip->usb_present = usb_present;
 		power_supply_changed(&chip->usb_psy);
+		power_supply_changed(&chip->batt_psy);
 	}
 	bms_notify_check(chip);
 }
@@ -1355,6 +1386,7 @@
 
 	chip->ext->stop_charging(chip->ext->ctx);
 	chip->ext_charging = false;
+	chip->ext_charge_done = false;
 }
 
 static void handle_start_ext_chg(struct pm8921_chg_chip *chip)
@@ -1420,6 +1452,7 @@
 	if (chip->dc_present ^ dc_present) {
 		chip->dc_present = dc_present;
 		power_supply_changed(&chip->dc_psy);
+		power_supply_changed(&chip->batt_psy);
 	}
 	bms_notify_check(chip);
 }
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 3467e0d..e11339c 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -49,6 +49,8 @@
 #define MSM_HDMI_SAMPLE_RATE_MAX		7
 #define MSM_HDMI_SAMPLE_RATE_FORCE_32BIT	0x7FFFFFFF
 
+static int msm_hdmi_sample_rate = MSM_HDMI_SAMPLE_RATE_48KHZ;
+
 struct workqueue_struct *hdmi_work_queue;
 struct hdmi_msm_state_type *hdmi_msm_state;
 
@@ -3331,6 +3333,19 @@
 }
 #endif
 
+int hdmi_msm_audio_get_sample_rate(void)
+{
+	return msm_hdmi_sample_rate;
+}
+EXPORT_SYMBOL(hdmi_msm_audio_get_sample_rate);
+
+void hdmi_msm_audio_sample_rate_reset(int rate)
+{
+	msm_hdmi_sample_rate = rate;
+	hdcp_deauthenticate();
+}
+EXPORT_SYMBOL(hdmi_msm_audio_sample_rate_reset);
+
 static void hdmi_msm_audio_setup(void)
 {
 	const int channels = MSM_HDMI_AUDIO_CHANNEL_2;
@@ -3344,7 +3359,7 @@
 	DEV_DBG("Not setting ACP, ISRC1, ISRC2 packets\n");
 	hdmi_msm_audio_acr_setup(TRUE,
 		external_common_state->video_resolution,
-		MSM_HDMI_SAMPLE_RATE_48KHZ, channels);
+		msm_hdmi_sample_rate, channels);
 	hdmi_msm_audio_info_setup(TRUE, channels, 0, FALSE);
 
 	/* Turn on Audio FIFO and SAM DROP ISR */
@@ -3682,7 +3697,27 @@
 static void hdmi_msm_turn_on(void)
 {
 	uint32 hpd_ctrl;
+	uint32 audio_pkt_ctrl, audio_cfg;
+	/*
+	 * Number of wait iterations for QDSP to disable Audio Engine
+	 * before resetting HDMI core
+	 */
+	int i = 10;
+	audio_pkt_ctrl = HDMI_INP_ND(0x0020);
+	audio_cfg = HDMI_INP_ND(0x01D0);
 
+	/*
+	 * Checking BIT[0] of AUDIO PACKET CONTROL and
+	 * AUDIO CONFIGURATION register
+	 */
+	while (((audio_pkt_ctrl & 0x00000001) || (audio_cfg & 0x00000001))
+		&& (i--)) {
+		audio_pkt_ctrl = HDMI_INP_ND(0x0020);
+		audio_cfg = HDMI_INP_ND(0x01D0);
+		DEV_DBG("%d times :: HDMI AUDIO PACKET is %08x and "
+			"AUDIO CFG is %08x", i, audio_pkt_ctrl, audio_cfg);
+		msleep(20);
+	}
 	hdmi_msm_reset_core();
 	hdmi_msm_init_phy(external_common_state->video_resolution);
 	/* HDMI_USEC_REFTIMER[0x0208] */
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index ad7fc04..a511e3c 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -35,6 +35,10 @@
 #define MDP4_RGB_BASE 0x40000
 #define MDP4_RGB_OFF 0x10000
 
+/* chip select controller */
+#define CS_CONTROLLER_0 0x0707ffff
+#define CS_CONTROLLER_1 0x03073f3f
+
 enum {
 	OVERLAY_PERF_LEVEL1 = 1,
 	OVERLAY_PERF_LEVEL2,
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 1b80d4c..383a16d 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -43,11 +43,13 @@
 struct mdp4_overlay_ctrl {
 	struct mdp4_overlay_pipe plist[OVERLAY_PIPE_MAX];
 	struct mdp4_overlay_pipe *stage[MDP4_MIXER_MAX][MDP4_MIXER_STAGE_MAX];
+	uint32 cs_controller;
 	uint32 panel_3d;
 	uint32 panel_mode;
 	uint32 mixer0_played;
 	uint32 mixer1_played;
 } mdp4_overlay_db = {
+	.cs_controller = CS_CONTROLLER_0,
 	.plist = {
 		{
 			.pipe_type = OVERLAY_TYPE_RGB,
@@ -484,6 +486,7 @@
 	char *vg_base;
 	uint32 frame_size, src_size, src_xy, dst_size, dst_xy;
 	uint32 format, pattern, luma_offset, chroma_offset;
+	uint32 mask;
 	int pnum, ptype;
 
 	pnum = pipe->pipe_num - OVERLAY_PIPE_VG1; /* start from 0 */
@@ -574,6 +577,24 @@
 									1));
 	}
 
+	if (mdp_rev > MDP_REV_41) {
+		/* mdp chip select controller */
+		mask = 0;
+		if (pipe->pipe_num == OVERLAY_PIPE_VG1)
+			mask = 0x020; /* bit 5 */
+		else if (pipe->pipe_num == OVERLAY_PIPE_VG2)
+			mask = 0x02000; /* bit 13 */
+		if (mask) {
+			if (pipe->op_mode & MDP4_OP_SCALEY_MN_PHASE)
+				ctrl->cs_controller &= ~mask;
+			else
+				ctrl->cs_controller |= mask;
+			/* NOT double buffered */
+			outpdw(MDP_BASE + 0x00c0, ctrl->cs_controller);
+		}
+	}
+
+
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 
 	mdp4_stat.pipe[pipe->pipe_num]++;
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 143df46..770424a 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -615,10 +615,21 @@
 void mdp4_dsi_cmd_kickoff_video(struct msm_fb_data_type *mfd,
 				struct mdp4_overlay_pipe *pipe)
 {
+	/*
+	 * a video kickoff may happen before UI kickoff after
+	 * blt enabled. mdp4_overlay_update_dsi_cmd() need
+	 * to be called before kickoff.
+	 * vice versa for blt disabled.
+	 */
 	if (dsi_pipe->blt_addr && dsi_pipe->blt_cnt == 0)
-		mdp4_overlay_update_dsi_cmd(mfd);
+		mdp4_overlay_update_dsi_cmd(mfd); /* first time */
+	else if (dsi_pipe->blt_addr == 0  && dsi_pipe->blt_cnt) {
+		mdp4_overlay_update_dsi_cmd(mfd); /* last time */
+		dsi_pipe->blt_cnt = 0;
+	}
 
-	pr_debug("%s: pid=%d\n", __func__, current->pid);
+	pr_debug("%s: blt_addr=%d blt_cnt=%d\n",
+		__func__, (int)dsi_pipe->blt_addr, dsi_pipe->blt_cnt);
 
 	if (dsi_pipe->blt_addr)
 		mdp4_dsi_blt_dmap_busy_wait(dsi_mfd);
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 8370208..f96c7ea 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -258,6 +258,12 @@
 	mdp4_sw_reset(0x17);
 #endif
 
+	if (mdp_rev > MDP_REV_41) {
+		/* mdp chip select controller */
+		outpdw(MDP_BASE + 0x00c0, CS_CONTROLLER_0);
+		outpdw(MDP_BASE + 0x00c4, CS_CONTROLLER_1);
+	}
+
 	mdp4_clear_lcdc();
 
 	mdp4_mixer_blend_init(0);
diff --git a/include/linux/mfd/pm8xxx/irq.h b/include/linux/mfd/pm8xxx/irq.h
index 4e2570c..1e1fe6c 100644
--- a/include/linux/mfd/pm8xxx/irq.h
+++ b/include/linux/mfd/pm8xxx/irq.h
@@ -24,6 +24,7 @@
 struct pm8xxx_irq_core_data {
 	u32		rev;
 	int		nirqs;
+	unsigned int	base_addr;
 };
 
 struct pm8xxx_irq_platform_data {
diff --git a/include/linux/mfd/wcd9310/core.h b/include/linux/mfd/wcd9310/core.h
index 2d03c95..0eb875c 100644
--- a/include/linux/mfd/wcd9310/core.h
+++ b/include/linux/mfd/wcd9310/core.h
@@ -19,6 +19,9 @@
 
 #define TABLA_SLIM_NUM_PORT_REG 3
 
+#define TABLA_INTERFACE_TYPE_SLIMBUS	0x00
+#define TABLA_INTERFACE_TYPE_I2C	0x01
+
 enum {
 	TABLA_IRQ_SLIMBUS = 0,
 	TABLA_IRQ_MBHC_REMOVAL,
@@ -82,6 +85,7 @@
 int tabla_irq_init(struct tabla *tabla);
 void tabla_irq_exit(struct tabla *tabla);
 int tabla_get_logical_addresses(u8 *pgd_la, u8 *inf_la);
+int tabla_get_intf_type(void);
 
 static inline int tabla_request_irq(struct tabla *tabla, int irq,
 				     irq_handler_t handler, const char *name,
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 9db6bc6..273850f 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -2,7 +2,7 @@
 #define _MSM_KGSL_H
 
 #define KGSL_VERSION_MAJOR        3
-#define KGSL_VERSION_MINOR        7
+#define KGSL_VERSION_MINOR        8
 
 /*context flags */
 #define KGSL_CONTEXT_SAVE_GMEM	1
@@ -427,6 +427,30 @@
 #define IOCTL_KGSL_CFF_SYNCMEM \
 	_IOW(KGSL_IOC_TYPE, 0x30, struct kgsl_cff_syncmem)
 
+/*
+ * A timestamp event allows the user space to register an action following an
+ * expired timestamp.
+ */
+
+struct kgsl_timestamp_event {
+	int type;                /* Type of event (see list below) */
+	unsigned int timestamp;  /* Timestamp to trigger event on */
+	unsigned int context_id; /* Context for the timestamp */
+	void *priv;              /* Pointer to the event specific blob */
+	size_t len;              /* Size of the event specific blob */
+};
+
+#define IOCTL_KGSL_TIMESTAMP_EVENT \
+	_IOW(KGSL_IOC_TYPE, 0x31, struct kgsl_timestamp_event)
+
+/* A genlock timestamp event releases an existing lock on timestamp expire */
+
+#define KGSL_TIMESTAMP_EVENT_GENLOCK 1
+
+struct kgsl_timestamp_event_genlock {
+	int handle; /* Handle of the genlock lock to release */
+};
+
 #ifdef __KERNEL__
 #ifdef CONFIG_MSM_KGSL_DRM
 int kgsl_gem_obj_addr(int drm_fd, int handle, unsigned long *start,
diff --git a/include/media/tavarua.h b/include/media/tavarua.h
index aafa5d0..43ce153 100644
--- a/include/media/tavarua.h
+++ b/include/media/tavarua.h
@@ -41,6 +41,12 @@
 #define MPX_DCC_PEEK_MSB_REG3      (0x88)
 #define MPX_DCC_PEEK_LSB_REG3      (0xC4)
 
+#define ON_CHANNEL_TH_MSB          (0x0B)
+#define ON_CHANNEL_TH_LSB          (0xA8)
+
+#define OFF_CHANNEL_TH_MSB         (0x0B)
+#define OFF_CHANNEL_TH_LSB         (0xAC)
+
 #define ENF_200Khz                    (1)
 #define SRCH200KHZ_OFFSET             (7)
 #define SRCH_MASK                  (1 << SRCH200KHZ_OFFSET)
@@ -147,7 +153,14 @@
 	*/
 	V4L2_CID_PRIVATE_TAVARUA_SET_NOTCH_FILTER =
 		V4L2_CID_PRIVATE_BASE + 0x28,
-	V4L2_CID_PRIVATE_TAVARUA_SET_AUDIO_PATH
+	V4L2_CID_PRIVATE_TAVARUA_SET_AUDIO_PATH,
+	/*0x800002a is used for iris specific ioctl*/
+
+	V4L2_CID_PRIVATE_TAVARUA_ON_CHANNEL_THRESHOLD =
+		V4L2_CTRL_CLASS_USER + 0x92B,
+	V4L2_CID_PRIVATE_TAVARUA_OFF_CHANNEL_THRESHOLD =
+		V4L2_CTRL_CLASS_USER + 0x92C
+
 };
 
 enum tavarua_buf_t {
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index a9205e3..2043c08 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -885,10 +885,13 @@
 			     struct hrtimer_clock_base *base,
 			     unsigned long newstate, int reprogram)
 {
+	struct timerqueue_node *next_timer;
 	if (!(timer->state & HRTIMER_STATE_ENQUEUED))
 		goto out;
 
-	if (&timer->node == timerqueue_getnext(&base->active)) {
+	next_timer = timerqueue_getnext(&base->active);
+	timerqueue_del(&base->active, &timer->node);
+	if (&timer->node == next_timer) {
 #ifdef CONFIG_HIGH_RES_TIMERS
 		/* Reprogram the clock event device. if enabled */
 		if (reprogram && hrtimer_hres_active()) {
@@ -901,7 +904,6 @@
 		}
 #endif
 	}
-	timerqueue_del(&base->active, &timer->node);
 	if (!timerqueue_getnext(&base->active))
 		base->cpu_base->active_bases &= ~(1 << base->index);
 out:
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index b7bbe02..a27358f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -612,6 +612,8 @@
 
 static int hci_dev_do_close(struct hci_dev *hdev)
 {
+	unsigned long keepflags = 0;
+
 	BT_DBG("%s %p", hdev->name, hdev);
 
 	hci_req_cancel(hdev, ENODEV);
@@ -669,8 +671,15 @@
 	if (hdev->dev_type == HCI_BREDR)
 		mgmt_powered(hdev->id, 0);
 
-	/* Clear flags */
-	hdev->flags = 0;
+	/* Clear only non-persistent flags */
+	if (test_bit(HCI_MGMT, &hdev->flags))
+		set_bit(HCI_MGMT, &keepflags);
+	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
+		set_bit(HCI_LINK_KEYS, &keepflags);
+	if (test_bit(HCI_DEBUG_KEYS, &hdev->flags))
+		set_bit(HCI_DEBUG_KEYS, &keepflags);
+
+	hdev->flags = keepflags;
 
 	hci_req_unlock(hdev);
 
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index a88f4a5..e301edf 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -1020,12 +1020,16 @@
 		*keydist &= ~SMP_DIST_SIGN;
 	}
 
-	if (hcon->out || rsp->resp_key_dist) {
+	if (hcon->out) {
 		if (hcon->disconn_cfm_cb)
 			hcon->disconn_cfm_cb(hcon, 0);
-
 		del_timer(&hcon->smp_timer);
 		clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+		hci_conn_put(hcon);
+	} else if (rsp->resp_key_dist) {
+		if (hcon->disconn_cfm_cb)
+			hcon->disconn_cfm_cb(hcon, SMP_UNSPECIFIED);
+		clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
 		mgmt_auth_failed(hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
 		hci_conn_put(hcon);
 	}
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 7f7bdc9..cab5ec5 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -14,12 +14,15 @@
 #include <linux/firmware.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
+#include <linux/device.h>
 #include <linux/printk.h>
 #include <linux/ratelimit.h>
 #include <linux/debugfs.h>
 #include <linux/mfd/wcd9310/core.h>
 #include <linux/mfd/wcd9310/registers.h>
 #include <linux/mfd/wcd9310/pdata.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
 #include <sound/jack.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
@@ -39,6 +42,8 @@
 
 #define TABLA_JACK_MASK (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR)
 
+#define TABLA_I2S_MASTER_MODE_MASK 0x08
+
 static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
 static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
 static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
@@ -87,6 +92,9 @@
 	u8 cfilt_k_value;
 	bool mbhc_micbias_switched;
 
+	/*track tabla interface type*/
+	u8 intf_type;
+
 	u32 hph_status; /* track headhpone status */
 	/* define separate work for left and right headphone OCP to avoid
 	 * additional checking on which OCP event to report so no locking
@@ -1426,6 +1434,12 @@
 		break;
 	}
 }
+static const struct snd_soc_dapm_widget tabla_dapm_i2s_widgets[] = {
+	SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", TABLA_A_CDC_CLK_RX_I2S_CTL,
+	4, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", TABLA_A_CDC_CLK_TX_I2S_CTL, 4,
+	0, NULL, 0),
+};
 
 static const struct snd_soc_dapm_widget tabla_dapm_widgets[] = {
 	/*RX stuff */
@@ -1438,6 +1452,8 @@
 
 	SND_SOC_DAPM_AIF_IN("SLIM RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
 	SND_SOC_DAPM_AIF_IN("SLIM RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("SLIM RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("SLIM RX4", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
 
 	/* Headphone */
 	SND_SOC_DAPM_OUTPUT("HEADPHONE"),
@@ -1701,6 +1717,19 @@
 	SND_SOC_DAPM_PGA("IIR1", TABLA_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
 };
 
+static const struct snd_soc_dapm_route audio_i2s_map[] = {
+	{"RX_I2S_CLK", NULL, "CDC_CONN"},
+	{"SLIM RX1", NULL, "RX_I2S_CLK"},
+	{"SLIM RX2", NULL, "RX_I2S_CLK"},
+	{"SLIM RX3", NULL, "RX_I2S_CLK"},
+	{"SLIM RX4", NULL, "RX_I2S_CLK"},
+
+	{"SLIM TX7", NULL, "TX_I2S_CLK"},
+	{"SLIM TX8", NULL, "TX_I2S_CLK"},
+	{"SLIM TX9", NULL, "TX_I2S_CLK"},
+	{"SLIM TX10", NULL, "TX_I2S_CLK"},
+};
+
 static const struct snd_soc_dapm_route audio_map[] = {
 	/* SLIMBUS Connections */
 
@@ -1814,45 +1843,73 @@
 
 	{"RX1 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
 	{"RX1 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
 	{"RX1 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX2 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX2 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX2 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX2 MIX1 INP1", "RX4", "SLIM RX4"},
 	{"RX2 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
 	{"RX2 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
 	{"RX3 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
 	{"RX3 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
 	{"RX4 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
 	{"RX4 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX5 MIX1 INP1", "RX4", "SLIM RX4"},
 	{"RX5 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX5 MIX1 INP2", "RX4", "SLIM RX4"},
 	{"RX5 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX6 MIX1 INP1", "RX4", "SLIM RX4"},
 	{"RX6 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX6 MIX1 INP2", "RX4", "SLIM RX4"},
 	{"RX6 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX7 MIX1 INP1", "RX4", "SLIM RX4"},
 	{"RX7 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX7 MIX1 INP2", "RX4", "SLIM RX4"},
 	{"RX7 MIX1 INP2", "IIR1", "IIR1"},
 
 	/* Decimator Inputs */
@@ -2111,7 +2168,7 @@
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B10_CTL, 0xFF);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B9_CTL, 0x20);
 
-	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0x08);
+	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0xF8);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL, 0xEE);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL, 0xFC);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL, 0xCE);
@@ -2191,7 +2248,39 @@
 
 static int tabla_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
+	u8 val = 0;
+	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(dai->codec);
+
 	pr_debug("%s\n", __func__);
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		/* CPU is master */
+		if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
+			if (dai->id == TABLA_TX_DAI_ID)
+				snd_soc_update_bits(dai->codec,
+					TABLA_A_CDC_CLK_TX_I2S_CTL,
+					TABLA_I2S_MASTER_MODE_MASK, 0);
+			else if (dai->id == TABLA_RX_DAI_ID)
+				snd_soc_update_bits(dai->codec,
+					TABLA_A_CDC_CLK_RX_I2S_CTL,
+					TABLA_I2S_MASTER_MODE_MASK, 0);
+		}
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+	/* CPU is slave */
+		if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
+			val = TABLA_I2S_MASTER_MODE_MASK;
+			if (dai->id == TABLA_TX_DAI_ID)
+				snd_soc_update_bits(dai->codec,
+					TABLA_A_CDC_CLK_TX_I2S_CTL, val, val);
+			else if (dai->id == TABLA_RX_DAI_ID)
+				snd_soc_update_bits(dai->codec,
+					TABLA_A_CDC_CLK_RX_I2S_CTL, val, val);
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
 	return 0;
 }
 
@@ -2200,6 +2289,7 @@
 			    struct snd_soc_dai *dai)
 {
 	struct snd_soc_codec *codec = dai->codec;
+	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(dai->codec);
 	u8 path, shift;
 	u16 tx_fs_reg, rx_fs_reg;
 	u8 tx_fs_rate, rx_fs_rate, rx_state, tx_state;
@@ -2255,6 +2345,25 @@
 							0x03, tx_fs_rate);
 			}
 		}
+		if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
+			switch (params_format(params)) {
+			case SNDRV_PCM_FORMAT_S16_LE:
+				snd_soc_update_bits(codec,
+					TABLA_A_CDC_CLK_TX_I2S_CTL,
+					0x20, 0x20);
+				break;
+			case SNDRV_PCM_FORMAT_S32_LE:
+				snd_soc_update_bits(codec,
+					TABLA_A_CDC_CLK_TX_I2S_CTL,
+					0x20, 0x00);
+				break;
+			default:
+				pr_err("invalid format\n");
+				break;
+			}
+			snd_soc_update_bits(codec, TABLA_A_CDC_CLK_TX_I2S_CTL,
+						0x03, tx_fs_rate);
+		}
 	}
 
 	/**
@@ -2281,6 +2390,25 @@
 						0xE0, rx_fs_rate);
 			}
 		}
+		if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
+			switch (params_format(params)) {
+			case SNDRV_PCM_FORMAT_S16_LE:
+				snd_soc_update_bits(codec,
+					TABLA_A_CDC_CLK_RX_I2S_CTL,
+					0x20, 0x20);
+				break;
+			case SNDRV_PCM_FORMAT_S32_LE:
+				snd_soc_update_bits(codec,
+					TABLA_A_CDC_CLK_RX_I2S_CTL,
+					0x20, 0x00);
+				break;
+			default:
+				pr_err("invalid format\n");
+				break;
+			}
+			snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_I2S_CTL,
+						0x03, (rx_fs_rate >> 0x05));
+		}
 	}
 
 	return 0;
@@ -2324,6 +2452,37 @@
 		.ops = &tabla_dai_ops,
 	},
 };
+
+static struct snd_soc_dai_driver tabla_i2s_dai[] = {
+	{
+		.name = "tabla_i2s_rx1",
+		.id = 1,
+		.playback = {
+			.stream_name = "AIF1 Playback",
+			.rates = WCD9310_RATES,
+			.formats = TABLA_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &tabla_dai_ops,
+	},
+	{
+		.name = "tabla_i2s_tx1",
+		.id = 2,
+		.capture = {
+			.stream_name = "AIF1 Capture",
+			.rates = WCD9310_RATES,
+			.formats = TABLA_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &tabla_dai_ops,
+	},
+};
 static short tabla_codec_read_sta_result(struct snd_soc_codec *codec)
 {
 	u8 bias_msb, bias_lsb;
@@ -2603,7 +2762,6 @@
 	 */
 	priv->buttons_pressed |= SND_JACK_BTN_0;
 
-	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0x09);
 	msleep(100);
 
 	schedule_delayed_work(&priv->btn0_dwork, msecs_to_jiffies(400));
@@ -2663,7 +2821,6 @@
 		priv->buttons_pressed &= ~SND_JACK_BTN_0;
 	}
 
-	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0x08);
 	tabla_codec_start_hs_polling(codec);
 
 	return IRQ_HANDLED;
@@ -3186,6 +3343,7 @@
 	tabla->no_mic_headset_override = false;
 	tabla->codec = codec;
 	tabla->pdata = dev_get_platdata(codec->dev->parent);
+	tabla->intf_type = tabla_get_intf_type();
 
 	tabla_update_reg_defaults(codec);
 	tabla_codec_init_reg(codec);
@@ -3204,6 +3362,12 @@
 		ARRAY_SIZE(tabla_snd_controls));
 	snd_soc_dapm_new_controls(dapm, tabla_dapm_widgets,
 		ARRAY_SIZE(tabla_dapm_widgets));
+	if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
+		snd_soc_dapm_new_controls(dapm, tabla_dapm_i2s_widgets,
+			ARRAY_SIZE(tabla_dapm_i2s_widgets));
+		snd_soc_dapm_add_routes(dapm, audio_i2s_map,
+			ARRAY_SIZE(audio_i2s_map));
+	}
 	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 	snd_soc_dapm_sync(dapm);
 
@@ -3362,13 +3526,19 @@
 
 static int __devinit tabla_probe(struct platform_device *pdev)
 {
+	int ret = 0;
 #ifdef CONFIG_DEBUG_FS
 	debugfs_poke = debugfs_create_file("TRRS",
 		S_IFREG | S_IRUGO, NULL, (void *) "TRRS", &codec_debug_ops);
 
 #endif
-	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tabla,
-		tabla_dai, ARRAY_SIZE(tabla_dai));
+	if (tabla_get_intf_type() == TABLA_INTERFACE_TYPE_SLIMBUS)
+		ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tabla,
+			tabla_dai, ARRAY_SIZE(tabla_dai));
+	else if (tabla_get_intf_type() == TABLA_INTERFACE_TYPE_I2C)
+		ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tabla,
+			tabla_i2s_dai, ARRAY_SIZE(tabla_i2s_dai));
+	return ret;
 }
 static int __devexit tabla_remove(struct platform_device *pdev)
 {
diff --git a/sound/soc/msm/msm8660-apq-wm8903.c b/sound/soc/msm/msm8660-apq-wm8903.c
index af72872..a163006 100644
--- a/sound/soc/msm/msm8660-apq-wm8903.c
+++ b/sound/soc/msm/msm8660-apq-wm8903.c
@@ -9,8 +9,6 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- *TODO:
- *  - Audio stream capture support
  */
 
 #include <linux/clk.h>
@@ -34,11 +32,11 @@
 #define MSM_GPIO_CLASS_D0_EN  80
 #define MSM_GPIO_CLASS_D1_EN  81
 
-#define MSM8660_SPK_ON    1
-#define MSM8660_SPK_OFF   0
 #define MSM_CDC_MIC_I2S_MCLK 108
 
 static int msm8660_spk_func;
+static int msm8660_headset_func;
+static int msm8660_headphone_func;
 
 static struct clk *mic_bit_clk;
 static struct clk *spkr_osr_clk;
@@ -56,6 +54,11 @@
 	NONE
 };
 
+enum {
+	FUNC_OFF,
+	FUNC_ON,
+};
+
 static struct wm8903_vdd {
 	struct regulator *reg_id;
 	const char *name;
@@ -295,23 +298,19 @@
 		/* config WM8903 in Mater mode */
 		ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_CBM_CFM |
 				SND_SOC_DAIFMT_I2S);
-		mic_bit_clk = clk_get(NULL, "i2s_mic_bit_clk");
-		if (IS_ERR(mic_bit_clk)) {
-			pr_err("Failed to get i2s_mic_bit_clk\n");
-			return PTR_ERR(mic_bit_clk);
-		}
-		clk_set_rate(mic_bit_clk, 0);
-		ret = clk_enable(mic_bit_clk);
 		if (ret != 0) {
-			pr_err("Unable to enable i2s_mic_bit_clk\n");
-			clk_put(mic_bit_clk);
+			pr_err("codec_dai set_fmt error\n");
+			return ret;
+		}
+		/* config CPU in SLAVE mode */
+		ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM);
+		if (ret != 0) {
+			pr_err("cpu_dai set_fmt error\n");
 			return ret;
 		}
 		spkr_osr_clk = clk_get(NULL, "i2s_spkr_osr_clk");
 		if (IS_ERR(spkr_osr_clk)) {
 			pr_err("Failed to get i2s_spkr_osr_clk\n");
-			clk_disable(mic_bit_clk);
-			clk_put(mic_bit_clk);
 			return PTR_ERR(spkr_osr_clk);
 		}
 		clk_set_rate(spkr_osr_clk, 48000 * 256);
@@ -319,8 +318,6 @@
 		if (ret != 0) {
 			pr_err("Unable to enable i2s_spkr_osr_clk\n");
 			clk_put(spkr_osr_clk);
-			clk_disable(mic_bit_clk);
-			clk_put(mic_bit_clk);
 			return ret;
 		}
 		spkr_bit_clk = clk_get(NULL, "i2s_spkr_bit_clk");
@@ -328,8 +325,6 @@
 			pr_err("Failed to get i2s_spkr_bit_clk\n");
 			clk_disable(spkr_osr_clk);
 			clk_put(spkr_osr_clk);
-			clk_disable(mic_bit_clk);
-			clk_put(mic_bit_clk);
 			return PTR_ERR(spkr_bit_clk);
 		}
 		clk_set_rate(spkr_bit_clk, 0);
@@ -338,15 +333,24 @@
 			pr_err("Unable to enable i2s_spkr_bit_clk\n");
 			clk_disable(spkr_osr_clk);
 			clk_put(spkr_osr_clk);
-			clk_disable(mic_bit_clk);
-			clk_put(mic_bit_clk);
 			clk_put(spkr_bit_clk);
 			return ret;
 		}
+	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		/* config WM8903 in Mater mode */
+		ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_CBM_CFM |
+				SND_SOC_DAIFMT_I2S);
+		if (ret != 0) {
+			pr_err("codec_dai set_fmt error\n");
+			return ret;
+		}
 		/* config CPU in SLAVE mode */
 		ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM);
-		/* End of platform specific logic */
-	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		if (ret != 0) {
+			pr_err("codec_dai set_fmt error\n");
+			return ret;
+		}
+
 		mic_bit_clk = clk_get(NULL, "i2s_mic_bit_clk");
 		if (IS_ERR(mic_bit_clk)) {
 			pr_err("Failed to get i2s_mic_bit_clk\n");
@@ -359,7 +363,6 @@
 			clk_put(mic_bit_clk);
 			return ret;
 		}
-		msleep(30);
 	}
 	return ret;
 }
@@ -367,7 +370,9 @@
 static void msm8660_i2s_shutdown(struct snd_pcm_substream *substream)
 {
 	pr_debug("Enter %s\n", __func__);
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+			 substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		tx_hw_param_status = 0;
 		rx_hw_param_status = 0;
 		if (spkr_bit_clk) {
 			clk_disable(spkr_bit_clk);
@@ -384,25 +389,29 @@
 			clk_put(mic_bit_clk);
 			mic_bit_clk = NULL;
 		}
-	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
-		tx_hw_param_status = 0;
-		msleep(30);
-		if (mic_bit_clk) {
-			clk_disable(mic_bit_clk);
-			clk_put(mic_bit_clk);
-			mic_bit_clk = NULL;
-		}
 	}
 }
 
 static void msm8660_ext_control(struct snd_soc_codec *codec)
 {
 	/* set the enpoints to their new connetion states */
-	if (msm8660_spk_func == MSM8660_SPK_ON)
+	if (msm8660_spk_func == FUNC_ON)
 		snd_soc_dapm_enable_pin(&codec->dapm, "Ext Spk");
 	else
 		snd_soc_dapm_disable_pin(&codec->dapm, "Ext Spk");
 
+	/* set the enpoints to their new connetion states */
+	if (msm8660_headset_func == FUNC_ON)
+		snd_soc_dapm_enable_pin(&codec->dapm, "Headset Jack");
+	else
+		snd_soc_dapm_disable_pin(&codec->dapm, "Headset Jack");
+
+	/* set the enpoints to their new connetion states */
+	if (msm8660_headphone_func == FUNC_ON)
+		snd_soc_dapm_enable_pin(&codec->dapm, "Headphone Jack");
+	else
+		snd_soc_dapm_disable_pin(&codec->dapm, "Headphone Jack");
+
 	/* signal a DAPM event */
 	snd_soc_dapm_sync(&codec->dapm);
 }
@@ -428,6 +437,48 @@
 	return 1;
 }
 
+static int msm8660_get_hs(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = msm8660_headset_func;
+	return 0;
+}
+
+static int msm8660_set_hs(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+
+	pr_debug("%s()\n", __func__);
+	if (msm8660_headset_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	msm8660_headset_func = ucontrol->value.integer.value[0];
+	msm8660_ext_control(codec);
+	return 1;
+}
+
+static int msm8660_get_hph(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = msm8660_headphone_func;
+	return 0;
+}
+
+static int msm8660_set_hph(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+
+	pr_debug("%s()\n", __func__);
+	if (msm8660_headphone_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	msm8660_headphone_func = ucontrol->value.integer.value[0];
+	msm8660_ext_control(codec);
+	return 1;
+}
+
 static int msm8660_spkramp_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *k, int event)
 {
@@ -446,22 +497,42 @@
 
 static const struct snd_soc_dapm_widget msm8660_dapm_widgets[] = {
 	SND_SOC_DAPM_SPK("Ext Spk", msm8660_spkramp_event),
+	SND_SOC_DAPM_MIC("Headset Jack", NULL),
+	SND_SOC_DAPM_MIC("Headphone Jack", NULL),
+	/* to fix a bug in wm8903.c, where audio doesn't function
+	 * after suspend/resume
+	 */
+	SND_SOC_DAPM_SUPPLY("CLK_SYS_ENA", WM8903_CLOCK_RATES_2, 2, 0, NULL, 0),
 };
 
 static const struct snd_soc_dapm_route audio_map[] = {
 	/* Match with wm8903 codec line out pin */
 	{"Ext Spk", NULL, "LINEOUTL"},
 	{"Ext Spk", NULL, "LINEOUTR"},
+	/* Headset connects to IN3L with Bias */
+	{"IN3L", NULL, "Mic Bias"},
+	{"Mic Bias", NULL, "Headset Jack"},
+	/* Headphone connects to IN3R with Bias */
+	{"IN3R", NULL, "Mic Bias"},
+	{"Mic Bias", NULL, "Headphone Jack"},
+	{"ADCL", NULL, "CLK_SYS_ENA"},
+	{"ADCR", NULL, "CLK_SYS_ENA"},
+	{"DACL", NULL, "CLK_SYS_ENA"},
+	{"DACR", NULL, "CLK_SYS_ENA"},
 };
 
-static const char *spk_function[] = {"Off", "On"};
+static const char *cmn_status[] = {"Off", "On"};
 static const struct soc_enum msm8660_enum[] = {
-	SOC_ENUM_SINGLE_EXT(2, spk_function),
+	SOC_ENUM_SINGLE_EXT(2, cmn_status),
 };
 
 static const struct snd_kcontrol_new wm8903_msm8660_controls[] = {
 	SOC_ENUM_EXT("Speaker Function", msm8660_enum[0], msm8660_get_spk,
 		msm8660_set_spk),
+	SOC_ENUM_EXT("Headset Function", msm8660_enum[0], msm8660_get_hs,
+		msm8660_set_hs),
+	SOC_ENUM_EXT("Headphone Function", msm8660_enum[0], msm8660_get_hph,
+		msm8660_set_hph),
 };
 
 static int msm8660_audrx_init(struct snd_soc_pcm_runtime *rtd)
@@ -470,6 +541,7 @@
 	int err;
 
 	snd_soc_dapm_disable_pin(&codec->dapm, "Ext Spk");
+	snd_soc_dapm_enable_pin(&codec->dapm, "CLK_SYS_ENA");
 
 	err = snd_soc_add_controls(codec, wm8903_msm8660_controls,
 				ARRAY_SIZE(wm8903_msm8660_controls));
diff --git a/sound/soc/soc-dsp.c b/sound/soc/soc-dsp.c
index bef84a1..6b0c215 100644
--- a/sound/soc/soc-dsp.c
+++ b/sound/soc/soc-dsp.c
@@ -482,6 +482,9 @@
 		struct snd_pcm_substream *be_substream =
 			snd_soc_dsp_get_substream(dsp_params->be, stream);
 
+		if (dsp_params->state != SND_SOC_DSP_LINK_STATE_FREE)
+			continue;
+
 		/* is this op for this BE ? */
 		if (fe->dsp[stream].runtime_update &&
 				!dsp_params->be->dsp[stream].runtime_update)
@@ -490,9 +493,6 @@
 		if (--dsp_params->be->dsp[stream].users != 0)
 			continue;
 
-		if (dsp_params->state != SND_SOC_DSP_LINK_STATE_FREE)
-			continue;
-
 		dev_dbg(&dsp_params->be->dev, "dsp: close BE %s\n",
 			dsp_params->fe->dai_link->name);