Merge "msm: scm: Mark scm_call_atomic*() return value as signed" into msm-3.0
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index 25ba590..985d735 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -294,6 +294,7 @@
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_SX150X=y
+# CONFIG_MPP_PMIC8901 is not set
 CONFIG_POWER_SUPPLY=y
 # CONFIG_BATTERY_MSM is not set
 CONFIG_BATTERY_MSM8X60=y
@@ -305,7 +306,6 @@
 CONFIG_SENSORS_MSM_ADC=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_HWMON=y
-CONFIG_THERMAL_PM8901=y
 CONFIG_THERMAL_TSENS=y
 CONFIG_THERMAL_PM8XXX=y
 CONFIG_PMIC8058=y
@@ -314,6 +314,7 @@
 CONFIG_TIMPANI_CODEC=y
 # CONFIG_MFD_PM8XXX_PWM is not set
 CONFIG_MFD_PM8XXX_BATT_ALARM=y
+CONFIG_REGULATOR_GPIO=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
 # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
@@ -432,6 +433,7 @@
 CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
 CONFIG_CRYPTO_SHA256=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index ae33597..dbde99f 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -284,6 +284,7 @@
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_SX150X=y
+# CONFIG_MPP_PMIC8901 is not set
 CONFIG_POWER_SUPPLY=y
 # CONFIG_BATTERY_MSM is not set
 CONFIG_BATTERY_MSM8X60=y
@@ -294,7 +295,6 @@
 CONFIG_BATTERY_BQ27541=y
 CONFIG_SENSORS_MSM_ADC=y
 CONFIG_THERMAL=y
-CONFIG_THERMAL_PM8901=y
 CONFIG_THERMAL_TSENS=y
 CONFIG_THERMAL_PM8XXX=y
 CONFIG_PMIC8058=y
@@ -303,6 +303,7 @@
 CONFIG_TIMPANI_CODEC=y
 # CONFIG_MFD_PM8XXX_PWM is not set
 CONFIG_MFD_PM8XXX_BATT_ALARM=y
+CONFIG_REGULATOR_GPIO=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
 # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
@@ -427,6 +428,7 @@
 CONFIG_DEBUG_LIST=y
 CONFIG_DEBUG_SG=y
 CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 47e3c41..748b8ca 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -235,7 +235,7 @@
 CONFIG_KS8851=m
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
-CONFIG_WCNSS_CORE=m
+CONFIG_WCNSS_CORE=y
 CONFIG_USB_USBNET=y
 CONFIG_SLIP=y
 CONFIG_SLIP_COMPRESSED=y
@@ -296,6 +296,7 @@
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_ACTUATOR=y
 CONFIG_MSM_GEMINI=y
+CONFIG_MT9M114=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
 CONFIG_ION=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 003f9c1..b5aa1b4 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -188,6 +188,7 @@
 CONFIG_MSM_SSBI=y
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_BAMDMA=y
+CONFIG_USB_BAM=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_YAFFS_FS=y
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index b59ad93..6a7158b 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -247,7 +247,6 @@
 	/* Don't read disabled counters! */
 	if (hwc->idx < 0)
 		return;
-
 	armpmu_event_update(event, hwc, hwc->idx, 0);
 }
 
@@ -632,6 +631,24 @@
 		armpmu->stop();
 }
 
+static void armpmu_update_counters(void)
+{
+	int idx;
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+
+	if (!armpmu)
+		return;
+
+	for (idx = 0; idx <= armpmu->num_events; ++idx) {
+		struct perf_event *event = cpuc->events[idx];
+
+		if (!event)
+			continue;
+
+		armpmu_read(event);
+	}
+}
+
 static struct pmu pmu = {
 	.pmu_enable	= armpmu_enable,
 	.pmu_disable	= armpmu_disable,
@@ -657,6 +674,7 @@
 {
 	switch (cmd) {
 	case CPU_PM_ENTER:
+		armpmu_update_counters();
 		perf_pmu_disable(&pmu);
 		break;
 
diff --git a/arch/arm/kernel/perf_event_msm.c b/arch/arm/kernel/perf_event_msm.c
index b40a226..8fa2f30 100644
--- a/arch/arm/kernel/perf_event_msm.c
+++ b/arch/arm/kernel/perf_event_msm.c
@@ -610,6 +610,7 @@
 	u32 gr;
 	unsigned long event;
 	struct scorpion_evt evtinfo;
+	unsigned long long prev_count = local64_read(&hwc->prev_count);
 
 	/*
 	 * Enable counter and interrupt, and set the counter to count
@@ -652,6 +653,9 @@
 	/* Enable interrupt for this counter */
 	armv7_pmnc_enable_intens(idx);
 
+	/* Restore prev val */
+	armv7pmu_write_counter(idx, prev_count & COUNT_MASK);
+
 	/* Enable counter */
 	armv7_pmnc_enable_counter(idx);
 
diff --git a/arch/arm/kernel/perf_event_msm_krait.c b/arch/arm/kernel/perf_event_msm_krait.c
index cf1f1ee..3c8fb84 100644
--- a/arch/arm/kernel/perf_event_msm_krait.c
+++ b/arch/arm/kernel/perf_event_msm_krait.c
@@ -419,6 +419,7 @@
 	u32 gr;
 	unsigned long event;
 	struct krait_evt evtinfo;
+	unsigned long long prev_count = local64_read(&hwc->prev_count);
 
 	/*
 	 * Enable counter and interrupt, and set the counter to count
@@ -465,6 +466,9 @@
 	/* Enable interrupt for this counter */
 	armv7_pmnc_enable_intens(idx);
 
+	/* Restore prev val */
+	armv7pmu_write_counter(idx, prev_count & COUNT_MASK);
+
 	/* Enable counter */
 	armv7_pmnc_enable_counter(idx);
 
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 277f1ce..3689e07 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -738,6 +738,10 @@
 #define        ARMV7_EXCLUDE_USER      (1 << 30)
 #define        ARMV7_INCLUDE_HYP       (1 << 27)
 
+
+/* Mask for restoring h/w counter val */
+#define	COUNT_MASK	0xffffffff
+
 /*
  * Add an event filter to a given event. This will only work for PMUv2 PMUs.
  */
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 0078ebc..204aa5d 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -41,6 +41,8 @@
 	select ARCH_HAS_HOLES_MEMORYMODEL
 	select MEMORY_HOTPLUG
 	select MEMORY_HOTREMOVE
+	select ARCH_ENABLE_MEMORY_HOTPLUG
+	select ARCH_ENABLE_MEMORY_HOTREMOVE
 	select MIGRATION
 	select ARCH_MEMORY_PROBE
 	select ARCH_MEMORY_REMOVE
@@ -143,6 +145,8 @@
 	select ARCH_HAS_HOLES_MEMORYMODEL
 	select MEMORY_HOTPLUG
 	select MEMORY_HOTREMOVE
+	select ARCH_ENABLE_MEMORY_HOTPLUG
+	select ARCH_ENABLE_MEMORY_HOTREMOVE
 	select MIGRATION
 	select ARCH_MEMORY_PROBE
 	select ARCH_MEMORY_REMOVE
@@ -174,6 +178,8 @@
 	select ARCH_HAS_HOLES_MEMORYMODEL
 	select MEMORY_HOTPLUG
 	select MEMORY_HOTREMOVE
+	select ARCH_ENABLE_MEMORY_HOTPLUG
+	select ARCH_ENABLE_MEMORY_HOTREMOVE
 	select MIGRATION
 	select ARCH_MEMORY_PROBE
 	select ARCH_MEMORY_REMOVE
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index be8c31c..82d8173 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -68,7 +68,7 @@
 #define STBY_KHZ		1
 
 #define HFPLL_NOMINAL_VDD	1050000
-#define HFPLL_LOW_VDD		945000
+#define HFPLL_LOW_VDD		 850000
 #define HFPLL_LOW_VDD_PLL_L_MAX	0x28
 
 #define SECCLKAGD		BIT(4)
@@ -147,7 +147,7 @@
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_A] = { "hfpll", 2200000,
+			.vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8921_S8 },
 			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
@@ -165,7 +165,7 @@
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_A] = { "hfpll", 2200000,
+			.vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_S8 },
 			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
@@ -176,7 +176,7 @@
 			.hfpll_base   = MSM_HFPLL_BASE    + 0x400,
 			.aux_clk_sel  = MSM_APCS_GCC_BASE + 0x028,
 			.l2cpmr_iaddr = L2CPMR_IADDR,
-			.vreg[VREG_HFPLL_A] = { "hfpll", 2200000,
+			.vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
 					     RPM_VREG_VOTER6,
 					     RPM_VREG_ID_PM8921_S8 },
 			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
@@ -269,12 +269,13 @@
 		.num_paths = 2, \
 	}
 static struct msm_bus_paths bw_level_tbl[] = {
-	[0] =  BW_MBPS(616), /* At least  77 MHz on bus. */
-	[1] = BW_MBPS(1024), /* At least 128 MHz on bus. */
-	[2] = BW_MBPS(1536), /* At least 192 MHz on bus. */
-	[3] = BW_MBPS(2048), /* At least 256 MHz on bus. */
-	[4] = BW_MBPS(3080), /* At least 385 MHz on bus. */
-	[5] = BW_MBPS(3968), /* At least 496 MHz on bus. */
+	[0] =  BW_MBPS(640), /* At least  80 MHz on bus. */
+	[1] = BW_MBPS(1064), /* At least 133 MHz on bus. */
+	[2] = BW_MBPS(1600), /* At least 200 MHz on bus. */
+	[3] = BW_MBPS(2128), /* At least 266 MHz on bus. */
+	[4] = BW_MBPS(3200), /* At least 400 MHz on bus. */
+	[5] = BW_MBPS(3600), /* At least 450 MHz on bus. */
+	[6] = BW_MBPS(3936), /* At least 492 MHz on bus. */
 };
 
 static struct msm_bus_scale_pdata bus_client_pdata = {
@@ -303,19 +304,35 @@
 	[11] = { {  918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 3 },
 };
 
-static struct acpu_level acpu_freq_tbl_8960_kraitv1[] = {
-	{ 0, {STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   950000 },
-	{ 1, {  384000, PLL_8, 0, 2, 0x00 }, L2(1),   950000 },
-	{ 1, {  432000, HFPLL, 2, 0, 0x20 }, L2(6),   950000 },
-	{ 1, {  486000, HFPLL, 2, 0, 0x24 }, L2(6),   962500 },
-	{ 1, {  540000, HFPLL, 2, 0, 0x28 }, L2(6),   962500 },
-	{ 1, {  594000, HFPLL, 1, 0, 0x16 }, L2(6),   987500 },
-	{ 1, {  648000, HFPLL, 1, 0, 0x18 }, L2(6),  1000000 },
-	{ 1, {  702000, HFPLL, 1, 0, 0x1A }, L2(6),  1025000 },
-	{ 1, {  756000, HFPLL, 1, 0, 0x1C }, L2(11), 1050000 },
-	{ 1, {  810000, HFPLL, 1, 0, 0x1E }, L2(11), 1087500 },
-	{ 1, {  864000, HFPLL, 1, 0, 0x20 }, L2(11), 1125000 },
-	{ 1, {  918000, HFPLL, 1, 0, 0x22 }, L2(11), 1137500 },
+static struct acpu_level acpu_freq_tbl_8960_kraitv1_slow[] = {
+	{ 0, {STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   900000 },
+	{ 1, {  384000, PLL_8, 0, 2, 0x00 }, L2(1),   900000 },
+	{ 1, {  432000, HFPLL, 2, 0, 0x20 }, L2(6),   925000 },
+	{ 1, {  486000, HFPLL, 2, 0, 0x24 }, L2(6),   925000 },
+	{ 1, {  540000, HFPLL, 2, 0, 0x28 }, L2(6),   937500 },
+	{ 1, {  594000, HFPLL, 1, 0, 0x16 }, L2(6),   962500 },
+	{ 1, {  648000, HFPLL, 1, 0, 0x18 }, L2(6),   987500 },
+	{ 1, {  702000, HFPLL, 1, 0, 0x1A }, L2(6),  1000000 },
+	{ 1, {  756000, HFPLL, 1, 0, 0x1C }, L2(11), 1025000 },
+	{ 1, {  810000, HFPLL, 1, 0, 0x1E }, L2(11), 1062500 },
+	{ 1, {  864000, HFPLL, 1, 0, 0x20 }, L2(11), 1062500 },
+	{ 1, {  918000, HFPLL, 1, 0, 0x22 }, L2(11), 1087500 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_8960_kraitv1_nom_fast[] = {
+	{ 0, {STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   862500 },
+	{ 1, {  384000, PLL_8, 0, 2, 0x00 }, L2(1),   862500 },
+	{ 1, {  432000, HFPLL, 2, 0, 0x20 }, L2(6),   862500 },
+	{ 1, {  486000, HFPLL, 2, 0, 0x24 }, L2(6),   887500 },
+	{ 1, {  540000, HFPLL, 2, 0, 0x28 }, L2(6),   900000 },
+	{ 1, {  594000, HFPLL, 1, 0, 0x16 }, L2(6),   925000 },
+	{ 1, {  648000, HFPLL, 1, 0, 0x18 }, L2(6),   925000 },
+	{ 1, {  702000, HFPLL, 1, 0, 0x1A }, L2(6),   937500 },
+	{ 1, {  756000, HFPLL, 1, 0, 0x1C }, L2(11),  962500 },
+	{ 1, {  810000, HFPLL, 1, 0, 0x1E }, L2(11), 1012500 },
+	{ 1, {  864000, HFPLL, 1, 0, 0x20 }, L2(11), 1025000 },
+	{ 1, {  918000, HFPLL, 1, 0, 0x22 }, L2(11), 1025000 },
 	{ 0, { 0 } }
 };
 
@@ -324,36 +341,63 @@
 static struct l2_level l2_freq_tbl_8960_kraitv2[] = {
 	[0]  = { {STBY_KHZ, QSB,   0, 0, 0x00 }, 1050000, 1050000, 0 },
 	[1]  = { {  384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
-	[2]  = { {  432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 1 },
-	[3]  = { {  486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 1 },
-	[4]  = { {  540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 1 },
+	[2]  = { {  432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 2 },
+	[3]  = { {  486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 2 },
+	[4]  = { {  540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 2 },
 	[5]  = { {  594000, HFPLL, 1, 0, 0x16 }, 1050000, 1050000, 2 },
-	[6]  = { {  648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 2 },
-	[7]  = { {  702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 2 },
-	[8]  = { {  756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 2 },
-	[9]  = { {  810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 3 },
-	[10] = { {  864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 3 },
-	[11] = { {  918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 3 },
-	[12] = { {  972000, HFPLL, 1, 0, 0x24 }, 1150000, 1150000, 4 },
-	[13] = { { 1026000, HFPLL, 1, 0, 0x26 }, 1150000, 1150000, 4 },
-	[14] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 4 },
-	[15] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 4 },
-	[16] = { { 1188000, HFPLL, 1, 0, 0x2C }, 1150000, 1150000, 4 },
+	[6]  = { {  648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 4 },
+	[7]  = { {  702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 4 },
+	[8]  = { {  756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 4 },
+	[9]  = { {  810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 4 },
+	[10] = { {  864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 4 },
+	[11] = { {  918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 6 },
+	[12] = { {  972000, HFPLL, 1, 0, 0x24 }, 1150000, 1150000, 6 },
+	[13] = { { 1026000, HFPLL, 1, 0, 0x26 }, 1150000, 1150000, 6 },
+	[14] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 6 },
+	[15] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 6 },
+	[16] = { { 1188000, HFPLL, 1, 0, 0x2C }, 1150000, 1150000, 6 },
 };
 
-static struct acpu_level acpu_freq_tbl_8960_kraitv2[] = {
-	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   950000 },
-	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   950000 },
-	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   950000 },
-	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(6),   962500 },
-	{ 1, {   540000, HFPLL, 2, 0, 0x28 }, L2(6),   962500 },
-	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(6),   987500 },
-	{ 1, {   648000, HFPLL, 1, 0, 0x18 }, L2(6),  1000000 },
-	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(6),  1025000 },
-	{ 1, {   756000, HFPLL, 1, 0, 0x1C }, L2(11), 1050000 },
-	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(11), 1087500 },
-	{ 1, {   864000, HFPLL, 1, 0, 0x20 }, L2(11), 1125000 },
-	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(11), 1137500 },
+static struct acpu_level acpu_freq_tbl_8960_kraitv2_slow[] = {
+	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   900000 },
+	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   900000 },
+	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   925000 },
+	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(6),   925000 },
+	{ 1, {   540000, HFPLL, 2, 0, 0x28 }, L2(6),   937500 },
+	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(6),   962500 },
+	{ 1, {   648000, HFPLL, 1, 0, 0x18 }, L2(6),   987500 },
+	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(6),  1000000 },
+	{ 1, {   756000, HFPLL, 1, 0, 0x1C }, L2(11), 1025000 },
+	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(11), 1062500 },
+	{ 1, {   864000, HFPLL, 1, 0, 0x20 }, L2(11), 1062500 },
+	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(11), 1087500 },
+	{ 1, {   972000, HFPLL, 1, 0, 0x24 }, L2(16), 1300000 },
+	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1300000 },
+	{ 1, {  1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1300000 },
+	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1300000 },
+	{ 1, {  1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1300000 },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1300000 },
+	{ 1, {  1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1300000 },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1300000 },
+	{ 1, {  1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1300000 },
+	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(16), 1300000 },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(16), 1300000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_8960_kraitv2_nom_fast[] = {
+	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   862500 },
+	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   862500 },
+	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   862500 },
+	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(6),   887500 },
+	{ 1, {   540000, HFPLL, 2, 0, 0x28 }, L2(6),   900000 },
+	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(6),   925000 },
+	{ 1, {   648000, HFPLL, 1, 0, 0x18 }, L2(6),   925000 },
+	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(6),   937500 },
+	{ 1, {   756000, HFPLL, 1, 0, 0x1C }, L2(11),  962500 },
+	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(11), 1012500 },
+	{ 1, {   864000, HFPLL, 1, 0, 0x20 }, L2(11), 1025000 },
+	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(11), 1025000 },
 	{ 1, {   972000, HFPLL, 1, 0, 0x24 }, L2(16), 1300000 },
 	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1300000 },
 	{ 1, {  1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1300000 },
@@ -485,14 +529,14 @@
 
 	if (cpu_is_msm8960()) {
 		rc = rpm_vreg_set_voltage(sc->vreg[VREG_HFPLL_A].rpm_vreg_id,
-				sc->vreg[VREG_HFPLL_A].rpm_vreg_voter, 2200000,
-				2200000, 0);
+				sc->vreg[VREG_HFPLL_A].rpm_vreg_voter, 2100000,
+				sc->vreg[VREG_HFPLL_A].max_vdd, 0);
 		if (rc)
 			pr_err("%s regulator enable failed (%d)\n",
 				sc->vreg[VREG_HFPLL_A].name, rc);
 		rc = rpm_vreg_set_voltage(sc->vreg[VREG_HFPLL_B].rpm_vreg_id,
 				sc->vreg[VREG_HFPLL_B].rpm_vreg_voter, 1800000,
-				1800000, 0);
+				sc->vreg[VREG_HFPLL_B].max_vdd, 0);
 		if (rc)
 			pr_err("%s regulator enable failed (%d)\n",
 				sc->vreg[VREG_HFPLL_B].name, rc);
@@ -1080,6 +1124,7 @@
 	/* Select frequency tables. */
 	if (cpu_is_msm8960() || cpu_is_msm8930()) {
 		uint32_t pte_efuse, pvs;
+		struct acpu_level *v1, *v2;
 
 		pte_efuse = readl_relaxed(QFPROM_PTE_EFUSE_ADDR);
 		pvs = (pte_efuse >> 10) & 0x7;
@@ -1090,26 +1135,33 @@
 		case 0x0:
 		case 0x7:
 			pr_info("ACPU PVS: Slow\n");
+			v1 = acpu_freq_tbl_8960_kraitv1_slow;
+			v2 = acpu_freq_tbl_8960_kraitv2_slow;
 			break;
 		case 0x1:
 			pr_info("ACPU PVS: Nominal\n");
+			v1 = acpu_freq_tbl_8960_kraitv1_nom_fast;
+			v2 = acpu_freq_tbl_8960_kraitv2_nom_fast;
 			break;
 		case 0x3:
 			pr_info("ACPU PVS: Fast\n");
+			v1 = acpu_freq_tbl_8960_kraitv1_nom_fast;
+			v2 = acpu_freq_tbl_8960_kraitv2_nom_fast;
 			break;
 		default:
 			pr_warn("ACPU PVS: Unknown. Defaulting to slow.\n");
+			v1 = acpu_freq_tbl_8960_kraitv1_slow;
+			v2 = acpu_freq_tbl_8960_kraitv2_slow;
 			break;
 		}
 
-		/* TODO: Select tables based on PVS data. */
 		scalable = scalable_8960;
 		if (cpu_is_krait_v1()) {
-			acpu_freq_tbl = acpu_freq_tbl_8960_kraitv1;
+			acpu_freq_tbl = v1;
 			l2_freq_tbl = l2_freq_tbl_8960_kraitv1;
 			l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960_kraitv1);
 		} else {
-			acpu_freq_tbl = acpu_freq_tbl_8960_kraitv2;
+			acpu_freq_tbl = v2;
 			l2_freq_tbl = l2_freq_tbl_8960_kraitv2;
 			l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960_kraitv2);
 		}
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index e827b2b..9e97e3f 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -415,6 +415,35 @@
 	},
 };
 #endif
+
+#ifdef CONFIG_MT9M114
+static struct msm_camera_sensor_flash_data flash_mt9m114 = {
+	.flash_type = MSM_CAMERA_FLASH_NONE
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_mt9m114 = {
+	.mount_angle = 90,
+	.sensor_reset = 107,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_mt9m114_data = {
+	.sensor_name = "mt9m114",
+	.pdata = &msm_camera_csi_device_data[0],
+	.flash_data = &flash_mt9m114,
+	.sensor_platform_info = &sensor_board_info_mt9m114,
+	.gpio_conf = &gpio_conf,
+	.csi_if = 1,
+	.camera_type = BACK_CAMERA_2D,
+};
+
+struct platform_device msm8960_camera_sensor_mt9m114 = {
+	.name = "msm_camera_mt9m114",
+	.dev = {
+		.platform_data = &msm_camera_sensor_mt9m114_data,
+	},
+};
+#endif
+
 #ifdef CONFIG_OV2720
 static struct msm_camera_sensor_flash_data flash_ov2720 = {
 	.flash_type	= MSM_CAMERA_FLASH_NONE,
@@ -455,6 +484,9 @@
 	int i;
 	struct platform_device *cam_dev[] = {
 		&msm8960_camera_sensor_imx074,
+#ifdef CONFIG_MT9M114
+		&msm8960_camera_sensor_mt9m114,
+#endif
 		&msm8960_camera_sensor_ov2720,
 	};
 
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
index ce260e1..71713829 100644
--- a/arch/arm/mach-msm/board-8960-gpiomux.c
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -247,7 +247,7 @@
 static struct gpiomux_setting hdmi_active_3_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_2MA,
-	.pull = GPIOMUX_PULL_DOWN,
+	.pull = GPIOMUX_PULL_UP,
 	.dir = GPIOMUX_IN,
 };
 
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 7bc3ca5..de4a6d6 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -32,6 +32,7 @@
 	REGULATOR_SUPPLY("dsi_vdda",		"mipi_dsi.1"),
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_camera_imx074.0"),
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_camera_ov2720.0"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_camera_mt9m114.0"),
 };
 VREG_CONSUMERS(L3) = {
 	REGULATOR_SUPPLY("8921_l3",		NULL),
@@ -71,11 +72,13 @@
 	REGULATOR_SUPPLY("8921_l11",		NULL),
 	REGULATOR_SUPPLY("cam_vana",		"msm_camera_imx074.0"),
 	REGULATOR_SUPPLY("cam_vana",		"msm_camera_ov2720.0"),
+	REGULATOR_SUPPLY("cam_vana",		"msm_camera_mt9m114.0"),
 };
 VREG_CONSUMERS(L12) = {
 	REGULATOR_SUPPLY("8921_l12",		NULL),
 	REGULATOR_SUPPLY("cam_vdig",		"msm_camera_imx074.0"),
 	REGULATOR_SUPPLY("cam_vdig",		"msm_camera_ov2720.0"),
+	REGULATOR_SUPPLY("cam_vdig",		"msm_camera_mt9m114.0"),
 };
 VREG_CONSUMERS(L14) = {
 	REGULATOR_SUPPLY("8921_l14",		NULL),
@@ -88,6 +91,7 @@
 	REGULATOR_SUPPLY("8921_l16",		NULL),
 	REGULATOR_SUPPLY("cam_vaf",		"msm_camera_imx074.0"),
 	REGULATOR_SUPPLY("cam_vaf",		"msm_camera_ov2720.0"),
+	REGULATOR_SUPPLY("cam_vaf",		"msm_camera_mt9m114.0"),
 };
 VREG_CONSUMERS(L17) = {
 	REGULATOR_SUPPLY("8921_l17",		NULL),
@@ -197,6 +201,7 @@
 	REGULATOR_SUPPLY("8921_lvs5",		NULL),
 	REGULATOR_SUPPLY("cam_vio",		"msm_camera_imx074.0"),
 	REGULATOR_SUPPLY("cam_vio",		"msm_camera_ov2720.0"),
+	REGULATOR_SUPPLY("cam_vio",		"msm_camera_mt9m114.0"),
 };
 VREG_CONSUMERS(LVS6) = {
 	REGULATOR_SUPPLY("8921_lvs6",		NULL),
@@ -449,9 +454,9 @@
 /* SAW regulator constraints */
 struct regulator_init_data msm_saw_regulator_pdata_s5 =
 	/*	      ID  vreg_name	       min_uV   max_uV */
-	SAW_VREG_INIT(S5, "8921_s5",	       950000, 1300000);
+	SAW_VREG_INIT(S5, "8921_s5",	       850000, 1300000);
 struct regulator_init_data msm_saw_regulator_pdata_s6 =
-	SAW_VREG_INIT(S6, "8921_s6",	       950000, 1300000);
+	SAW_VREG_INIT(S6, "8921_s6",	       850000, 1300000);
 
 /* PM8921 regulator constraints */
 struct pm8921_regulator_platform_data
@@ -482,7 +487,7 @@
 	RPM_SMPS(S3,	 0, 1, 1,  500000, 1150000, NULL, 100000, 4p80),
 	RPM_SMPS(S4,	 1, 1, 0, 1800000, 1800000, NULL, 100000, 3p20),
 	RPM_SMPS(S7,	 0, 1, 0, 1150000, 1150000, NULL, 100000, 3p20),
-	RPM_SMPS(S8,	 1, 1, 1, 2200000, 2200000, NULL, 100000, 1p60),
+	RPM_SMPS(S8,	 1, 1, 1, 2100000, 2100000, NULL, 100000, 1p60),
 
 	/*	ID     a_on pd ss min_uV   max_uV  supply  sys_uA init_ip */
 	RPM_LDO(L1,	 1, 1, 0, 1050000, 1050000, "8921_s4", 0, 10000),
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index fa607bf..cadaa4d 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1167,7 +1167,6 @@
 static struct i2c_board_info msm_isa1200_board_info[] __initdata = {
 	{
 		I2C_BOARD_INFO("isa1200_1", 0x90>>1),
-		.platform_data = &isa1200_1_pdata,
 	},
 };
 
@@ -1589,7 +1588,6 @@
 	&msm_device_saw_core0,
 	&msm_device_saw_core1,
 	&msm8960_device_ext_5v_vreg,
-	&msm8960_device_ext_l2_vreg,
 	&msm8960_device_ssbi_pmic,
 	&msm8960_device_qup_spi_gsbi1,
 	&msm8960_device_qup_i2c_gsbi3,
@@ -1924,6 +1922,11 @@
 	I2C_BOARD_INFO("ov2720", 0x6C),
 	},
 #endif
+#ifdef CONFIG_MT9M114
+	{
+	I2C_BOARD_INFO("mt9m114", 0x48),
+	},
+#endif
 #ifdef CONFIG_MSM_CAMERA_FLASH_SC628A
 	{
 	I2C_BOARD_INFO("sc628a", 0x6E),
@@ -2013,7 +2016,7 @@
 		ARRAY_SIZE(mxt_device_info),
 	},
 	{
-		I2C_LIQUID,
+		I2C_FFA | I2C_LIQUID,
 		MSM_8960_GSBI10_QUP_I2C_BUS_ID,
 		sii_device_info,
 		ARRAY_SIZE(sii_device_info),
@@ -2169,6 +2172,9 @@
 	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 
 	msm8960_init_pmic();
+	if ((SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2 &&
+		(machine_is_msm8960_mtp())) || machine_is_msm8960_liquid())
+		msm_isa1200_board_info[0].platform_data = &isa1200_1_pdata;
 	msm8960_i2c_init();
 	msm8960_gfx_init();
 	msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
@@ -2178,6 +2184,8 @@
 		msm_num_footswitch_devices);
 	if (machine_is_msm8960_liquid())
 		platform_device_register(&msm8960_device_ext_3p3v_vreg);
+	if (machine_is_msm8960_cdp())
+		platform_device_register(&msm8960_device_ext_l2_vreg);
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
 	msm8960_pm8921_gpio_mpp_init();
 	platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 5efafae..be0e4e6 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -727,6 +727,39 @@
 	0x13, 0x83,/* set source impedance adjustment */
 	-1};
 
+#define USB_BAM_PHY_BASE	0x12502000
+#define USB_BAM_PHY_SIZE	0x10000
+#define A2_BAM_PHY_BASE		0x124C2000
+static struct usb_bam_pipe_connect msm_usb_bam_connections[4][2] = {
+	[0][USB_TO_PEER_PERIPHERAL] = {
+		.src_phy_addr = USB_BAM_PHY_BASE,
+		.src_pipe_index = 11,
+		.dst_phy_addr = A2_BAM_PHY_BASE,
+		.dst_pipe_index = 0,
+		.data_fifo_base_offset = 0xf00,
+		.data_fifo_size = 0x400,
+		.desc_fifo_base_offset = 0x1300,
+		.desc_fifo_size = 0x300,
+	},
+	[0][PEER_PERIPHERAL_TO_USB] = {
+		.src_phy_addr = A2_BAM_PHY_BASE,
+		.src_pipe_index = 1,
+		.dst_phy_addr = USB_BAM_PHY_BASE,
+		.dst_pipe_index = 10,
+		.data_fifo_base_offset = 0xa00,
+		.data_fifo_size = 0x400,
+		.desc_fifo_base_offset = 0xe00,
+		.desc_fifo_size = 0x100,
+	},
+};
+
+static struct msm_usb_bam_platform_data msm_usb_bam_pdata = {
+	.connections = &msm_usb_bam_connections[0][0],
+	.usb_bam_phy_base = USB_BAM_PHY_BASE,
+	.usb_bam_phy_size = USB_BAM_PHY_SIZE,
+	.usb_bam_num_pipes = 32,
+};
+
 static struct msm_otg_platform_data msm_otg_pdata = {
 	.mode			= USB_OTG,
 	.otg_control	= OTG_PHY_CONTROL,
@@ -781,6 +814,7 @@
 	&msm_device_otg,
 	&msm_device_gadget_peripheral,
 	&msm_device_hsusb_host,
+	&msm_device_usb_bam,
 	&android_usb_device,
 	&msm9615_device_uart_gsbi4,
 	&msm9615_device_ext_2p95v_vreg,
@@ -833,6 +867,7 @@
 
 	msm_device_otg.dev.platform_data = &msm_otg_pdata;
 	msm_otg_pdata.phy_init_seq = shelby_phy_init_seq;
+	msm_device_usb_bam.dev.platform_data = &msm_usb_bam_pdata;
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
 
 	acpuclk_init(&acpuclk_9615_soc_data);
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 3038ff0..765f49e 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -22,6 +22,7 @@
 #include <linux/leds.h>
 #include <linux/pmic8058-othc.h>
 #include <linux/mfd/pmic8901.h>
+#include <linux/regulator/gpio-regulator.h>
 #include <linux/regulator/pmic8901-regulator.h>
 #include <linux/bootmem.h>
 #include <linux/msm_adc.h>
@@ -54,7 +55,6 @@
 #include <asm/setup.h>
 
 #include <mach/dma.h>
-#include <mach/mpp.h>
 #include <mach/board.h>
 #include <mach/irqs.h>
 #include <mach/msm_spi.h>
@@ -83,6 +83,7 @@
 #include <mach/rpm.h>
 #include <mach/rpm-regulator.h>
 #include <mach/restart.h>
+#include <mach/board-msm8660.h>
 
 #include "devices.h"
 #include "devices-msm8x60.h"
@@ -104,23 +105,6 @@
 #include <mach/ion.h>
 
 #define MSM_SHARED_RAM_PHYS 0x40000000
-
-/* Macros assume PMIC GPIOs start at 0 */
-#define PM8058_GPIO_BASE			NR_MSM_GPIOS
-#define PM8058_GPIO_PM_TO_SYS(pm_gpio)		(pm_gpio + PM8058_GPIO_BASE)
-#define PM8058_GPIO_SYS_TO_PM(sys_gpio)		(sys_gpio - PM8058_GPIO_BASE)
-#define PM8058_MPP_BASE			(PM8058_GPIO_BASE + PM8058_GPIOS)
-#define PM8058_MPP_PM_TO_SYS(pm_gpio)		(pm_gpio + PM8058_MPP_BASE)
-#define PM8058_MPP_SYS_TO_PM(sys_gpio)		(sys_gpio - PM8058_MPP_BASE)
-#define PM8058_IRQ_BASE				(NR_MSM_IRQS + NR_GPIO_IRQS)
-
-#define PM8901_GPIO_BASE			(PM8058_GPIO_BASE + \
-						PM8058_GPIOS + PM8058_MPPS)
-#define PM8901_GPIO_PM_TO_SYS(pm_gpio)		(pm_gpio + PM8901_GPIO_BASE)
-#define PM8901_GPIO_SYS_TO_PM(sys_gpio)		(sys_gpio - PM901_GPIO_BASE)
-#define PM8901_IRQ_BASE				(PM8058_IRQ_BASE + \
-						NR_PMIC8058_IRQS)
-
 #define MDM2AP_SYNC 129
 
 #define GPIO_ETHERNET_RESET_N_DRAGON	30
@@ -150,7 +134,7 @@
 
 enum {
 	GPIO_EXPANDER_IRQ_BASE  = PM8901_IRQ_BASE + NR_PMIC8901_IRQS,
-	GPIO_EXPANDER_GPIO_BASE = PM8901_GPIO_BASE + PM8901_MPPS,
+	GPIO_EXPANDER_GPIO_BASE = PM8901_MPP_BASE + PM8901_MPPS,
 	/* CORE expander */
 	GPIO_CORE_EXPANDER_BASE = GPIO_EXPANDER_GPIO_BASE,
 	GPIO_CLASS_D1_EN        = GPIO_CORE_EXPANDER_BASE,
@@ -273,7 +257,7 @@
 	struct pm8xxx_mpp_config_data	config;
 };
 
-#define PM8XXX_MPP_INIT(_mpp, _type, _level, _control) \
+#define PM8058_MPP_INIT(_mpp, _type, _level, _control) \
 { \
 	.mpp	= PM8058_MPP_PM_TO_SYS(_mpp), \
 	.config	= { \
@@ -283,6 +267,16 @@
 	} \
 }
 
+#define PM8901_MPP_INIT(_mpp, _type, _level, _control) \
+{ \
+	.mpp	= PM8901_MPP_PM_TO_SYS(_mpp), \
+	.config	= { \
+		.type		= PM8XXX_MPP_TYPE_##_type, \
+		.level		= _level, \
+		.control	= PM8XXX_MPP_##_control, \
+	} \
+}
+
 /*
  * The UI_INTx_N lines are pmic gpio lines which connect i2c
  * gpio expanders to the pm8058.
@@ -1045,14 +1039,21 @@
 {
 	unsigned ret;
 
+	struct pm8xxx_mpp_config_data hsusb_phy_mpp = {
+		.type	= PM8XXX_MPP_TYPE_D_OUTPUT,
+		.level	= PM8901_MPP_DIG_LEVEL_L5,
+	};
+
 	if (init) {
-		ret = pm8901_mpp_config_digital_out(1,
-			PM8901_MPP_DIG_LEVEL_L5, 1);
+		hsusb_phy_mpp.control = PM8XXX_MPP_DOUT_CTRL_HIGH;
+		ret = pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(1),
+							&hsusb_phy_mpp);
 		if (ret < 0)
 			pr_err("%s:MPP2 configuration failed\n", __func__);
 	} else {
-		ret = pm8901_mpp_config_digital_out(1,
-			PM8901_MPP_DIG_LEVEL_L5, 0);
+		hsusb_phy_mpp.control = PM8XXX_MPP_DOUT_CTRL_LOW;
+		ret = pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(1),
+							&hsusb_phy_mpp);
 		if (ret < 0)
 			pr_err("%s:MPP2 un config failed\n", __func__);
 	}
@@ -4837,23 +4838,20 @@
 {
 	int rc, i;
 	struct pm8xxx_mpp_init_info xoadc_mpps[] = {
-		PM8XXX_MPP_INIT(XOADC_MPP_3, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH5,
+		PM8058_MPP_INIT(XOADC_MPP_3, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH5,
 							AOUT_CTRL_DISABLE),
-		PM8XXX_MPP_INIT(XOADC_MPP_5, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH9,
+		PM8058_MPP_INIT(XOADC_MPP_5, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH9,
 							AOUT_CTRL_DISABLE),
-		PM8XXX_MPP_INIT(XOADC_MPP_7, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH6,
+		PM8058_MPP_INIT(XOADC_MPP_7, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH6,
 							AOUT_CTRL_DISABLE),
-		PM8XXX_MPP_INIT(XOADC_MPP_8, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH8,
+		PM8058_MPP_INIT(XOADC_MPP_8, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH8,
 							AOUT_CTRL_DISABLE),
-		PM8XXX_MPP_INIT(XOADC_MPP_10, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH7,
+		PM8058_MPP_INIT(XOADC_MPP_10, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH7,
 							AOUT_CTRL_DISABLE),
+		PM8901_MPP_INIT(XOADC_MPP_4, D_OUTPUT, PM8901_MPP_DIG_LEVEL_S4,
+							DOUT_CTRL_LOW),
 	};
 
-	rc = pm8901_mpp_config_digital_out(XOADC_MPP_4,
-			PM8901_MPP_DIG_LEVEL_S4, PM_MPP_DOUT_CTL_LOW);
-	if (rc)
-		pr_err("%s: Config mpp4 on pmic 8901 failed\n", __func__);
-
 	for (i = 0; i < ARRAY_SIZE(xoadc_mpps); i++) {
 		rc = pm8xxx_mpp_config(xoadc_mpps[i].mpp,
 					&xoadc_mpps[i].config);
@@ -4982,6 +4980,75 @@
 
 #endif /* CONFIG_MSM_SDIO_AL */
 
+#define GPIO_VREG_ID_EXT_5V		0
+
+static struct regulator_consumer_supply vreg_consumers_EXT_5V[] = {
+	REGULATOR_SUPPLY("ext_5v",	NULL),
+	REGULATOR_SUPPLY("8901_mpp0",	NULL),
+};
+
+#define GPIO_VREG_INIT(_id, _reg_name, _gpio_label, _gpio, _active_low) \
+	[GPIO_VREG_ID_##_id] = { \
+		.init_data = { \
+			.constraints = { \
+				.valid_ops_mask	= REGULATOR_CHANGE_STATUS, \
+			}, \
+			.num_consumer_supplies	= \
+					ARRAY_SIZE(vreg_consumers_##_id), \
+			.consumer_supplies	= vreg_consumers_##_id, \
+		}, \
+		.regulator_name	= _reg_name, \
+		.active_low	= _active_low, \
+		.gpio_label	= _gpio_label, \
+		.gpio		= _gpio, \
+	}
+
+/* GPIO regulator constraints */
+static struct gpio_regulator_platform_data msm_gpio_regulator_pdata[] = {
+	GPIO_VREG_INIT(EXT_5V, "ext_5v", "ext_5v_en",
+					PM8901_MPP_PM_TO_SYS(0), 0),
+};
+
+/* GPIO regulator */
+static struct platform_device msm8x60_8901_mpp_vreg __devinitdata = {
+	.name	= GPIO_REGULATOR_DEV_NAME,
+	.id	= PM8901_MPP_PM_TO_SYS(0),
+	.dev	= {
+		.platform_data =
+			&msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V],
+	},
+};
+
+static void __init pm8901_vreg_mpp0_init(void)
+{
+	int rc;
+
+	struct pm8xxx_mpp_init_info pm8901_vreg_mpp0 = {
+		.mpp	= PM8901_MPP_PM_TO_SYS(0),
+		.config =  {
+			.type	= PM8XXX_MPP_TYPE_D_OUTPUT,
+			.level	= PM8901_MPP_DIG_LEVEL_VPH,
+		},
+	};
+
+	/*
+	 * Set PMIC 8901 MPP0 active_high to 0 for surf and charm_surf. This
+	 * implies that the regulator connected to MPP0 is enabled when
+	 * MPP0 is low.
+	 */
+	if (machine_is_msm8x60_surf() || machine_is_msm8x60_fusion()) {
+		msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V].active_low = 1;
+		pm8901_vreg_mpp0.config.control = PM8XXX_MPP_DOUT_CTRL_HIGH;
+	} else {
+		msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V].active_low = 0;
+		pm8901_vreg_mpp0.config.control = PM8XXX_MPP_DOUT_CTRL_LOW;
+	}
+
+	rc = pm8xxx_mpp_config(pm8901_vreg_mpp0.mpp, &pm8901_vreg_mpp0.config);
+	if (rc)
+		pr_err("%s: pm8xxx_mpp_config: rc=%d\n", __func__, rc);
+}
+
 static struct platform_device *charm_devices[] __initdata = {
 	&msm_charm_modem,
 #ifdef CONFIG_MSM_SDIO_AL
@@ -5309,9 +5376,9 @@
 #define EXT_CHG_VALID_MPP_2 11
 
 static struct pm8xxx_mpp_init_info isl_mpp[] = {
-	PM8XXX_MPP_INIT(EXT_CHG_VALID_MPP, D_INPUT,
+	PM8058_MPP_INIT(EXT_CHG_VALID_MPP, D_INPUT,
 		PM8058_MPP_DIG_LEVEL_S3, DIN_TO_INT),
-	PM8XXX_MPP_INIT(EXT_CHG_VALID_MPP_2, D_BI_DIR,
+	PM8058_MPP_INIT(EXT_CHG_VALID_MPP_2, D_BI_DIR,
 		PM8058_MPP_DIG_LEVEL_S3, BI_PULLUP_10KOHM),
 };
 
@@ -6526,32 +6593,10 @@
 #ifdef CONFIG_PMIC8901
 
 #define PM8901_GPIO_INT           91
-
-static struct pm8901_gpio_platform_data pm8901_mpp_data = {
-	.gpio_base	= PM8901_GPIO_PM_TO_SYS(0),
-	.irq_base	= PM8901_MPP_IRQ(PM8901_IRQ_BASE, 0),
-};
-
-static struct resource pm8901_temp_alarm[] = {
-	{
-		.start = PM8901_TEMP_ALARM_IRQ(PM8901_IRQ_BASE),
-		.end = PM8901_TEMP_ALARM_IRQ(PM8901_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.start = PM8901_TEMP_HI_ALARM_IRQ(PM8901_IRQ_BASE),
-		.end = PM8901_TEMP_HI_ALARM_IRQ(PM8901_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
 /*
  * Consumer specific regulator names:
  *			 regulator name		consumer dev_name
  */
-static struct regulator_consumer_supply vreg_consumers_8901_MPP0[] = {
-	REGULATOR_SUPPLY("8901_mpp0",		NULL),
-};
 static struct regulator_consumer_supply vreg_consumers_8901_USB_OTG[] = {
 	REGULATOR_SUPPLY("8901_usb_otg",	NULL),
 };
@@ -6560,8 +6605,8 @@
 };
 
 #define PM8901_VREG_INIT(_id, _min_uV, _max_uV, _modes, _ops, _apply_uV, \
-			 _always_on, _active_high) \
-	[PM8901_VREG_ID_##_id] = { \
+			 _always_on) \
+	{ \
 		.init_data = { \
 			.constraints = { \
 				.valid_modes_mask = _modes, \
@@ -6576,53 +6621,33 @@
 			.num_consumer_supplies = \
 				ARRAY_SIZE(vreg_consumers_8901_##_id), \
 		}, \
-		.active_high = _active_high, \
+		.id = PM8901_VREG_ID_##_id, \
 	}
 
-#define PM8901_VREG_INIT_MPP(_id, _active_high) \
-	PM8901_VREG_INIT(_id, 0, 0, REGULATOR_MODE_NORMAL, \
-			REGULATOR_CHANGE_STATUS, 0, 0, _active_high)
-
 #define PM8901_VREG_INIT_VS(_id) \
 	PM8901_VREG_INIT(_id, 0, 0, REGULATOR_MODE_NORMAL, \
-			REGULATOR_CHANGE_STATUS, 0, 0, 0)
+			REGULATOR_CHANGE_STATUS, 0, 0)
 
-static struct pm8901_vreg_pdata pm8901_vreg_init_pdata[PM8901_VREG_MAX] = {
-	PM8901_VREG_INIT_MPP(MPP0, 1),
-
+static struct pm8901_vreg_pdata pm8901_vreg_init[] = {
 	PM8901_VREG_INIT_VS(USB_OTG),
 	PM8901_VREG_INIT_VS(HDMI_MVS),
 };
 
-#define PM8901_VREG(_id) { \
-	.name = "pm8901-regulator", \
-	.id = _id, \
-	.platform_data = &pm8901_vreg_init_pdata[_id], \
-	.pdata_size = sizeof(pm8901_vreg_init_pdata[_id]), \
-}
+static struct pm8xxx_irq_platform_data pm8901_irq_pdata = {
+	.irq_base		= PM8901_IRQ_BASE,
+	.devirq			= MSM_GPIO_TO_INT(PM8901_GPIO_INT),
+	.irq_trigger_flag	= IRQF_TRIGGER_LOW,
+};
 
-static struct mfd_cell pm8901_subdevs[] = {
-	{	.name = "pm8901-mpp",
-		.id		= -1,
-		.platform_data	= &pm8901_mpp_data,
-		.pdata_size      = sizeof(pm8901_mpp_data),
-	},
-	{	.name = "pm8901-tm",
-		.id		= -1,
-		.num_resources  = ARRAY_SIZE(pm8901_temp_alarm),
-		.resources      = pm8901_temp_alarm,
-	},
-	PM8901_VREG(PM8901_VREG_ID_MPP0),
-	PM8901_VREG(PM8901_VREG_ID_USB_OTG),
-	PM8901_VREG(PM8901_VREG_ID_HDMI_MVS),
+static struct pm8xxx_mpp_platform_data pm8901_mpp_pdata = {
+	.mpp_base		= PM8901_MPP_PM_TO_SYS(0),
 };
 
 static struct pm8901_platform_data pm8901_platform_data = {
-	.irq_base = PM8901_IRQ_BASE,
-	.irq = MSM_GPIO_TO_INT(PM8901_GPIO_INT),
-	.num_subdevs = ARRAY_SIZE(pm8901_subdevs),
-	.sub_devices = pm8901_subdevs,
-	.irq_trigger_flags = IRQF_TRIGGER_LOW,
+	.irq_pdata		= &pm8901_irq_pdata,
+	.mpp_pdata		= &pm8901_mpp_pdata,
+	.regulator_pdatas	= pm8901_vreg_init,
+	.num_regulators		= ARRAY_SIZE(pm8901_vreg_init),
 };
 
 static struct msm_ssbi_platform_data msm8x60_ssbi_pm8901_pdata __devinitdata = {
@@ -7106,15 +7131,6 @@
 		sx150x_data[SX150X_CORE_FLUID].irq_summary =
 			PM8058_GPIO_IRQ(PM8058_IRQ_BASE, UI_INT1_N);
 #endif
-	/*
-	 * Set PMIC 8901 MPP0 active_high to 0 for surf and charm_surf. This
-	 * implies that the regulator connected to MPP0 is enabled when
-	 * MPP0 is low.
-	 */
-	if (machine_is_msm8x60_surf() || machine_is_msm8x60_fusion())
-		pm8901_vreg_init_pdata[PM8901_VREG_ID_MPP0].active_high = 0;
-	else
-		pm8901_vreg_init_pdata[PM8901_VREG_ID_MPP0].active_high = 1;
 #endif
 }
 
@@ -9905,7 +9921,13 @@
 static void __init msm8x60_init(struct msm_board_data *board_data)
 {
 	uint32_t soc_platform_version;
-
+#ifdef CONFIG_USB_EHCI_MSM_72K
+	struct pm8xxx_mpp_config_data hsusb_phy_mpp = {
+		.type		= PM8XXX_MPP_TYPE_D_OUTPUT,
+		.level		= PM8901_MPP_DIG_LEVEL_L5,
+		.control	= PM8XXX_MPP_DOUT_CTRL_HIGH,
+	};
+#endif
 	pmic_reset_irq = PM8058_IRQ_BASE + PM8058_RESOUT_IRQ;
 
 	/*
@@ -10057,16 +10079,18 @@
 		}
 #endif
 
+	pm8901_vreg_mpp0_init();
+
+	platform_device_register(&msm8x60_8901_mpp_vreg);
+
 #ifdef CONFIG_USB_EHCI_MSM_72K
 	/*
 	 * Drive MPP2 pin HIGH for PHY to generate ID interrupts on 8660
 	 * fluid
 	 */
-	if (machine_is_msm8x60_fluid()) {
-		pm8901_mpp_config_digital_out(1,
-			PM8901_MPP_DIG_LEVEL_L5, 1);
-	}
-		msm_add_host(0, &msm_usb_host_pdata);
+	if (machine_is_msm8x60_fluid())
+		pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(1), &hsusb_phy_mpp);
+	msm_add_host(0, &msm_usb_host_pdata);
 #endif
 
 #ifdef CONFIG_SND_SOC_MSM8660_APQ
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 91bb455..537251a 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -676,6 +676,10 @@
 		goto reg_fail;
 	}
 
+	gpio_tlmm_config(GPIO_CFG(GPIO_BT_SYS_REST_EN, 0,
+				GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
+				GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+
 	/*setup Bahama_sys_reset_n*/
 	rc = gpio_request(GPIO_BT_SYS_REST_EN, "bahama sys_rst_n");
 	if (rc < 0) {
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index d7322b6..841c899 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5407,6 +5407,7 @@
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,		NULL),
 	CLK_LOOKUP("cam_clk",		cam1_clk.c,		NULL),
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"msm_camera_imx074.0"),
+	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"msm_camera_mt9m114.0"),
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"msm_camera_ov2720.0"),
 	CLK_LOOKUP("csi_src_clk",	csi0_src_clk.c,		"msm_csid.0"),
 	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		"msm_csid.1"),
@@ -5646,7 +5647,7 @@
 	rmwreg(0x80FF0000, DSI2_BYTE_CC_REG,  0xE0FF0010);
 	rmwreg(0x80FF0000, DSI_PIXEL_CC_REG,  0xE0FF0010);
 	rmwreg(0x80FF0000, DSI2_PIXEL_CC_REG, 0xE0FF0010);
-	rmwreg(0x80FF0000, GFX3D_CC_REG,      0xE0FF0010);
+	rmwreg(0xC0FF0000, GFX3D_CC_REG,      0xE0FF0010);
 	rmwreg(0x80FF0000, IJPEG_CC_REG,      0xE0FF0010);
 	rmwreg(0x80FF0000, JPEGD_CC_REG,      0xE0FF0010);
 	rmwreg(0x80FF0000, MDP_CC_REG,        0xE1FF0010);
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 208ed4e..8c251ba 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -564,6 +564,7 @@
 	.memtype = MEMTYPE_EBI1,
 	.enable_ion = 0,
 #endif
+	.disable_dmx = 0,
 };
 
 struct platform_device msm_device_vidc = {
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 012eb85..63a86cb 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -99,6 +99,9 @@
 	},
 };
 
+#define MSM_USB_BAM_BASE     0x12502000
+#define MSM_USB_BAM_SIZE     0x3DFFF
+
 static struct resource resources_otg[] = {
 	{
 		.start	= MSM9615_HSUSB_PHYS,
@@ -135,6 +138,28 @@
 	},
 };
 
+static struct resource resources_usb_bam[] = {
+	{
+		.name	= "usb_bam_addr",
+		.start	= MSM_USB_BAM_BASE,
+		.end	= MSM_USB_BAM_BASE + MSM_USB_BAM_SIZE,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "usb_bam_irq",
+		.start	= USB1_HS_BAM_IRQ,
+		.end	= USB1_HS_BAM_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm_device_usb_bam = {
+	.name		= "usb_bam",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(resources_usb_bam),
+	.resource	= resources_usb_bam,
+};
+
 struct platform_device msm_device_gadget_peripheral = {
 	.name		= "msm_hsusb",
 	.id		= -1,
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 41136d2..2c21f57 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -790,7 +790,8 @@
 
 struct msm_vidc_platform_data vidc_platform_data = {
 	.memtype = MEMTYPE_EBI0,
-	.enable_ion = 0
+	.enable_ion = 0,
+	.disable_dmx = 0
 };
 
 struct platform_device msm_device_vidc_720p = {
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index b9ff604..72fdcf7 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -2129,6 +2129,7 @@
 	.memtype = MEMTYPE_SMI_KERNEL,
 	.enable_ion = 0,
 #endif
+	.disable_dmx = 0
 };
 
 struct platform_device msm_device_vidc = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 2fac2ef..ffe22f8 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -118,6 +118,7 @@
 
 extern struct platform_device msm_slim_ctrl;
 extern struct platform_device msm_device_sps;
+extern struct platform_device msm_device_usb_bam;
 extern struct platform_device msm_device_sps_apq8064;
 extern struct platform_device msm_device_bam_dmux;
 extern struct platform_device msm_device_smd;
diff --git a/arch/arm/mach-msm/include/mach/board-msm8660.h b/arch/arm/mach-msm/include/mach/board-msm8660.h
new file mode 100644
index 0000000..b07cc62
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/board-msm8660.h
@@ -0,0 +1,36 @@
+/* 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_BOARD_MSM8660_H
+#define __ARCH_ARM_MACH_MSM_BOARD_MSM8660_H
+
+#include <linux/mfd/pmic8058.h>
+#include <linux/mfd/pmic8901.h>
+#include <mach/irqs.h>
+
+/* Macros assume PMIC GPIOs start at 0 */
+#define PM8058_GPIO_BASE			NR_MSM_GPIOS
+#define PM8058_GPIO_PM_TO_SYS(pm_gpio)		(pm_gpio + PM8058_GPIO_BASE)
+#define PM8058_GPIO_SYS_TO_PM(sys_gpio)		(sys_gpio - PM8058_GPIO_BASE)
+#define PM8058_MPP_BASE			(PM8058_GPIO_BASE + PM8058_GPIOS)
+#define PM8058_MPP_PM_TO_SYS(pm_gpio)		(pm_gpio + PM8058_MPP_BASE)
+#define PM8058_MPP_SYS_TO_PM(sys_gpio)		(sys_gpio - PM8058_MPP_BASE)
+#define PM8058_IRQ_BASE				(NR_MSM_IRQS + NR_GPIO_IRQS)
+
+#define PM8901_MPP_BASE				(PM8058_GPIO_BASE + \
+						PM8058_GPIOS + PM8058_MPPS)
+#define PM8901_MPP_PM_TO_SYS(pm_gpio)		(pm_gpio + PM8901_MPP_BASE)
+#define PM8901_MPP_SYS_TO_PM(sys_gpio)		(sys_gpio - PM901_MPP_BASE)
+#define PM8901_IRQ_BASE				(PM8058_IRQ_BASE + \
+						NR_PMIC8058_IRQS)
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 2116ee7..06a389e 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -405,6 +405,7 @@
 struct msm_vidc_platform_data {
 	int memtype;
 	u32 enable_ion;
+	int disable_dmx;
 #ifdef CONFIG_MSM_BUS_SCALING
 	struct msm_bus_scale_pdata *vidc_bus_client_pdata;
 #endif
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index b41398e..ce89c14 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -195,6 +195,7 @@
 #define VFE31_OUTPUT_MODE_T (0x1 << 4)
 
 #define CSI_EMBED_DATA 0x12
+#define CSI_YUV422_8  0x1E
 #define CSI_RAW8    0x2A
 #define CSI_RAW10   0x2B
 #define CSI_RAW12   0x2C
diff --git a/arch/arm/mach-msm/include/mach/msm_memtypes.h b/arch/arm/mach-msm/include/mach/msm_memtypes.h
index 2c278a6..29a9d4a 100644
--- a/arch/arm/mach-msm/include/mach/msm_memtypes.h
+++ b/arch/arm/mach-msm/include/mach/msm_memtypes.h
@@ -62,4 +62,6 @@
 };
 
 extern struct reserve_info *reserve_info;
+
+unsigned long __init reserve_memory_for_fmem(unsigned long);
 #endif
diff --git a/drivers/net/wireless/wcnss/wcnss_riva.h b/arch/arm/mach-msm/include/mach/msm_tspp.h
similarity index 61%
rename from drivers/net/wireless/wcnss/wcnss_riva.h
rename to arch/arm/mach-msm/include/mach/msm_tspp.h
index e037f58..6912f0c 100644
--- a/drivers/net/wireless/wcnss/wcnss_riva.h
+++ b/arch/arm/mach-msm/include/mach/msm_tspp.h
@@ -10,22 +10,15 @@
  * GNU General Public License for more details.
  */
 
-#ifndef _WCNSS_RIVA_H_
-#define _WCNSS_RIVA_H_
+#ifndef _MSM_TSPP_H_
+#define _MSM_TSPP_H_
 
-#include <linux/device.h>
-
-enum wcnss_opcode {
-	WCNSS_WLAN_SWITCH_OFF = 0,
-	WCNSS_WLAN_SWITCH_ON,
+struct msm_tspp_platform_data {
+	int num_gpios;
+	const struct msm_gpio *gpios;
+	const char *tsif_pclk;
+	const char *tsif_ref_clk;
 };
 
-struct wcnss_wlan_config {
-	int		use_48mhz_xo;
-};
+#endif /* _MSM_TSPP_H_ */
 
-int wcnss_wlan_power(struct device *dev,
-		struct wcnss_wlan_config *cfg,
-		enum wcnss_opcode opcode);
-
-#endif /* _WCNSS_RIVA_H_ */
diff --git a/arch/arm/mach-msm/include/mach/usb_bam.h b/arch/arm/mach-msm/include/mach/usb_bam.h
new file mode 100644
index 0000000..4caa71b
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/usb_bam.h
@@ -0,0 +1,40 @@
+/* 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 _USB_BAM_H_
+#define _USB_BAM_H_
+
+/**
+ * Connect USB-to-Periperal SPS connection.
+ *
+ * This function returns the allocated pipes number.
+ *
+ * @idx - Connection index.
+ *
+ * @src_pipe_idx - allocated pipe index - USB as a
+ *  source (output)
+ *
+ * @dst_pipe_idx - allocated pipe index - USB as a
+ * destination (output)
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+#ifdef CONFIG_USB_BAM
+int usb_bam_connect(u8 idx, u8 *src_pipe_idx, u8 *dst_pipe_idx);
+#else
+int usb_bam_connect(u8 idx, u8 *src_pipe_idx, u8 *dst_pipe_idx)
+{
+	return -ENODEV;
+}
+#endif
+#endif				/* _USB_BAM_H_ */
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 31fbd43..33db3fa 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -304,6 +304,24 @@
 	}
 }
 
+unsigned long __init reserve_memory_for_fmem(unsigned long fmem_size)
+{
+	struct membank *mb;
+	int ret;
+	unsigned long fmem_phys;
+
+	if (!fmem_size)
+		return 0;
+
+	mb = &meminfo.bank[meminfo.nr_banks - 1];
+	fmem_phys = mb->start + (mb->size - fmem_size);
+	ret = memblock_remove(fmem_phys, fmem_size);
+	BUG_ON(ret);
+
+	pr_info("fmem start %lx size %lx\n", fmem_phys, fmem_size);
+	return fmem_phys;
+}
+
 static void __init initialize_mempools(void)
 {
 	struct mem_pool *mpool;
diff --git a/arch/arm/mach-msm/memory_topology.c b/arch/arm/mach-msm/memory_topology.c
index 7a75bc1..5854a23 100644
--- a/arch/arm/mach-msm/memory_topology.c
+++ b/arch/arm/mach-msm/memory_topology.c
@@ -113,7 +113,7 @@
 
 static int switch_memory_state(int id, int new_state)
 {
-	int mask;
+	int mask = 0;
 	int power_down_masks[MAX_NR_REGIONS] = { 0xFFFFFF00, 0xFFFF00FF,
 						0xFF00FFFF, 0x00FFFFFF };
 	int self_refresh_masks[MAX_NR_REGIONS] = { 0xFFFFFFF0, 0xFFFFFF0F,
diff --git a/arch/arm/mach-msm/qdsp6v2/aac_in.c b/arch/arm/mach-msm/qdsp6v2/aac_in.c
index 7140601..2519bb7 100644
--- a/arch/arm/mach-msm/qdsp6v2/aac_in.c
+++ b/arch/arm/mach-msm/qdsp6v2/aac_in.c
@@ -214,6 +214,12 @@
 			rc = -EINVAL;
 			break;
 		}
+		if ((cfg.bit_rate < 24000) || (cfg.bit_rate > 192000)) {
+			pr_err("%s: ERROR in setting bitrate = %d\n",
+				__func__, cfg.bit_rate);
+			rc = -EINVAL;
+			break;
+		}
 		enc_cfg->sample_rate = cfg.sample_rate;
 		enc_cfg->channels = cfg.channels;
 		enc_cfg->bit_rate = cfg.bit_rate;
diff --git a/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c b/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c
index 135dd03..11687ac 100644
--- a/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c
+++ b/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c
@@ -17,19 +17,16 @@
 #include <linux/delay.h>
 #include <linux/debugfs.h>
 #include <linux/mfd/pmic8058.h>
-#include <linux/pmic8058-othc.h>
 #include <linux/mfd/pmic8901.h>
 #include <linux/mfd/msm-adie-codec.h>
-#include <linux/regulator/pmic8058-regulator.h>
-#include <linux/regulator/pmic8901-regulator.h>
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/machine.h>
 
 #include <mach/qdsp6v2/audio_dev_ctl.h>
-#include <mach/mpp.h>
 #include <sound/apr_audio.h>
 #include <asm/mach-types.h>
 #include <asm/uaccess.h>
+#include <mach/board-msm8660.h>
 
 #include "snddev_icodec.h"
 #include "snddev_ecodec.h"
@@ -266,10 +263,15 @@
 {
 	int rc;
 
-	if (enable) {
-		rc = pm8901_mpp_config_digital_out(PM8901_MPP_3,
-			PM8901_MPP_DIG_LEVEL_MSMIO, 1);
+	struct pm8xxx_mpp_config_data class_d0_mpp = {
+		.type		= PM8XXX_MPP_TYPE_D_OUTPUT,
+		.level		= PM8901_MPP_DIG_LEVEL_MSMIO,
+	};
 
+	if (enable) {
+		class_d0_mpp.control = PM8XXX_MPP_DOUT_CTRL_HIGH;
+		rc = pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(PM8901_MPP_3),
+							&class_d0_mpp);
 		if (rc) {
 			pr_err("%s: CLASS_D0_EN failed\n", __func__);
 			return rc;
@@ -280,18 +282,20 @@
 		if (rc) {
 			pr_err("%s: spkr pamp gpio pm8901 mpp3 request"
 			"failed\n", __func__);
-			pm8901_mpp_config_digital_out(PM8901_MPP_3,
-			PM8901_MPP_DIG_LEVEL_MSMIO, 0);
+			class_d0_mpp.control = PM8XXX_MPP_DOUT_CTRL_LOW;
+			pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(PM8901_MPP_3),
+						&class_d0_mpp);
 			return rc;
 		}
 
 		gpio_direction_output(SNDDEV_GPIO_CLASS_D0_EN, 1);
-		gpio_set_value(SNDDEV_GPIO_CLASS_D0_EN, 1);
+		gpio_set_value_cansleep(SNDDEV_GPIO_CLASS_D0_EN, 1);
 
 	} else {
-		pm8901_mpp_config_digital_out(PM8901_MPP_3,
-		PM8901_MPP_DIG_LEVEL_MSMIO, 0);
-		gpio_set_value(SNDDEV_GPIO_CLASS_D0_EN, 0);
+		class_d0_mpp.control = PM8XXX_MPP_DOUT_CTRL_LOW;
+		pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(PM8901_MPP_3),
+						&class_d0_mpp);
+		gpio_set_value_cansleep(SNDDEV_GPIO_CLASS_D0_EN, 0);
 		gpio_free(SNDDEV_GPIO_CLASS_D0_EN);
 	}
 	return 0;
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 18b7334..af92d22 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -17,6 +17,8 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/wcnss_wlan.h>
 #include <mach/irqs.h>
 #include <mach/scm.h>
 #include <mach/subsystem_restart.h>
@@ -79,14 +81,32 @@
 /* Subsystem handlers */
 static int riva_shutdown(const struct subsys_data *subsys)
 {
+	struct platform_device *pdev = wcnss_get_platform_device();
+	struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
+	int    ret = -1;
+
 	pil_force_shutdown("wcnss");
-	return 0;
+
+	/* proxy vote on behalf of Riva */
+	if (pdev && pwlanconfig)
+		ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
+					WCNSS_WLAN_SWITCH_OFF);
+	return ret;
 }
 
 static int riva_powerup(const struct subsys_data *subsys)
 {
-	pil_force_boot("wcnss");
-	return 0;
+	struct platform_device *pdev = wcnss_get_platform_device();
+	struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
+	int    ret = -1;
+
+	if (pdev && pwlanconfig)
+		ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
+					WCNSS_WLAN_SWITCH_ON);
+	if (!ret)
+		pil_force_boot("wcnss");
+
+	return ret;
 }
 
 /* RAM segments for Riva SS;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 58c9b9a..c8555cd 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -503,9 +503,11 @@
 	} else {
 		if (len > 0) {
 			if (entry.client_id == MODEM_PROC && driver->ch) {
-				if ((cpu_is_msm8960() || cpu_is_msm8930()) &&
+				if ((cpu_is_msm8960() || cpu_is_msm8930() ||
+					cpu_is_msm9615()) &&
 					 (int)(*(char *)buf) == MODE_CMD)
-					if ((int)(*(char *)(buf+1)) == RESET_ID)
+					if ((int)(*(char *)(buf+1)) ==
+						RESET_ID)
 						return;
 				smd_write(driver->ch, buf, len);
 			} else if (entry.client_id == QDSP_PROC &&
@@ -542,7 +544,8 @@
 	temp += 2;
 	data_type = APPS_DATA;
 	/* Dont send any command other than mode reset */
-	if ((cpu_is_msm8960() || cpu_is_msm8930()) && cmd_code == MODE_CMD) {
+	if ((cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615()) &&
+		cmd_code == MODE_CMD) {
 		if (subsys_id != RESET_ID)
 			data_type = MODEM_DATA;
 	}
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index dd7b1d6..e8bad9d 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -278,7 +278,7 @@
 DEVICE_ATTR(gpuclk, 0644, kgsl_pwrctrl_gpuclk_show, kgsl_pwrctrl_gpuclk_store);
 DEVICE_ATTR(max_gpuclk, 0644, kgsl_pwrctrl_max_gpuclk_show,
 	kgsl_pwrctrl_max_gpuclk_store);
-DEVICE_ATTR(pwrnap, 0644, kgsl_pwrctrl_pwrnap_show, kgsl_pwrctrl_pwrnap_store);
+DEVICE_ATTR(pwrnap, 0666, kgsl_pwrctrl_pwrnap_show, kgsl_pwrctrl_pwrnap_store);
 DEVICE_ATTR(idle_timer, 0644, kgsl_pwrctrl_idle_timer_show,
 	kgsl_pwrctrl_idle_timer_store);
 DEVICE_ATTR(gpubusy, 0644, kgsl_pwrctrl_gpubusy_show,
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index b5c6876..114053c 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -90,7 +90,7 @@
 	return ret;
 }
 
-PWRSCALE_ATTR(policy, 0644, pwrscale_policy_show, pwrscale_policy_store);
+PWRSCALE_ATTR(policy, 0666, pwrscale_policy_show, pwrscale_policy_store);
 
 static ssize_t pwrscale_avail_policies_show(struct kgsl_device *device,
 					    char *buf)
diff --git a/drivers/hwmon/pm8xxx-adc.c b/drivers/hwmon/pm8xxx-adc.c
index 5da80d9..6b3aa0c 100644
--- a/drivers/hwmon/pm8xxx-adc.c
+++ b/drivers/hwmon/pm8xxx-adc.c
@@ -974,22 +974,14 @@
 {
 	struct pm8xxx_adc *adc_pmic = pmic_adc;
 	int i, rc;
-	u8 data_arb_btm_cntrl;
+	u8 data_arb_btm_cntrl = 0;
 	unsigned long flags;
 
 	disable_irq_nosync(adc_pmic->btm_warm_irq);
 	disable_irq_nosync(adc_pmic->btm_cool_irq);
 
 	spin_lock_irqsave(&adc_pmic->btm_lock, flags);
-	/* Set BTM registers to Disable mode */
-	rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_BTM_CNTRL1,
-						&data_arb_btm_cntrl);
-	if (rc < 0) {
-		spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
-		return rc;
-	}
 
-	data_arb_btm_cntrl |= ~PM8XXX_ADC_ARB_BTM_CNTRL1_EN_BTM;
 	/* Write twice to the CNTRL register for the arbiter settings
 	   to take into effect */
 	for (i = 0; i < 2; i++) {
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index d09f89f..b73775c 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -2433,7 +2433,7 @@
 		.minimum       = 0,
 		.maximum       = 1,
 	},
-	{	.id	       = V4L2_CID_PRIVATE_TAVARUA_SET_NOTCH_FILTER,
+	{	.id	       = V4L2_CID_PRIVATE_SET_NOTCH_FILTER,
 		.type	       = V4L2_CTRL_TYPE_INTEGER,
 		.name	       = "Notch filter",
 		.minimum       = 0,
@@ -3297,9 +3297,20 @@
 		if (retval < 0)
 			FMDBG("write failed");
 	} break;
-	/*This IOCTL is a place holder to keep the
+	/*These IOCTL's are place holders to keep the
 	driver compatible with change in frame works for IRIS */
-	case V4L2_CID_PRIVATE_TAVARUA_SET_NOTCH_FILTER:
+	case V4L2_CID_PRIVATE_SOFT_MUTE:
+	case V4L2_CID_PRIVATE_RIVA_ACCS_ADDR:
+	case V4L2_CID_PRIVATE_RIVA_ACCS_LEN:
+	case V4L2_CID_PRIVATE_RIVA_PEEK:
+	case V4L2_CID_PRIVATE_RIVA_POKE:
+	case V4L2_CID_PRIVATE_SSBI_ACCS_ADDR:
+	case V4L2_CID_PRIVATE_SSBI_PEEK:
+	case V4L2_CID_PRIVATE_SSBI_POKE:
+	case V4L2_CID_PRIVATE_TX_TONE:
+	case V4L2_CID_PRIVATE_RDS_GRP_COUNTERS:
+	case V4L2_CID_PRIVATE_SET_NOTCH_FILTER:
+	case V4L2_CID_PRIVATE_TAVARUA_DO_CALIBRATION:
 		retval = 0;
 		break;
 	default:
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index 0d822bb..aa0e392 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -49,6 +49,11 @@
 	default n
 	---help---
 	  Omni Vision VGA YUV Sensor for QRD Devices
+config MT9M114
+        bool "Sensor MT9M114 (YUV 1.26M)"
+        depends on MSM_CAMERA && ARCH_MSM8960
+        ---help---
+        APTINA 1.26 MP yuv Sensor
 config WEBCAM_OV7692
 	bool "Sensor OV7692 (VGA YUV)"
 	depends on MSM_CAMERA && ARCH_MSM8X60 && !MSM_CAMERA_V4L2
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.c b/drivers/media/video/msm/io/msm_camera_i2c.c
index 23db5f6b..a3cc012 100644
--- a/drivers/media/video/msm/io/msm_camera_i2c.c
+++ b/drivers/media/video/msm/io/msm_camera_i2c.c
@@ -250,42 +250,52 @@
 	int32_t rc = -EFAULT;
 	for (i = 0; i < size; i++) {
 		enum msm_camera_i2c_data_type dt;
-		if (reg_conf_tbl->dt == 0)
-			dt = data_type;
-		else
-			dt = reg_conf_tbl->dt;
+		if (reg_conf_tbl->cmd_type == MSM_CAMERA_I2C_CMD_POLL) {
+			rc = msm_camera_i2c_poll(client, reg_conf_tbl->reg_addr,
+				reg_conf_tbl->reg_addr, reg_conf_tbl->dt);
+		} else {
+			if (reg_conf_tbl->dt == 0)
+				dt = data_type;
+			else
+				dt = reg_conf_tbl->dt;
 
-		switch (dt) {
-		case MSM_CAMERA_I2C_BYTE_DATA:
-		case MSM_CAMERA_I2C_WORD_DATA:
-			rc = msm_camera_i2c_write(
-				client,
-				reg_conf_tbl->reg_addr,
-				reg_conf_tbl->reg_data, dt);
-			break;
-		case MSM_CAMERA_I2C_SET_BYTE_MASK:
-			rc = msm_camera_i2c_set_mask(client,
-				reg_conf_tbl->reg_addr, reg_conf_tbl->reg_data,
-				MSM_CAMERA_I2C_BYTE_DATA, 1);
-			break;
-		case MSM_CAMERA_I2C_UNSET_BYTE_MASK:
-			rc = msm_camera_i2c_set_mask(client,
-				reg_conf_tbl->reg_addr, reg_conf_tbl->reg_data,
-				MSM_CAMERA_I2C_BYTE_DATA, 0);
-			break;
-		case MSM_CAMERA_I2C_SET_WORD_MASK:
-			rc = msm_camera_i2c_set_mask(client,
-				reg_conf_tbl->reg_addr, reg_conf_tbl->reg_data,
-				MSM_CAMERA_I2C_WORD_DATA, 1);
-			break;
-		case MSM_CAMERA_I2C_UNSET_WORD_MASK:
-			rc = msm_camera_i2c_set_mask(client,
-				reg_conf_tbl->reg_addr, reg_conf_tbl->reg_data,
-				MSM_CAMERA_I2C_WORD_DATA, 0);
-			break;
-		default:
-			pr_err("%s: Unsupport data type: %d\n", __func__, dt);
-			break;
+			switch (dt) {
+			case MSM_CAMERA_I2C_BYTE_DATA:
+			case MSM_CAMERA_I2C_WORD_DATA:
+				rc = msm_camera_i2c_write(
+					client,
+					reg_conf_tbl->reg_addr,
+					reg_conf_tbl->reg_data, dt);
+				break;
+			case MSM_CAMERA_I2C_SET_BYTE_MASK:
+				rc = msm_camera_i2c_set_mask(client,
+					reg_conf_tbl->reg_addr,
+					reg_conf_tbl->reg_data,
+					MSM_CAMERA_I2C_BYTE_DATA, 1);
+				break;
+			case MSM_CAMERA_I2C_UNSET_BYTE_MASK:
+				rc = msm_camera_i2c_set_mask(client,
+					reg_conf_tbl->reg_addr,
+					reg_conf_tbl->reg_data,
+					MSM_CAMERA_I2C_BYTE_DATA, 0);
+				break;
+			case MSM_CAMERA_I2C_SET_WORD_MASK:
+				rc = msm_camera_i2c_set_mask(client,
+					reg_conf_tbl->reg_addr,
+					reg_conf_tbl->reg_data,
+					MSM_CAMERA_I2C_WORD_DATA, 1);
+				break;
+			case MSM_CAMERA_I2C_UNSET_WORD_MASK:
+				rc = msm_camera_i2c_set_mask(client,
+					reg_conf_tbl->reg_addr,
+					reg_conf_tbl->reg_data,
+					MSM_CAMERA_I2C_WORD_DATA, 0);
+				break;
+			default:
+				pr_err("%s: Unsupport data type: %d\n",
+					__func__, dt);
+				break;
+			}
 		}
 		if (rc < 0)
 			break;
@@ -364,16 +374,10 @@
 			struct msm_camera_i2c_conf_array *array, uint16_t index)
 {
 	int32_t rc;
-	if (array[index].pre_process != NULL)
-		array[index].pre_process();
 
 	rc = msm_camera_i2c_write_tbl(client,
 		(struct msm_camera_i2c_reg_conf *) array[index].conf,
 		array[index].size, array[index].data_type);
-
-	if (array[index].post_process != NULL)
-		array[index].post_process();
-
 	if (array[index].delay > 20)
 		msleep(array[index].delay);
 	else
@@ -382,6 +386,34 @@
 	return rc;
 }
 
+int32_t msm_sensor_write_enum_conf_array(struct msm_camera_i2c_client *client,
+			struct msm_camera_i2c_enum_conf_array *conf,
+			uint16_t enum_val)
+{
+	int32_t rc = -1, i;
+	for (i = 0; i < conf->num_enum; i++) {
+		if (conf->conf_enum[i] == enum_val)
+			break;
+		if (conf->conf_enum[i] > enum_val)
+			break;
+	}
+	if (i == conf->num_enum)
+		i = conf->num_enum - 1;
+
+	if (i >= conf->num_index)
+		return rc;
+
+	rc = msm_sensor_write_all_conf_array(client,
+		&conf->conf[i*conf->num_conf], conf->num_conf);
+
+	if (conf->delay > 20)
+		msleep(conf->delay);
+	else
+		usleep_range(conf->delay*1000,
+					(conf->delay+1)*1000);
+	return rc;
+}
+
 int32_t msm_sensor_write_all_conf_array(struct msm_camera_i2c_client *client,
 			struct msm_camera_i2c_conf_array *array, uint16_t size)
 {
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.h b/drivers/media/video/msm/io/msm_camera_i2c.h
index 05b3960..2fbf5ca 100644
--- a/drivers/media/video/msm/io/msm_camera_i2c.h
+++ b/drivers/media/video/msm/io/msm_camera_i2c.h
@@ -44,10 +44,16 @@
 	MSM_CAMERA_I2C_UNSET_WORD_MASK,
 };
 
+enum msm_camera_i2c_cmd_type {
+	MSM_CAMERA_I2C_CMD_WRITE,
+	MSM_CAMERA_I2C_CMD_POLL,
+};
+
 struct msm_camera_i2c_reg_conf {
 	uint16_t reg_addr;
 	uint16_t reg_data;
 	enum msm_camera_i2c_data_type dt;
+	enum msm_camera_i2c_cmd_type cmd_type;
 };
 
 struct msm_camera_i2c_conf_array {
@@ -55,8 +61,16 @@
 	uint16_t size;
 	uint16_t delay;
 	enum msm_camera_i2c_data_type data_type;
-	int (*pre_process) (void);
-	int (*post_process) (void);
+};
+
+struct msm_camera_i2c_enum_conf_array {
+	struct msm_camera_i2c_conf_array *conf;
+	int *conf_enum;
+	uint16_t num_enum;
+	uint16_t num_index;
+	uint16_t num_conf;
+	uint16_t delay;
+	enum msm_camera_i2c_data_type data_type;
 };
 
 int32_t msm_camera_i2c_rxdata(struct msm_camera_i2c_client *client,
@@ -98,6 +112,9 @@
 int32_t msm_sensor_write_conf_array(struct msm_camera_i2c_client *client,
 	struct msm_camera_i2c_conf_array *array, uint16_t index);
 
+int32_t msm_sensor_write_enum_conf_array(struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_enum_conf_array *conf, uint16_t enum_val);
+
 int32_t msm_sensor_write_all_conf_array(struct msm_camera_i2c_client *client,
 	struct msm_camera_i2c_conf_array *array, uint16_t size);
 #endif
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 73fd383..8d502da 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -261,6 +261,45 @@
 			rc = p_mctl->sync.sctrl.s_config(argp);
 			break;
 
+	case MSM_CAM_IOCTL_SENSOR_V4l2_S_CTRL: {
+			struct v4l2_control v4l2_ctrl;
+			CDBG("subdev call\n");
+			if (copy_from_user(&v4l2_ctrl,
+				(void *)argp,
+				sizeof(struct v4l2_control))) {
+				CDBG("copy fail\n");
+				return -EFAULT;
+			}
+			CDBG("subdev call ok\n");
+			rc = v4l2_subdev_call(p_mctl->sensor_sdev,
+				core, s_ctrl, &v4l2_ctrl);
+			break;
+	}
+
+	case MSM_CAM_IOCTL_SENSOR_V4l2_QUERY_CTRL: {
+			struct v4l2_queryctrl v4l2_qctrl;
+			CDBG("query called\n");
+			if (copy_from_user(&v4l2_qctrl,
+				(void *)argp,
+				sizeof(struct v4l2_queryctrl))) {
+				CDBG("copy fail\n");
+				rc = -EFAULT;
+				break;
+			}
+			rc = v4l2_subdev_call(p_mctl->sensor_sdev,
+				core, queryctrl, &v4l2_qctrl);
+			if (rc < 0) {
+				rc = -EFAULT;
+				break;
+			}
+			if (copy_to_user((void *)argp,
+					 &v4l2_qctrl,
+					 sizeof(struct v4l2_queryctrl))) {
+				rc = -EFAULT;
+			}
+			break;
+	}
+
 	case MSM_CAM_IOCTL_ACTUATOR_IO_CFG: {
 		struct msm_actuator_cfg_data act_data;
 		if (p_mctl->sync.actctrl.a_config) {
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index 2f693ea..16bec18 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -127,7 +127,7 @@
 	rot_flag = msm_io_r(vpe_ctrl->vpebase +
 						VPE_OP_MODE_OFFSET) & 0xE00;
 	if (pinfo != NULL) {
-		pr_err("%s: Crop info in2_w = %d, in2_h = %d "
+		CDBG("%s: Crop info in2_w = %d, in2_h = %d "
 			"out2_w = %d out2_h = %d\n",
 			__func__, pcrop->src_w, pcrop->src_h,
 			pcrop->dst_w, pcrop->dst_h);
diff --git a/drivers/media/video/msm/sensors/Makefile b/drivers/media/video/msm/sensors/Makefile
index 3e42126..7b22592 100644
--- a/drivers/media/video/msm/sensors/Makefile
+++ b/drivers/media/video/msm/sensors/Makefile
@@ -4,4 +4,5 @@
 EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
 obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
 obj-$(CONFIG_IMX074) += imx074_v4l2.o
+obj-$(CONFIG_MT9M114) += mt9m114_v4l2.o
 obj-$(CONFIG_OV2720) += ov2720.o
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 7eb3160..e67f9cd 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -578,6 +578,74 @@
 	return 0;
 }
 
+int32_t msm_sensor_v4l2_s_ctrl(struct v4l2_subdev *sd,
+	struct v4l2_control *ctrl)
+{
+	int rc = -1, i = 0;
+	struct msm_sensor_ctrl_t *s_ctrl =
+		(struct msm_sensor_ctrl_t *) sd->dev_priv;
+	struct msm_sensor_v4l2_ctrl_info_t *v4l2_ctrl =
+		s_ctrl->msm_sensor_v4l2_ctrl_info;
+
+	CDBG("%s\n", __func__);
+	CDBG("%d\n", ctrl->id);
+	if (v4l2_ctrl == NULL)
+		return rc;
+
+	for (i = 0; i < s_ctrl->num_v4l2_ctrl; i++) {
+		if (v4l2_ctrl[i].ctrl_id == ctrl->id) {
+			if (v4l2_ctrl[i].s_v4l2_ctrl != NULL) {
+				rc = v4l2_ctrl[i].s_v4l2_ctrl(
+					s_ctrl,
+					&s_ctrl->msm_sensor_v4l2_ctrl_info[i],
+					ctrl->value);
+			}
+			break;
+		}
+	}
+
+	return rc;
+}
+
+int32_t msm_sensor_v4l2_query_ctrl(
+	struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl)
+{
+	int rc = -1, i = 0;
+	struct msm_sensor_ctrl_t *s_ctrl =
+		(struct msm_sensor_ctrl_t *) sd->dev_priv;
+
+	CDBG("%s\n", __func__);
+	CDBG("%s id: %d\n", __func__, qctrl->id);
+
+	if (s_ctrl->msm_sensor_v4l2_ctrl_info == NULL)
+		return rc;
+
+	for (i = 0; i < s_ctrl->num_v4l2_ctrl; i++) {
+		if (s_ctrl->msm_sensor_v4l2_ctrl_info[i].ctrl_id == qctrl->id) {
+			qctrl->minimum =
+				s_ctrl->msm_sensor_v4l2_ctrl_info[i].min;
+			qctrl->maximum =
+				s_ctrl->msm_sensor_v4l2_ctrl_info[i].max;
+			qctrl->flags = 1;
+			rc = 0;
+			break;
+		}
+	}
+
+	return rc;
+}
+
+int msm_sensor_s_ctrl_by_enum(struct msm_sensor_ctrl_t *s_ctrl,
+		struct msm_sensor_v4l2_ctrl_info_t *ctrl_info, int value)
+{
+	int rc = 0;
+	CDBG("%s enter\n", __func__);
+	rc = msm_sensor_write_enum_conf_array(
+		s_ctrl->sensor_i2c_client,
+		ctrl_info->enum_cfg_settings, value);
+	return rc;
+}
+
 static int msm_sensor_debugfs_stream_s(void *data, u64 val)
 {
 	struct msm_sensor_ctrl_t *s_ctrl = (struct msm_sensor_ctrl_t *) data;
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/video/msm/sensors/msm_sensor.h
index e4dc34f..f1a15b2 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.h
+++ b/drivers/media/video/msm/sensors/msm_sensor.h
@@ -93,6 +93,17 @@
 };
 
 struct msm_sensor_ctrl_t;
+
+struct msm_sensor_v4l2_ctrl_info_t {
+	uint32_t ctrl_id;
+	int16_t min;
+	int16_t max;
+	int16_t step;
+	struct msm_camera_i2c_enum_conf_array *enum_cfg_settings;
+	int (*s_v4l2_ctrl) (struct msm_sensor_ctrl_t *,
+		struct msm_sensor_v4l2_ctrl_info_t *, int);
+};
+
 struct msm_sensor_fn_t {
 	void (*sensor_start_stream) (struct msm_sensor_ctrl_t *);
 	void (*sensor_stop_stream) (struct msm_sensor_ctrl_t *);
@@ -137,6 +148,8 @@
 	struct msm_sensor_id_info_t *sensor_id_info;
 	struct msm_sensor_exp_gain_info_t *sensor_exp_gain_info;
 	struct msm_sensor_reg_t *msm_sensor_reg;
+	struct msm_sensor_v4l2_ctrl_info_t *msm_sensor_v4l2_ctrl_info;
+	uint16_t num_v4l2_ctrl;
 
 	uint16_t curr_line_length_pclk;
 	uint16_t curr_frame_length_lines;
@@ -192,6 +205,18 @@
 	const struct msm_camera_sensor_info *info,
 	struct v4l2_subdev *sdev, struct msm_sensor_ctrl *s);
 
+int32_t msm_sensor_v4l2_s_ctrl(struct v4l2_subdev *sd,
+	struct v4l2_control *ctrl);
+
+int32_t msm_sensor_v4l2_query_ctrl(
+	struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl);
+
+int msm_sensor_s_ctrl_by_index(struct msm_sensor_ctrl_t *s_ctrl,
+	struct msm_sensor_v4l2_ctrl_info_t *ctrl_info, int value);
+
+int msm_sensor_s_ctrl_by_enum(struct msm_sensor_ctrl_t *s_ctrl,
+		struct msm_sensor_v4l2_ctrl_info_t *ctrl_info, int value);
+
 int msm_sensor_v4l2_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
 			enum v4l2_mbus_pixelcode *code);
 
diff --git a/drivers/media/video/msm/sensors/mt9m114_v4l2.c b/drivers/media/video/msm/sensors/mt9m114_v4l2.c
new file mode 100644
index 0000000..fc45705
--- /dev/null
+++ b/drivers/media/video/msm/sensors/mt9m114_v4l2.c
@@ -0,0 +1,1340 @@
+/* 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 "msm_sensor.h"
+#define SENSOR_NAME "mt9m114"
+#define PLATFORM_DRIVER_NAME "msm_camera_mt9m114"
+#define mt9m114_obj mt9m114_##obj
+
+/* Sysctl registers */
+#define MT9M114_COMMAND_REGISTER                0x0080
+#define MT9M114_COMMAND_REGISTER_APPLY_PATCH    (1 << 0)
+#define MT9M114_COMMAND_REGISTER_SET_STATE      (1 << 1)
+#define MT9M114_COMMAND_REGISTER_REFRESH        (1 << 2)
+#define MT9M114_COMMAND_REGISTER_WAIT_FOR_EVENT (1 << 3)
+#define MT9M114_COMMAND_REGISTER_OK             (1 << 15)
+
+DEFINE_MUTEX(mt9m114_mut);
+static struct msm_sensor_ctrl_t mt9m114_s_ctrl;
+
+static struct msm_camera_i2c_reg_conf mt9m114_720p_settings[] = {
+	{0xdc00, 0x50, MSM_CAMERA_I2C_BYTE_DATA, MSM_CAMERA_I2C_CMD_WRITE},
+	{MT9M114_COMMAND_REGISTER, MT9M114_COMMAND_REGISTER_SET_STATE,
+		MSM_CAMERA_I2C_UNSET_WORD_MASK, MSM_CAMERA_I2C_CMD_POLL},
+	{MT9M114_COMMAND_REGISTER, (MT9M114_COMMAND_REGISTER_OK |
+		MT9M114_COMMAND_REGISTER_SET_STATE), MSM_CAMERA_I2C_WORD_DATA,
+		MSM_CAMERA_I2C_CMD_WRITE},
+	{MT9M114_COMMAND_REGISTER, MT9M114_COMMAND_REGISTER_SET_STATE,
+		MSM_CAMERA_I2C_UNSET_WORD_MASK, MSM_CAMERA_I2C_CMD_POLL},
+	{0xDC01, 0x52, MSM_CAMERA_I2C_BYTE_DATA, MSM_CAMERA_I2C_CMD_POLL},
+
+	{0x098E, 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{0xC800, 0x007C,},/*y_addr_start = 124*/
+	{0xC802, 0x0004,},/*x_addr_start = 4*/
+	{0xC804, 0x0353,},/*y_addr_end = 851*/
+	{0xC806, 0x050B,},/*x_addr_end = 1291*/
+	{0xC808, 0x02DC,},/*pixclk = 48000000*/
+	{0xC80A, 0x6C00,},/*pixclk = 48000000*/
+	{0xC80C, 0x0001,},/*row_speed = 1*/
+	{0xC80E, 0x00DB,},/*fine_integ_time_min = 219*/
+	{0xC810, 0x05BD,},/*fine_integ_time_max = 1469*/
+	{0xC812, 0x03E8,},/*frame_length_lines = 1000*/
+	{0xC814, 0x0640,},/*line_length_pck = 1600*/
+	{0xC816, 0x0060,},/*fine_correction = 96*/
+	{0xC818, 0x02D3,},/*cpipe_last_row = 723*/
+	{0xC826, 0x0020,},/*reg_0_data = 32*/
+	{0xC834, 0x0000,},/*sensor_control_read_mode = 0*/
+	{0xC854, 0x0000,},/*crop_window_xoffset = 0*/
+	{0xC856, 0x0000,},/*crop_window_yoffset = 0*/
+	{0xC858, 0x0500,},/*crop_window_width = 1280*/
+	{0xC85A, 0x02D0,},/*crop_window_height = 720*/
+	{0xC85C, 0x03, MSM_CAMERA_I2C_BYTE_DATA},  /*crop_cropmode = 3*/
+	{0xC868, 0x0500,},/*output_width = 1280*/
+	{0xC86A, 0x02D0,},/*output_height = 720*/
+	{0xC878, 0x00, MSM_CAMERA_I2C_BYTE_DATA},  /*aet_aemode = 0*/
+	{0xC88C, 0x1E00,},/*aet_max_frame_rate = 7680*/
+	{0xC88E, 0x1E00,},/*aet_min_frame_rate = 7680*/
+	{0xC914, 0x0000,},/*stat_awb_window_xstart = 0*/
+	{0xC916, 0x0000,},/*stat_awb_window_ystart = 0*/
+	{0xC918, 0x04FF,},/*stat_awb_window_xend = 1279*/
+	{0xC91A, 0x02CF,},/*stat_awb_window_yend = 719*/
+	{0xC91C, 0x0000,},/*stat_ae_window_xstart = 0*/
+	{0xC91E, 0x0000,},/*stat_ae_window_ystart = 0*/
+	{0xC920, 0x00FF,},/*stat_ae_window_xend = 255*/
+	{0xC922, 0x008F,},/*stat_ae_window_yend = 143*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9m114_recommend_settings[] = {
+	{0x301A, 0x0200, MSM_CAMERA_I2C_SET_WORD_MASK},
+	{0x098E, 0, MSM_CAMERA_I2C_BYTE_DATA},
+	/*cam_sysctl_pll_enable = 1*/
+	{0xC97E, 0x01, MSM_CAMERA_I2C_BYTE_DATA},
+	/*cam_sysctl_pll_divider_m_n = 288*/
+	{0xC980, 0x0120,},
+	/*cam_sysctl_pll_divider_p = 1792*/
+	{0xC982, 0x0700,},
+	/*output_control = 32769*/
+	{0xC984, 0x8001,},
+	/*mipi_timing_t_hs_zero = 3840*/
+	{0xC988, 0x0F00,},
+	/*mipi_timing_t_hs_exit_hs_trail = 2823*/
+	{0xC98A, 0x0B07,},
+	/*mipi_timing_t_clk_post_clk_pre = 3329*/
+	{0xC98C, 0x0D01,},
+	/*mipi_timing_t_clk_trail_clk_zero = 1821*/
+	{0xC98E, 0x071D,},
+	/*mipi_timing_t_lpx = 6*/
+	{0xC990, 0x0006,},
+	/*mipi_timing_init_timing = 2572*/
+	{0xC992, 0x0A0C,},
+	{0xC800, 0x007C,},/*y_addr_start = 124*/
+	{0xC802, 0x0004,},/*x_addr_start = 4*/
+	{0xC804, 0x0353,},/*y_addr_end = 851*/
+	{0xC806, 0x050B,},/*x_addr_end = 1291*/
+	{0xC808, 0x02DC,},/*pixclk = 48000000*/
+	{0xC80A, 0x6C00,},/*pixclk = 48000000*/
+	{0xC80C, 0x0001,},/*row_speed = 1*/
+	{0xC80E, 0x00DB,},/*fine_integ_time_min = 219*/
+	{0xC810, 0x05BD,},/*fine_integ_time_max = 1469*/
+	{0xC812, 0x03E8,},/*frame_length_lines = 1000*/
+	{0xC814, 0x0640,},/*line_length_pck = 1600*/
+	{0xC816, 0x0060,},/*fine_correction = 96*/
+	{0xC818, 0x02D3,},/*cpipe_last_row = 723*/
+	{0xC826, 0x0020,},/*reg_0_data = 32*/
+	{0xC834, 0x0000,},/*sensor_control_read_mode = 0*/
+	{0xC854, 0x0000,},/*crop_window_xoffset = 0*/
+	{0xC856, 0x0000,},/*crop_window_yoffset = 0*/
+	{0xC858, 0x0500,},/*crop_window_width = 1280*/
+	{0xC85A, 0x02D0,},/*crop_window_height = 720*/
+	{0xC85C, 0x03, MSM_CAMERA_I2C_BYTE_DATA},  /*crop_cropmode = 3*/
+	{0xC868, 0x0500,},/*output_width = 1280*/
+	{0xC86A, 0x02D0,},/*output_height = 720*/
+	{0xC878, 0x00, MSM_CAMERA_I2C_BYTE_DATA},  /*aet_aemode = 0*/
+	{0xC88C, 0x1E00,},/*aet_max_frame_rate = 7680*/
+	{0xC88E, 0x1E00,},/*aet_min_frame_rate = 7680*/
+	{0xC914, 0x0000,},/*stat_awb_window_xstart = 0*/
+	{0xC916, 0x0000,},/*stat_awb_window_ystart = 0*/
+	{0xC918, 0x04FF,},/*stat_awb_window_xend = 1279*/
+	{0xC91A, 0x02CF,},/*stat_awb_window_yend = 719*/
+	{0xC91C, 0x0000,},/*stat_ae_window_xstart = 0*/
+	{0xC91E, 0x0000,},/*stat_ae_window_ystart = 0*/
+	{0xC920, 0x00FF,},/*stat_ae_window_xend = 255*/
+	{0xC922, 0x008F,},/*stat_ae_window_yend = 143*/
+
+	/*Sensor optimization*/
+	{0x316A, 0x8270,},
+	{0x316C, 0x8270,},
+	{0x3ED0, 0x2305,},
+	{0x3ED2, 0x77CF,},
+	{0x316E, 0x8202,},
+	{0x3180, 0x87FF,},
+	{0x30D4, 0x6080,},
+	{0xA802, 0x0008,},/*AE_TRACK_MODE*/
+	{0x3E14, 0xFF39,},
+	{0x0982, 0x0001,},/*ACCESS_CTL_STAT*/
+	{0x098A, 0x5000,},/*PHYSICAL_ADDRESS_ACCESS*/
+	{0xD000, 0x70CF,},
+	{0xD002, 0xFFFF,},
+	{0xD004, 0xC5D4,},
+	{0xD006, 0x903A,},
+	{0xD008, 0x2144,},
+	{0xD00A, 0x0C00,},
+	{0xD00C, 0x2186,},
+	{0xD00E, 0x0FF3,},
+	{0xD010, 0xB844,},
+	{0xD012, 0xB948,},
+	{0xD014, 0xE082,},
+	{0xD016, 0x20CC,},
+	{0xD018, 0x80E2,},
+	{0xD01A, 0x21CC,},
+	{0xD01C, 0x80A2,},
+	{0xD01E, 0x21CC,},
+	{0xD020, 0x80E2,},
+	{0xD022, 0xF404,},
+	{0xD024, 0xD801,},
+	{0xD026, 0xF003,},
+	{0xD028, 0xD800,},
+	{0xD02A, 0x7EE0,},
+	{0xD02C, 0xC0F1,},
+	{0xD02E, 0x08BA,},
+	{0xD030, 0x0600,},
+	{0xD032, 0xC1A1,},
+	{0xD034, 0x76CF,},
+	{0xD036, 0xFFFF,},
+	{0xD038, 0xC130,},
+	{0xD03A, 0x6E04,},
+	{0xD03C, 0xC040,},
+	{0xD03E, 0x71CF,},
+	{0xD040, 0xFFFF,},
+	{0xD042, 0xC790,},
+	{0xD044, 0x8103,},
+	{0xD046, 0x77CF,},
+	{0xD048, 0xFFFF,},
+	{0xD04A, 0xC7C0,},
+	{0xD04C, 0xE001,},
+	{0xD04E, 0xA103,},
+	{0xD050, 0xD800,},
+	{0xD052, 0x0C6A,},
+	{0xD054, 0x04E0,},
+	{0xD056, 0xB89E,},
+	{0xD058, 0x7508,},
+	{0xD05A, 0x8E1C,},
+	{0xD05C, 0x0809,},
+	{0xD05E, 0x0191,},
+	{0xD060, 0xD801,},
+	{0xD062, 0xAE1D,},
+	{0xD064, 0xE580,},
+	{0xD066, 0x20CA,},
+	{0xD068, 0x0022,},
+	{0xD06A, 0x20CF,},
+	{0xD06C, 0x0522,},
+	{0xD06E, 0x0C5C,},
+	{0xD070, 0x04E2,},
+	{0xD072, 0x21CA,},
+	{0xD074, 0x0062,},
+	{0xD076, 0xE580,},
+	{0xD078, 0xD901,},
+	{0xD07A, 0x79C0,},
+	{0xD07C, 0xD800,},
+	{0xD07E, 0x0BE6,},
+	{0xD080, 0x04E0,},
+	{0xD082, 0xB89E,},
+	{0xD084, 0x70CF,},
+	{0xD086, 0xFFFF,},
+	{0xD088, 0xC8D4,},
+	{0xD08A, 0x9002,},
+	{0xD08C, 0x0857,},
+	{0xD08E, 0x025E,},
+	{0xD090, 0xFFDC,},
+	{0xD092, 0xE080,},
+	{0xD094, 0x25CC,},
+	{0xD096, 0x9022,},
+	{0xD098, 0xF225,},
+	{0xD09A, 0x1700,},
+	{0xD09C, 0x108A,},
+	{0xD09E, 0x73CF,},
+	{0xD0A0, 0xFF00,},
+	{0xD0A2, 0x3174,},
+	{0xD0A4, 0x9307,},
+	{0xD0A6, 0x2A04,},
+	{0xD0A8, 0x103E,},
+	{0xD0AA, 0x9328,},
+	{0xD0AC, 0x2942,},
+	{0xD0AE, 0x7140,},
+	{0xD0B0, 0x2A04,},
+	{0xD0B2, 0x107E,},
+	{0xD0B4, 0x9349,},
+	{0xD0B6, 0x2942,},
+	{0xD0B8, 0x7141,},
+	{0xD0BA, 0x2A04,},
+	{0xD0BC, 0x10BE,},
+	{0xD0BE, 0x934A,},
+	{0xD0C0, 0x2942,},
+	{0xD0C2, 0x714B,},
+	{0xD0C4, 0x2A04,},
+	{0xD0C6, 0x10BE,},
+	{0xD0C8, 0x130C,},
+	{0xD0CA, 0x010A,},
+	{0xD0CC, 0x2942,},
+	{0xD0CE, 0x7142,},
+	{0xD0D0, 0x2250,},
+	{0xD0D2, 0x13CA,},
+	{0xD0D4, 0x1B0C,},
+	{0xD0D6, 0x0284,},
+	{0xD0D8, 0xB307,},
+	{0xD0DA, 0xB328,},
+	{0xD0DC, 0x1B12,},
+	{0xD0DE, 0x02C4,},
+	{0xD0E0, 0xB34A,},
+	{0xD0E2, 0xED88,},
+	{0xD0E4, 0x71CF,},
+	{0xD0E6, 0xFF00,},
+	{0xD0E8, 0x3174,},
+	{0xD0EA, 0x9106,},
+	{0xD0EC, 0xB88F,},
+	{0xD0EE, 0xB106,},
+	{0xD0F0, 0x210A,},
+	{0xD0F2, 0x8340,},
+	{0xD0F4, 0xC000,},
+	{0xD0F6, 0x21CA,},
+	{0xD0F8, 0x0062,},
+	{0xD0FA, 0x20F0,},
+	{0xD0FC, 0x0040,},
+	{0xD0FE, 0x0B02,},
+	{0xD100, 0x0320,},
+	{0xD102, 0xD901,},
+	{0xD104, 0x07F1,},
+	{0xD106, 0x05E0,},
+	{0xD108, 0xC0A1,},
+	{0xD10A, 0x78E0,},
+	{0xD10C, 0xC0F1,},
+	{0xD10E, 0x71CF,},
+	{0xD110, 0xFFFF,},
+	{0xD112, 0xC7C0,},
+	{0xD114, 0xD840,},
+	{0xD116, 0xA900,},
+	{0xD118, 0x71CF,},
+	{0xD11A, 0xFFFF,},
+	{0xD11C, 0xD02C,},
+	{0xD11E, 0xD81E,},
+	{0xD120, 0x0A5A,},
+	{0xD122, 0x04E0,},
+	{0xD124, 0xDA00,},
+	{0xD126, 0xD800,},
+	{0xD128, 0xC0D1,},
+	{0xD12A, 0x7EE0,},
+	{0x098E, 0x0000,},
+
+	{0x0982, 0x0001,},
+	{0x098A, 0x5C10,},
+	{0xDC10, 0xC0F1,},
+	{0xDC12, 0x0CDA,},
+	{0xDC14, 0x0580,},
+	{0xDC16, 0x76CF,},
+	{0xDC18, 0xFF00,},
+	{0xDC1A, 0x2184,},
+	{0xDC1C, 0x9624,},
+	{0xDC1E, 0x218C,},
+	{0xDC20, 0x8FC3,},
+	{0xDC22, 0x75CF,},
+	{0xDC24, 0xFFFF,},
+	{0xDC26, 0xE058,},
+	{0xDC28, 0xF686,},
+	{0xDC2A, 0x1550,},
+	{0xDC2C, 0x1080,},
+	{0xDC2E, 0xE001,},
+	{0xDC30, 0x1D50,},
+	{0xDC32, 0x1002,},
+	{0xDC34, 0x1552,},
+	{0xDC36, 0x1100,},
+	{0xDC38, 0x6038,},
+	{0xDC3A, 0x1D52,},
+	{0xDC3C, 0x1004,},
+	{0xDC3E, 0x1540,},
+	{0xDC40, 0x1080,},
+	{0xDC42, 0x081B,},
+	{0xDC44, 0x00D1,},
+	{0xDC46, 0x8512,},
+	{0xDC48, 0x1000,},
+	{0xDC4A, 0x00C0,},
+	{0xDC4C, 0x7822,},
+	{0xDC4E, 0x2089,},
+	{0xDC50, 0x0FC1,},
+	{0xDC52, 0x2008,},
+	{0xDC54, 0x0F81,},
+	{0xDC56, 0xFFFF,},
+	{0xDC58, 0xFF80,},
+	{0xDC5A, 0x8512,},
+	{0xDC5C, 0x1801,},
+	{0xDC5E, 0x0052,},
+	{0xDC60, 0xA512,},
+	{0xDC62, 0x1544,},
+	{0xDC64, 0x1080,},
+	{0xDC66, 0xB861,},
+	{0xDC68, 0x262F,},
+	{0xDC6A, 0xF007,},
+	{0xDC6C, 0x1D44,},
+	{0xDC6E, 0x1002,},
+	{0xDC70, 0x20CA,},
+	{0xDC72, 0x0021,},
+	{0xDC74, 0x20CF,},
+	{0xDC76, 0x04E1,},
+	{0xDC78, 0x0850,},
+	{0xDC7A, 0x04A1,},
+	{0xDC7C, 0x21CA,},
+	{0xDC7E, 0x0021,},
+	{0xDC80, 0x1542,},
+	{0xDC82, 0x1140,},
+	{0xDC84, 0x8D2C,},
+	{0xDC86, 0x6038,},
+	{0xDC88, 0x1D42,},
+	{0xDC8A, 0x1004,},
+	{0xDC8C, 0x1542,},
+	{0xDC8E, 0x1140,},
+	{0xDC90, 0xB601,},
+	{0xDC92, 0x046D,},
+	{0xDC94, 0x0580,},
+	{0xDC96, 0x78E0,},
+	{0xDC98, 0xD800,},
+	{0xDC9A, 0xB893,},
+	{0xDC9C, 0x002D,},
+	{0xDC9E, 0x04A0,},
+	{0xDCA0, 0xD900,},
+	{0xDCA2, 0x78E0,},
+	{0xDCA4, 0x72CF,},
+	{0xDCA6, 0xFFFF,},
+	{0xDCA8, 0xE058,},
+	{0xDCAA, 0x2240,},
+	{0xDCAC, 0x0340,},
+	{0xDCAE, 0xA212,},
+	{0xDCB0, 0x208A,},
+	{0xDCB2, 0x0FFF,},
+	{0xDCB4, 0x1A42,},
+	{0xDCB6, 0x0004,},
+	{0xDCB8, 0xD830,},
+	{0xDCBA, 0x1A44,},
+	{0xDCBC, 0x0002,},
+	{0xDCBE, 0xD800,},
+	{0xDCC0, 0x1A50,},
+	{0xDCC2, 0x0002,},
+	{0xDCC4, 0x1A52,},
+	{0xDCC6, 0x0004,},
+	{0xDCC8, 0x1242,},
+	{0xDCCA, 0x0140,},
+	{0xDCCC, 0x8A2C,},
+	{0xDCCE, 0x6038,},
+	{0xDCD0, 0x1A42,},
+	{0xDCD2, 0x0004,},
+	{0xDCD4, 0x1242,},
+	{0xDCD6, 0x0141,},
+	{0xDCD8, 0x70CF,},
+	{0xDCDA, 0xFF00,},
+	{0xDCDC, 0x2184,},
+	{0xDCDE, 0xB021,},
+	{0xDCE0, 0xD800,},
+	{0xDCE2, 0xB893,},
+	{0xDCE4, 0x07E5,},
+	{0xDCE6, 0x0460,},
+	{0xDCE8, 0xD901,},
+	{0xDCEA, 0x78E0,},
+	{0xDCEC, 0xC0F1,},
+	{0xDCEE, 0x0BFA,},
+	{0xDCF0, 0x05A0,},
+	{0xDCF2, 0x216F,},
+	{0xDCF4, 0x0043,},
+	{0xDCF6, 0xC1A4,},
+	{0xDCF8, 0x220A,},
+	{0xDCFA, 0x1F80,},
+	{0xDCFC, 0xFFFF,},
+	{0xDCFE, 0xE058,},
+	{0xDD00, 0x2240,},
+	{0xDD02, 0x134F,},
+	{0xDD04, 0x1A48,},
+	{0xDD06, 0x13C0,},
+	{0xDD08, 0x1248,},
+	{0xDD0A, 0x1002,},
+	{0xDD0C, 0x70CF,},
+	{0xDD0E, 0x7FFF,},
+	{0xDD10, 0xFFFF,},
+	{0xDD12, 0xE230,},
+	{0xDD14, 0xC240,},
+	{0xDD16, 0xDA00,},
+	{0xDD18, 0xF00C,},
+	{0xDD1A, 0x1248,},
+	{0xDD1C, 0x1003,},
+	{0xDD1E, 0x1301,},
+	{0xDD20, 0x04CB,},
+	{0xDD22, 0x7261,},
+	{0xDD24, 0x2108,},
+	{0xDD26, 0x0081,},
+	{0xDD28, 0x2009,},
+	{0xDD2A, 0x0080,},
+	{0xDD2C, 0x1A48,},
+	{0xDD2E, 0x10C0,},
+	{0xDD30, 0x1248,},
+	{0xDD32, 0x100B,},
+	{0xDD34, 0xC300,},
+	{0xDD36, 0x0BE7,},
+	{0xDD38, 0x90C4,},
+	{0xDD3A, 0x2102,},
+	{0xDD3C, 0x0003,},
+	{0xDD3E, 0x238C,},
+	{0xDD40, 0x8FC3,},
+	{0xDD42, 0xF6C7,},
+	{0xDD44, 0xDAFF,},
+	{0xDD46, 0x1A05,},
+	{0xDD48, 0x1082,},
+	{0xDD4A, 0xC241,},
+	{0xDD4C, 0xF005,},
+	{0xDD4E, 0x7A6F,},
+	{0xDD50, 0xC241,},
+	{0xDD52, 0x1A05,},
+	{0xDD54, 0x10C2,},
+	{0xDD56, 0x2000,},
+	{0xDD58, 0x8040,},
+	{0xDD5A, 0xDA00,},
+	{0xDD5C, 0x20C0,},
+	{0xDD5E, 0x0064,},
+	{0xDD60, 0x781C,},
+	{0xDD62, 0xC042,},
+	{0xDD64, 0x1C0E,},
+	{0xDD66, 0x3082,},
+	{0xDD68, 0x1A48,},
+	{0xDD6A, 0x13C0,},
+	{0xDD6C, 0x7548,},
+	{0xDD6E, 0x7348,},
+	{0xDD70, 0x7148,},
+	{0xDD72, 0x7648,},
+	{0xDD74, 0xF002,},
+	{0xDD76, 0x7608,},
+	{0xDD78, 0x1248,},
+	{0xDD7A, 0x1000,},
+	{0xDD7C, 0x1400,},
+	{0xDD7E, 0x300B,},
+	{0xDD80, 0x084D,},
+	{0xDD82, 0x02C5,},
+	{0xDD84, 0x1248,},
+	{0xDD86, 0x1000,},
+	{0xDD88, 0xE101,},
+	{0xDD8A, 0x1001,},
+	{0xDD8C, 0x04CB,},
+	{0xDD8E, 0x1A48,},
+	{0xDD90, 0x1000,},
+	{0xDD92, 0x7361,},
+	{0xDD94, 0x1408,},
+	{0xDD96, 0x300B,},
+	{0xDD98, 0x2302,},
+	{0xDD9A, 0x02C0,},
+	{0xDD9C, 0x780D,},
+	{0xDD9E, 0x2607,},
+	{0xDDA0, 0x903E,},
+	{0xDDA2, 0x07D6,},
+	{0xDDA4, 0xFFE3,},
+	{0xDDA6, 0x792F,},
+	{0xDDA8, 0x09CF,},
+	{0xDDAA, 0x8152,},
+	{0xDDAC, 0x1248,},
+	{0xDDAE, 0x100E,},
+	{0xDDB0, 0x2400,},
+	{0xDDB2, 0x334B,},
+	{0xDDB4, 0xE501,},
+	{0xDDB6, 0x7EE2,},
+	{0xDDB8, 0x0DBF,},
+	{0xDDBA, 0x90F2,},
+	{0xDDBC, 0x1B0C,},
+	{0xDDBE, 0x1382,},
+	{0xDDC0, 0xC123,},
+	{0xDDC2, 0x140E,},
+	{0xDDC4, 0x3080,},
+	{0xDDC6, 0x7822,},
+	{0xDDC8, 0x1A07,},
+	{0xDDCA, 0x1002,},
+	{0xDDCC, 0x124C,},
+	{0xDDCE, 0x1000,},
+	{0xDDD0, 0x120B,},
+	{0xDDD2, 0x1081,},
+	{0xDDD4, 0x1207,},
+	{0xDDD6, 0x1083,},
+	{0xDDD8, 0x2142,},
+	{0xDDDA, 0x004B,},
+	{0xDDDC, 0x781B,},
+	{0xDDDE, 0x0B21,},
+	{0xDDE0, 0x02E2,},
+	{0xDDE2, 0x1A4C,},
+	{0xDDE4, 0x1000,},
+	{0xDDE6, 0xE101,},
+	{0xDDE8, 0x0915,},
+	{0xDDEA, 0x00C2,},
+	{0xDDEC, 0xC101,},
+	{0xDDEE, 0x1204,},
+	{0xDDF0, 0x1083,},
+	{0xDDF2, 0x090D,},
+	{0xDDF4, 0x00C2,},
+	{0xDDF6, 0xE001,},
+	{0xDDF8, 0x1A4C,},
+	{0xDDFA, 0x1000,},
+	{0xDDFC, 0x1A06,},
+	{0xDDFE, 0x1002,},
+	{0xDE00, 0x234A,},
+	{0xDE02, 0x1000,},
+	{0xDE04, 0x7169,},
+	{0xDE06, 0xF008,},
+	{0xDE08, 0x2053,},
+	{0xDE0A, 0x0003,},
+	{0xDE0C, 0x6179,},
+	{0xDE0E, 0x781C,},
+	{0xDE10, 0x2340,},
+	{0xDE12, 0x104B,},
+	{0xDE14, 0x1203,},
+	{0xDE16, 0x1083,},
+	{0xDE18, 0x0BF1,},
+	{0xDE1A, 0x90C2,},
+	{0xDE1C, 0x1202,},
+	{0xDE1E, 0x1080,},
+	{0xDE20, 0x091D,},
+	{0xDE22, 0x0004,},
+	{0xDE24, 0x70CF,},
+	{0xDE26, 0xFFFF,},
+	{0xDE28, 0xC644,},
+	{0xDE2A, 0x881B,},
+	{0xDE2C, 0xE0B2,},
+	{0xDE2E, 0xD83C,},
+	{0xDE30, 0x20CA,},
+	{0xDE32, 0x0CA2,},
+	{0xDE34, 0x1A01,},
+	{0xDE36, 0x1002,},
+	{0xDE38, 0x1A4C,},
+	{0xDE3A, 0x1080,},
+	{0xDE3C, 0x02B9,},
+	{0xDE3E, 0x05A0,},
+	{0xDE40, 0xC0A4,},
+	{0xDE42, 0x78E0,},
+	{0xDE44, 0xC0F1,},
+	{0xDE46, 0xFF95,},
+	{0xDE48, 0xD800,},
+	{0xDE4A, 0x71CF,},
+	{0xDE4C, 0xFF00,},
+	{0xDE4E, 0x1FE0,},
+	{0xDE50, 0x19D0,},
+	{0xDE52, 0x001C,},
+	{0xDE54, 0x19D1,},
+	{0xDE56, 0x001C,},
+	{0xDE58, 0x70CF,},
+	{0xDE5A, 0xFFFF,},
+	{0xDE5C, 0xE058,},
+	{0xDE5E, 0x901F,},
+	{0xDE60, 0xB861,},
+	{0xDE62, 0x19D2,},
+	{0xDE64, 0x001C,},
+	{0xDE66, 0xC0D1,},
+	{0xDE68, 0x7EE0,},
+	{0xDE6A, 0x78E0,},
+	{0xDE6C, 0xC0F1,},
+	{0xDE6E, 0x0A7A,},
+	{0xDE70, 0x0580,},
+	{0xDE72, 0x70CF,},
+	{0xDE74, 0xFFFF,},
+	{0xDE76, 0xC5D4,},
+	{0xDE78, 0x9041,},
+	{0xDE7A, 0x9023,},
+	{0xDE7C, 0x75CF,},
+	{0xDE7E, 0xFFFF,},
+	{0xDE80, 0xE058,},
+	{0xDE82, 0x7942,},
+	{0xDE84, 0xB967,},
+	{0xDE86, 0x7F30,},
+	{0xDE88, 0xB53F,},
+	{0xDE8A, 0x71CF,},
+	{0xDE8C, 0xFFFF,},
+	{0xDE8E, 0xC84C,},
+	{0xDE90, 0x91D3,},
+	{0xDE92, 0x108B,},
+	{0xDE94, 0x0081,},
+	{0xDE96, 0x2615,},
+	{0xDE98, 0x1380,},
+	{0xDE9A, 0x090F,},
+	{0xDE9C, 0x0C91,},
+	{0xDE9E, 0x0A8E,},
+	{0xDEA0, 0x05A0,},
+	{0xDEA2, 0xD906,},
+	{0xDEA4, 0x7E10,},
+	{0xDEA6, 0x2615,},
+	{0xDEA8, 0x1380,},
+	{0xDEAA, 0x0A82,},
+	{0xDEAC, 0x05A0,},
+	{0xDEAE, 0xD960,},
+	{0xDEB0, 0x790F,},
+	{0xDEB2, 0x090D,},
+	{0xDEB4, 0x0133,},
+	{0xDEB6, 0xAD0C,},
+	{0xDEB8, 0xD904,},
+	{0xDEBA, 0xAD2C,},
+	{0xDEBC, 0x79EC,},
+	{0xDEBE, 0x2941,},
+	{0xDEC0, 0x7402,},
+	{0xDEC2, 0x71CF,},
+	{0xDEC4, 0xFF00,},
+	{0xDEC6, 0x2184,},
+	{0xDEC8, 0xB142,},
+	{0xDECA, 0x1906,},
+	{0xDECC, 0x0E44,},
+	{0xDECE, 0xFFDE,},
+	{0xDED0, 0x70C9,},
+	{0xDED2, 0x0A5A,},
+	{0xDED4, 0x05A0,},
+	{0xDED6, 0x8D2C,},
+	{0xDED8, 0xAD0B,},
+	{0xDEDA, 0xD800,},
+	{0xDEDC, 0xAD01,},
+	{0xDEDE, 0x0219,},
+	{0xDEE0, 0x05A0,},
+	{0xDEE2, 0xA513,},
+	{0xDEE4, 0xC0F1,},
+	{0xDEE6, 0x71CF,},
+	{0xDEE8, 0xFFFF,},
+	{0xDEEA, 0xC644,},
+	{0xDEEC, 0xA91B,},
+	{0xDEEE, 0xD902,},
+	{0xDEF0, 0x70CF,},
+	{0xDEF2, 0xFFFF,},
+	{0xDEF4, 0xC84C,},
+	{0xDEF6, 0x093E,},
+	{0xDEF8, 0x03A0,},
+	{0xDEFA, 0xA826,},
+	{0xDEFC, 0xFFDC,},
+	{0xDEFE, 0xF1B5,},
+	{0xDF00, 0xC0F1,},
+	{0xDF02, 0x09EA,},
+	{0xDF04, 0x0580,},
+	{0xDF06, 0x75CF,},
+	{0xDF08, 0xFFFF,},
+	{0xDF0A, 0xE058,},
+	{0xDF0C, 0x1540,},
+	{0xDF0E, 0x1080,},
+	{0xDF10, 0x08A7,},
+	{0xDF12, 0x0010,},
+	{0xDF14, 0x8D00,},
+	{0xDF16, 0x0813,},
+	{0xDF18, 0x009E,},
+	{0xDF1A, 0x1540,},
+	{0xDF1C, 0x1081,},
+	{0xDF1E, 0xE181,},
+	{0xDF20, 0x20CA,},
+	{0xDF22, 0x00A1,},
+	{0xDF24, 0xF24B,},
+	{0xDF26, 0x1540,},
+	{0xDF28, 0x1081,},
+	{0xDF2A, 0x090F,},
+	{0xDF2C, 0x0050,},
+	{0xDF2E, 0x1540,},
+	{0xDF30, 0x1081,},
+	{0xDF32, 0x0927,},
+	{0xDF34, 0x0091,},
+	{0xDF36, 0x1550,},
+	{0xDF38, 0x1081,},
+	{0xDF3A, 0xDE00,},
+	{0xDF3C, 0xAD2A,},
+	{0xDF3E, 0x1D50,},
+	{0xDF40, 0x1382,},
+	{0xDF42, 0x1552,},
+	{0xDF44, 0x1101,},
+	{0xDF46, 0x1D52,},
+	{0xDF48, 0x1384,},
+	{0xDF4A, 0xB524,},
+	{0xDF4C, 0x082D,},
+	{0xDF4E, 0x015F,},
+	{0xDF50, 0xFF55,},
+	{0xDF52, 0xD803,},
+	{0xDF54, 0xF033,},
+	{0xDF56, 0x1540,},
+	{0xDF58, 0x1081,},
+	{0xDF5A, 0x0967,},
+	{0xDF5C, 0x00D1,},
+	{0xDF5E, 0x1550,},
+	{0xDF60, 0x1081,},
+	{0xDF62, 0xDE00,},
+	{0xDF64, 0xAD2A,},
+	{0xDF66, 0x1D50,},
+	{0xDF68, 0x1382,},
+	{0xDF6A, 0x1552,},
+	{0xDF6C, 0x1101,},
+	{0xDF6E, 0x1D52,},
+	{0xDF70, 0x1384,},
+	{0xDF72, 0xB524,},
+	{0xDF74, 0x0811,},
+	{0xDF76, 0x019E,},
+	{0xDF78, 0xB8A0,},
+	{0xDF7A, 0xAD00,},
+	{0xDF7C, 0xFF47,},
+	{0xDF7E, 0x1D40,},
+	{0xDF80, 0x1382,},
+	{0xDF82, 0xF01F,},
+	{0xDF84, 0xFF5A,},
+	{0xDF86, 0x8D01,},
+	{0xDF88, 0x8D40,},
+	{0xDF8A, 0xE812,},
+	{0xDF8C, 0x71CF,},
+	{0xDF8E, 0xFFFF,},
+	{0xDF90, 0xC644,},
+	{0xDF92, 0x893B,},
+	{0xDF94, 0x7030,},
+	{0xDF96, 0x22D1,},
+	{0xDF98, 0x8062,},
+	{0xDF9A, 0xF20A,},
+	{0xDF9C, 0x0A0F,},
+	{0xDF9E, 0x009E,},
+	{0xDFA0, 0x71CF,},
+	{0xDFA2, 0xFFFF,},
+	{0xDFA4, 0xC84C,},
+	{0xDFA6, 0x893B,},
+	{0xDFA8, 0xE902,},
+	{0xDFAA, 0xFFCF,},
+	{0xDFAC, 0x8D00,},
+	{0xDFAE, 0xB8E7,},
+	{0xDFB0, 0x26CA,},
+	{0xDFB2, 0x1022,},
+	{0xDFB4, 0xF5E2,},
+	{0xDFB6, 0xFF3C,},
+	{0xDFB8, 0xD801,},
+	{0xDFBA, 0x1D40,},
+	{0xDFBC, 0x1002,},
+	{0xDFBE, 0x0141,},
+	{0xDFC0, 0x0580,},
+	{0xDFC2, 0x78E0,},
+	{0xDFC4, 0xC0F1,},
+	{0xDFC6, 0xC5E1,},
+	{0xDFC8, 0xFF34,},
+	{0xDFCA, 0xDD00,},
+	{0xDFCC, 0x70CF,},
+	{0xDFCE, 0xFFFF,},
+	{0xDFD0, 0xE090,},
+	{0xDFD2, 0xA8A8,},
+	{0xDFD4, 0xD800,},
+	{0xDFD6, 0xB893,},
+	{0xDFD8, 0x0C8A,},
+	{0xDFDA, 0x0460,},
+	{0xDFDC, 0xD901,},
+	{0xDFDE, 0x71CF,},
+	{0xDFE0, 0xFFFF,},
+	{0xDFE2, 0xDC10,},
+	{0xDFE4, 0xD813,},
+	{0xDFE6, 0x0B96,},
+	{0xDFE8, 0x0460,},
+	{0xDFEA, 0x72A9,},
+	{0xDFEC, 0x0119,},
+	{0xDFEE, 0x0580,},
+	{0xDFF0, 0xC0F1,},
+	{0xDFF2, 0x71CF,},
+	{0xDFF4, 0x0000,},
+	{0xDFF6, 0x5BAE,},
+	{0xDFF8, 0x7940,},
+	{0xDFFA, 0xFF9D,},
+	{0xDFFC, 0xF135,},
+	{0xDFFE, 0x78E0,},
+	{0xE000, 0xC0F1,},
+	{0xE002, 0x70CF,},
+	{0xE004, 0x0000,},
+	{0xE006, 0x5CBA,},
+	{0xE008, 0x7840,},
+	{0xE00A, 0x70CF,},
+	{0xE00C, 0xFFFF,},
+	{0xE00E, 0xE058,},
+	{0xE010, 0x8800,},
+	{0xE012, 0x0815,},
+	{0xE014, 0x001E,},
+	{0xE016, 0x70CF,},
+	{0xE018, 0xFFFF,},
+	{0xE01A, 0xC84C,},
+	{0xE01C, 0x881A,},
+	{0xE01E, 0xE080,},
+	{0xE020, 0x0EE0,},
+	{0xE022, 0xFFC1,},
+	{0xE024, 0xF121,},
+	{0xE026, 0x78E0,},
+	{0xE028, 0xC0F1,},
+	{0xE02A, 0xD900,},
+	{0xE02C, 0xF009,},
+	{0xE02E, 0x70CF,},
+	{0xE030, 0xFFFF,},
+	{0xE032, 0xE0AC,},
+	{0xE034, 0x7835,},
+	{0xE036, 0x8041,},
+	{0xE038, 0x8000,},
+	{0xE03A, 0xE102,},
+	{0xE03C, 0xA040,},
+	{0xE03E, 0x09F3,},
+	{0xE040, 0x8114,},
+	{0xE042, 0x71CF,},
+	{0xE044, 0xFFFF,},
+	{0xE046, 0xE058,},
+	{0xE048, 0x70CF,},
+	{0xE04A, 0xFFFF,},
+	{0xE04C, 0xC594,},
+	{0xE04E, 0xB030,},
+	{0xE050, 0xFFDD,},
+	{0xE052, 0xD800,},
+	{0xE054, 0xF109,},
+	{0xE056, 0x0000,},
+	{0xE058, 0x0300,},
+	{0xE05A, 0x0204,},
+	{0xE05C, 0x0700,},
+	{0xE05E, 0x0000,},
+	{0xE060, 0x0000,},
+	{0xE062, 0x0000,},
+	{0xE064, 0x0000,},
+	{0xE066, 0x0000,},
+	{0xE068, 0x0000,},
+	{0xE06A, 0x0000,},
+	{0xE06C, 0x0000,},
+	{0xE06E, 0x0000,},
+	{0xE070, 0x0000,},
+	{0xE072, 0x0000,},
+	{0xE074, 0x0000,},
+	{0xE076, 0x0000,},
+	{0xE078, 0x0000,},
+	{0xE07A, 0x0000,},
+	{0xE07C, 0x0000,},
+	{0xE07E, 0x0000,},
+	{0xE080, 0x0000,},
+	{0xE082, 0x0000,},
+	{0xE084, 0x0000,},
+	{0xE086, 0x0000,},
+	{0xE088, 0x0000,},
+	{0xE08A, 0x0000,},
+	{0xE08C, 0x0000,},
+	{0xE08E, 0x0000,},
+	{0xE090, 0x0000,},
+	{0xE092, 0x0000,},
+	{0xE094, 0x0000,},
+	{0xE096, 0x0000,},
+	{0xE098, 0x0000,},
+	{0xE09A, 0x0000,},
+	{0xE09C, 0x0000,},
+	{0xE09E, 0x0000,},
+	{0xE0A0, 0x0000,},
+	{0xE0A2, 0x0000,},
+	{0xE0A4, 0x0000,},
+	{0xE0A6, 0x0000,},
+	{0xE0A8, 0x0000,},
+	{0xE0AA, 0x0000,},
+	{0xE0AC, 0xFFFF,},
+	{0xE0AE, 0xCB68,},
+	{0xE0B0, 0xFFFF,},
+	{0xE0B2, 0xDFF0,},
+	{0xE0B4, 0xFFFF,},
+	{0xE0B6, 0xCB6C,},
+	{0xE0B8, 0xFFFF,},
+	{0xE0BA, 0xE000,},
+	{0x098E, 0x0000,},
+
+	/*MIPI setting for SOC1040*/
+	{0x3C5A, 0x0009,},
+	{0x3C44, 0x0080,},/*MIPI_CUSTOM_SHORT_PKT*/
+
+	/*[Tuning_settings]*/
+
+	/*[CCM]*/
+	{0xC892, 0x0267,},/*CAM_AWB_CCM_L_0*/
+	{0xC894, 0xFF1A,},/*CAM_AWB_CCM_L_1*/
+	{0xC896, 0xFFB3,},/*CAM_AWB_CCM_L_2*/
+	{0xC898, 0xFF80,},/*CAM_AWB_CCM_L_3*/
+	{0xC89A, 0x0166,},/*CAM_AWB_CCM_L_4*/
+	{0xC89C, 0x0003,},/*CAM_AWB_CCM_L_5*/
+	{0xC89E, 0xFF9A,},/*CAM_AWB_CCM_L_6*/
+	{0xC8A0, 0xFEB4,},/*CAM_AWB_CCM_L_7*/
+	{0xC8A2, 0x024D,},/*CAM_AWB_CCM_L_8*/
+	{0xC8A4, 0x01BF,},/*CAM_AWB_CCM_M_0*/
+	{0xC8A6, 0xFF01,},/*CAM_AWB_CCM_M_1*/
+	{0xC8A8, 0xFFF3,},/*CAM_AWB_CCM_M_2*/
+	{0xC8AA, 0xFF75,},/*CAM_AWB_CCM_M_3*/
+	{0xC8AC, 0x0198,},/*CAM_AWB_CCM_M_4*/
+	{0xC8AE, 0xFFFD,},/*CAM_AWB_CCM_M_5*/
+	{0xC8B0, 0xFF9A,},/*CAM_AWB_CCM_M_6*/
+	{0xC8B2, 0xFEE7,},/*CAM_AWB_CCM_M_7*/
+	{0xC8B4, 0x02A8,},/*CAM_AWB_CCM_M_8*/
+	{0xC8B6, 0x01D9,},/*CAM_AWB_CCM_R_0*/
+	{0xC8B8, 0xFF26,},/*CAM_AWB_CCM_R_1*/
+	{0xC8BA, 0xFFF3,},/*CAM_AWB_CCM_R_2*/
+	{0xC8BC, 0xFFB3,},/*CAM_AWB_CCM_R_3*/
+	{0xC8BE, 0x0132,},/*CAM_AWB_CCM_R_4*/
+	{0xC8C0, 0xFFE8,},/*CAM_AWB_CCM_R_5*/
+	{0xC8C2, 0xFFDA,},/*CAM_AWB_CCM_R_6*/
+	{0xC8C4, 0xFECD,},/*CAM_AWB_CCM_R_7*/
+	{0xC8C6, 0x02C2,},/*CAM_AWB_CCM_R_8*/
+	{0xC8C8, 0x0075,},/*CAM_AWB_CCM_L_RG_GAIN*/
+	{0xC8CA, 0x011C,},/*CAM_AWB_CCM_L_BG_GAIN*/
+	{0xC8CC, 0x009A,},/*CAM_AWB_CCM_M_RG_GAIN*/
+	{0xC8CE, 0x0105,},/*CAM_AWB_CCM_M_BG_GAIN*/
+	{0xC8D0, 0x00A4,},/*CAM_AWB_CCM_R_RG_GAIN*/
+	{0xC8D2, 0x00AC,},/*CAM_AWB_CCM_R_BG_GAIN*/
+	{0xC8D4, 0x0A8C,},/*CAM_AWB_CCM_L_CTEMP*/
+	{0xC8D6, 0x0F0A,},/*CAM_AWB_CCM_M_CTEMP*/
+	{0xC8D8, 0x1964,},/*CAM_AWB_CCM_R_CTEMP*/
+
+	/*[AWB]*/
+	{0xC914, 0x0000,},/*CAM_STAT_AWB_CLIP_WINDOW_XSTART*/
+	{0xC916, 0x0000,},/*CAM_STAT_AWB_CLIP_WINDOW_YSTART*/
+	{0xC918, 0x04FF,},/*CAM_STAT_AWB_CLIP_WINDOW_XEND*/
+	{0xC91A, 0x02CF,},/*CAM_STAT_AWB_CLIP_WINDOW_YEND*/
+	{0xC904, 0x0033,},/*CAM_AWB_AWB_XSHIFT_PRE_ADJ*/
+	{0xC906, 0x0040,},/*CAM_AWB_AWB_YSHIFT_PRE_ADJ*/
+	{0xC8F2, 0x03, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AWB_AWB_XSCALE*/
+	{0xC8F3, 0x02, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AWB_AWB_YSCALE*/
+	{0xC906, 0x003C,},/*CAM_AWB_AWB_YSHIFT_PRE_ADJ*/
+	{0xC8F4, 0x0000,},/*CAM_AWB_AWB_WEIGHTS_0*/
+	{0xC8F6, 0x0000,},/*CAM_AWB_AWB_WEIGHTS_1*/
+	{0xC8F8, 0x0000,},/*CAM_AWB_AWB_WEIGHTS_2*/
+	{0xC8FA, 0xE724,},/*CAM_AWB_AWB_WEIGHTS_3*/
+	{0xC8FC, 0x1583,},/*CAM_AWB_AWB_WEIGHTS_4*/
+	{0xC8FE, 0x2045,},/*CAM_AWB_AWB_WEIGHTS_5*/
+	{0xC900, 0x03FF,},/*CAM_AWB_AWB_WEIGHTS_6*/
+	{0xC902, 0x007C,},/*CAM_AWB_AWB_WEIGHTS_7*/
+	{0xC90C, 0x80, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AWB_K_R_L*/
+	{0xC90D, 0x80, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AWB_K_G_L*/
+	{0xC90E, 0x80, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AWB_K_B_L*/
+	{0xC90F, 0x88, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AWB_K_R_R*/
+	{0xC910, 0x80, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AWB_K_G_R*/
+	{0xC911, 0x80, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AWB_K_B_R*/
+
+	/*[Step7-CPIPE_Preference]*/
+	{0xC926, 0x0020,},/*CAM_LL_START_BRIGHTNESS*/
+	{0xC928, 0x009A,},/*CAM_LL_STOP_BRIGHTNESS*/
+	{0xC946, 0x0070,},/*CAM_LL_START_GAIN_METRIC*/
+	{0xC948, 0x00F3,},/*CAM_LL_STOP_GAIN_METRIC*/
+	{0xC952, 0x0020,},/*CAM_LL_START_TARGET_LUMA_BM*/
+	{0xC954, 0x009A,},/*CAM_LL_STOP_TARGET_LUMA_BM*/
+	{0xC92A, 0x80, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_SATURATION*/
+	{0xC92B, 0x4B, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_END_SATURATION*/
+	{0xC92C, 0x00, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_DESATURATION*/
+	{0xC92D, 0xFF, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_END_DESATURATION*/
+	{0xC92E, 0x3C, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_DEMOSAIC*/
+	{0xC92F, 0x02, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_AP_GAIN*/
+	{0xC930, 0x06, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_AP_THRESH*/
+	{0xC931, 0x64, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_STOP_DEMOSAIC*/
+	{0xC932, 0x01, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_STOP_AP_GAIN*/
+	{0xC933, 0x0C, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_STOP_AP_THRESH*/
+	{0xC934, 0x3C, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_NR_RED*/
+	{0xC935, 0x3C, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_NR_GREEN*/
+	{0xC936, 0x3C, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_NR_BLUE*/
+	{0xC937, 0x0F, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_NR_THRESH*/
+	{0xC938, 0x64, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_STOP_NR_RED*/
+	{0xC939, 0x64, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_STOP_NR_GREEN*/
+	{0xC93A, 0x64, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_STOP_NR_BLUE*/
+	{0xC93B, 0x32, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_STOP_NR_THRESH*/
+	{0xC93C, 0x0020,},/*CAM_LL_START_CONTRAST_BM*/
+	{0xC93E, 0x009A,},/*CAM_LL_STOP_CONTRAST_BM*/
+	{0xC940, 0x00DC,},/*CAM_LL_GAMMA*/
+	/*CAM_LL_START_CONTRAST_GRADIENT*/
+	{0xC942, 0x38, MSM_CAMERA_I2C_BYTE_DATA},
+	/*CAM_LL_STOP_CONTRAST_GRADIENT*/
+	{0xC943, 0x30, MSM_CAMERA_I2C_BYTE_DATA},
+	{0xC944, 0x50, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_CONTRAST_LUMA*/
+	{0xC945, 0x19, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_STOP_CONTRAST_LUMA*/
+	{0xC94A, 0x0230,},/*CAM_LL_START_FADE_TO_BLACK_LUMA*/
+	{0xC94C, 0x0010,},/*CAM_LL_STOP_FADE_TO_BLACK_LUMA*/
+	{0xC94E, 0x01CD,},/*CAM_LL_CLUSTER_DC_TH_BM*/
+	{0xC950, 0x05, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_CLUSTER_DC_GATE*/
+	{0xC951, 0x40, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_SUMMING_SENSITIVITY*/
+	/*CAM_AET_TARGET_AVERAGE_LUMA_DARK*/
+	{0xC87B, 0x1B, MSM_CAMERA_I2C_BYTE_DATA},
+	{0xC878, 0x0E, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AET_AEMODE*/
+	{0xC890, 0x0080,},/*CAM_AET_TARGET_GAIN*/
+	{0xC886, 0x0100,},/*CAM_AET_AE_MAX_VIRT_AGAIN*/
+	{0xC87C, 0x005A,},/*CAM_AET_BLACK_CLIPPING_TARGET*/
+	{0xB42A, 0x05, MSM_CAMERA_I2C_BYTE_DATA},/*CCM_DELTA_GAIN*/
+	/*AE_TRACK_AE_TRACKING_DAMPENING*/
+	{0xA80A, 0x20, MSM_CAMERA_I2C_BYTE_DATA},
+	{0x3C44, 0x0080,},
+	{0x3C40, 0x0004, MSM_CAMERA_I2C_UNSET_WORD_MASK},
+	{0xA802, 0x08, MSM_CAMERA_I2C_SET_BYTE_MASK},
+	{0xC908, 0x01, MSM_CAMERA_I2C_BYTE_DATA},
+	{0xC879, 0x01, MSM_CAMERA_I2C_BYTE_DATA},
+	{0xC909, 0x01, MSM_CAMERA_I2C_UNSET_BYTE_MASK},
+	{0xA80A, 0x18, MSM_CAMERA_I2C_BYTE_DATA},
+	{0xA80B, 0x18, MSM_CAMERA_I2C_BYTE_DATA},
+	{0xAC16, 0x18, MSM_CAMERA_I2C_BYTE_DATA},
+	{0xC878, 0x08, MSM_CAMERA_I2C_SET_BYTE_MASK},
+	{0xBC02, 0x08, MSM_CAMERA_I2C_UNSET_BYTE_MASK},
+};
+
+static struct v4l2_subdev_info mt9m114_subdev_info[] = {
+	{
+	.code   = V4L2_MBUS_FMT_YUYV8_2X8,
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	.fmt    = 1,
+	.order    = 0,
+	},
+	/* more can be supported, to be added later */
+};
+
+static struct msm_camera_i2c_reg_conf mt9m114_config_change_settings[] = {
+	{0xdc00, 0x28, MSM_CAMERA_I2C_BYTE_DATA, MSM_CAMERA_I2C_CMD_WRITE},
+	{MT9M114_COMMAND_REGISTER, MT9M114_COMMAND_REGISTER_SET_STATE,
+		MSM_CAMERA_I2C_UNSET_WORD_MASK, MSM_CAMERA_I2C_CMD_POLL},
+	{MT9M114_COMMAND_REGISTER, (MT9M114_COMMAND_REGISTER_OK |
+		MT9M114_COMMAND_REGISTER_SET_STATE), MSM_CAMERA_I2C_WORD_DATA,
+		MSM_CAMERA_I2C_CMD_WRITE},
+	{MT9M114_COMMAND_REGISTER, MT9M114_COMMAND_REGISTER_SET_STATE,
+		MSM_CAMERA_I2C_UNSET_WORD_MASK, MSM_CAMERA_I2C_CMD_POLL},
+	{0xDC01, 0x31, MSM_CAMERA_I2C_BYTE_DATA},
+};
+
+static void mt9m114_stop_stream(struct msm_sensor_ctrl_t *s_ctrl) {}
+
+static struct msm_camera_i2c_conf_array mt9m114_init_conf[] = {
+	{mt9m114_recommend_settings,
+	ARRAY_SIZE(mt9m114_recommend_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{mt9m114_config_change_settings,
+	ARRAY_SIZE(mt9m114_config_change_settings),
+	0, MSM_CAMERA_I2C_WORD_DATA},
+};
+
+static struct msm_camera_i2c_conf_array mt9m114_confs[] = {
+	{mt9m114_720p_settings,
+	ARRAY_SIZE(mt9m114_720p_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+};
+
+static struct msm_camera_i2c_reg_conf mt9m114_saturation[][1] = {
+	{{0xCC12, 0x00},},
+	{{0xCC12, 0x1A},},
+	{{0xCC12, 0x34},},
+	{{0xCC12, 0x4E},},
+	{{0xCC12, 0x68},},
+	{{0xCC12, 0x80},},
+	{{0xCC12, 0x9A},},
+	{{0xCC12, 0xB4},},
+	{{0xCC12, 0xCE},},
+	{{0xCC12, 0xE8},},
+	{{0xCC12, 0xFF},},
+};
+
+static struct msm_camera_i2c_reg_conf mt9m114_refresh[] = {
+	{MT9M114_COMMAND_REGISTER, MT9M114_COMMAND_REGISTER_REFRESH,
+		MSM_CAMERA_I2C_UNSET_WORD_MASK, MSM_CAMERA_I2C_CMD_POLL},
+	{MT9M114_COMMAND_REGISTER, (MT9M114_COMMAND_REGISTER_OK |
+		MT9M114_COMMAND_REGISTER_REFRESH), MSM_CAMERA_I2C_WORD_DATA,
+		MSM_CAMERA_I2C_CMD_WRITE},
+	{MT9M114_COMMAND_REGISTER, MT9M114_COMMAND_REGISTER_REFRESH,
+		MSM_CAMERA_I2C_UNSET_WORD_MASK, MSM_CAMERA_I2C_CMD_POLL},
+	{MT9M114_COMMAND_REGISTER, MT9M114_COMMAND_REGISTER_OK,
+		MSM_CAMERA_I2C_SET_WORD_MASK, MSM_CAMERA_I2C_CMD_POLL},
+};
+
+static struct msm_camera_i2c_conf_array mt9m114_saturation_confs[][2] = {
+	{{mt9m114_saturation[0],
+		ARRAY_SIZE(mt9m114_saturation[0]), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{mt9m114_refresh,
+		ARRAY_SIZE(mt9m114_refresh), 0, MSM_CAMERA_I2C_WORD_DATA},},
+	{{mt9m114_saturation[1],
+		ARRAY_SIZE(mt9m114_saturation[1]), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{mt9m114_refresh,
+		ARRAY_SIZE(mt9m114_refresh), 0, MSM_CAMERA_I2C_WORD_DATA},},
+	{{mt9m114_saturation[2],
+		ARRAY_SIZE(mt9m114_saturation[2]), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{mt9m114_refresh,
+		ARRAY_SIZE(mt9m114_refresh), 0, MSM_CAMERA_I2C_WORD_DATA},},
+	{{mt9m114_saturation[3],
+		ARRAY_SIZE(mt9m114_saturation[3]), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{mt9m114_refresh,
+		ARRAY_SIZE(mt9m114_refresh), 0, MSM_CAMERA_I2C_WORD_DATA},},
+	{{mt9m114_saturation[4],
+		ARRAY_SIZE(mt9m114_saturation[4]), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{mt9m114_refresh,
+		ARRAY_SIZE(mt9m114_refresh), 0, MSM_CAMERA_I2C_WORD_DATA},},
+	{{mt9m114_saturation[5],
+		ARRAY_SIZE(mt9m114_saturation[5]), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{mt9m114_refresh,
+		ARRAY_SIZE(mt9m114_refresh), 0, MSM_CAMERA_I2C_WORD_DATA},},
+	{{mt9m114_saturation[6],
+		ARRAY_SIZE(mt9m114_saturation[6]), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{mt9m114_refresh,
+		ARRAY_SIZE(mt9m114_refresh), 0, MSM_CAMERA_I2C_WORD_DATA},},
+	{{mt9m114_saturation[7],
+		ARRAY_SIZE(mt9m114_saturation[7]), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{mt9m114_refresh,
+		ARRAY_SIZE(mt9m114_refresh), 0, MSM_CAMERA_I2C_WORD_DATA},},
+	{{mt9m114_saturation[8],
+		ARRAY_SIZE(mt9m114_saturation[8]), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{mt9m114_refresh,
+		ARRAY_SIZE(mt9m114_refresh), 0, MSM_CAMERA_I2C_WORD_DATA},},
+	{{mt9m114_saturation[9],
+		ARRAY_SIZE(mt9m114_saturation[9]), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{mt9m114_refresh,
+		ARRAY_SIZE(mt9m114_refresh), 0, MSM_CAMERA_I2C_WORD_DATA},},
+	{{mt9m114_saturation[10],
+		ARRAY_SIZE(mt9m114_saturation[10]),
+		0, MSM_CAMERA_I2C_WORD_DATA},
+	{mt9m114_refresh,
+		ARRAY_SIZE(mt9m114_refresh), 0, MSM_CAMERA_I2C_WORD_DATA},},
+};
+
+static int mt9m114_saturation_enum_map[] = {
+	MSM_V4L2_SATURATION_L0,
+	MSM_V4L2_SATURATION_L1,
+	MSM_V4L2_SATURATION_L2,
+	MSM_V4L2_SATURATION_L3,
+	MSM_V4L2_SATURATION_L4,
+	MSM_V4L2_SATURATION_L5,
+	MSM_V4L2_SATURATION_L6,
+	MSM_V4L2_SATURATION_L7,
+	MSM_V4L2_SATURATION_L8,
+	MSM_V4L2_SATURATION_L9,
+	MSM_V4L2_SATURATION_L10,
+};
+
+static struct msm_camera_i2c_enum_conf_array mt9m114_saturation_enum_confs = {
+	.conf = &mt9m114_saturation_confs[0][0],
+	.conf_enum = mt9m114_saturation_enum_map,
+	.num_enum = ARRAY_SIZE(mt9m114_saturation_enum_map),
+	.num_index = ARRAY_SIZE(mt9m114_saturation_confs),
+	.num_conf = ARRAY_SIZE(mt9m114_saturation_confs[0]),
+	.data_type = MSM_CAMERA_I2C_WORD_DATA,
+};
+
+struct msm_sensor_v4l2_ctrl_info_t mt9m114_v4l2_ctrl_info[] = {
+	{
+		.ctrl_id = V4L2_CID_SATURATION,
+		.min = MSM_V4L2_SATURATION_L0,
+		.max = MSM_V4L2_SATURATION_L10,
+		.step = 1,
+		.enum_cfg_settings = &mt9m114_saturation_enum_confs,
+		.s_v4l2_ctrl = msm_sensor_s_ctrl_by_enum,
+	},
+};
+
+static struct msm_sensor_output_info_t mt9m114_dimensions[] = {
+	{
+		.x_output = 0x500,
+		.y_output = 0x2D0,
+		.line_length_pclk = 0x500,
+		.frame_length_lines = 0x2D0,
+		.vt_pixel_clk = 48000000,
+		.op_pixel_clk = 128000000,
+		.binning_factor = 1,
+	},
+};
+
+static struct msm_camera_csid_vc_cfg mt9m114_cid_cfg[] = {
+	{0, CSI_YUV422_8, CSI_DECODE_8BIT},
+	{1, CSI_EMBED_DATA, CSI_DECODE_8BIT},
+};
+
+static struct msm_camera_csi2_params mt9m114_csi_params = {
+	.csid_params = {
+		.lane_assign = 0xe4,
+		.lane_cnt = 1,
+		.lut_params = {
+			.num_cid = 2,
+			.vc_cfg = mt9m114_cid_cfg,
+		},
+	},
+	.csiphy_params = {
+		.lane_cnt = 1,
+		.settle_cnt = 0x14,
+	},
+};
+
+static struct msm_camera_csi2_params *mt9m114_csi_params_array[] = {
+	&mt9m114_csi_params,
+	&mt9m114_csi_params,
+};
+
+static struct msm_sensor_output_reg_addr_t mt9m114_reg_addr = {
+	.x_output = 0xC868,
+	.y_output = 0xC86A,
+	.line_length_pclk = 0xC868,
+	.frame_length_lines = 0xC86A,
+};
+
+static struct msm_sensor_id_info_t mt9m114_id_info = {
+	.sensor_id_reg_addr = 0x0,
+	.sensor_id = 0x2481,
+};
+
+static int mt9m114_sensor_config(void __user *argp)
+{
+	return msm_sensor_config(&mt9m114_s_ctrl, argp);
+}
+
+static int mt9m114_sensor_open_init(const struct msm_camera_sensor_info *data)
+{
+	return msm_sensor_open_init(&mt9m114_s_ctrl, data);
+}
+
+static int mt9m114_sensor_release(void)
+{
+	return msm_sensor_release(&mt9m114_s_ctrl);
+}
+
+static const struct i2c_device_id mt9m114_i2c_id[] = {
+	{SENSOR_NAME, (kernel_ulong_t)&mt9m114_s_ctrl},
+	{ }
+};
+
+static struct i2c_driver mt9m114_i2c_driver = {
+	.id_table = mt9m114_i2c_id,
+	.probe  = msm_sensor_i2c_probe,
+	.driver = {
+		.name = SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client mt9m114_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static int mt9m114_sensor_v4l2_probe(const struct msm_camera_sensor_info *info,
+	struct v4l2_subdev *sdev, struct msm_sensor_ctrl *s)
+{
+	return msm_sensor_v4l2_probe(&mt9m114_s_ctrl, info, sdev, s);
+}
+
+static int mt9m114_probe(struct platform_device *pdev)
+{
+	return msm_sensor_register(pdev, mt9m114_sensor_v4l2_probe);
+}
+
+struct platform_driver mt9m114_driver = {
+	.probe = mt9m114_probe,
+	.driver = {
+		.name = PLATFORM_DRIVER_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_sensor_init_module(void)
+{
+	return platform_driver_register(&mt9m114_driver);
+}
+
+static struct v4l2_subdev_core_ops mt9m114_subdev_core_ops = {
+	.s_ctrl = msm_sensor_v4l2_s_ctrl,
+	.queryctrl = msm_sensor_v4l2_query_ctrl,
+};
+
+static struct v4l2_subdev_video_ops mt9m114_subdev_video_ops = {
+	.enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops mt9m114_subdev_ops = {
+	.core = &mt9m114_subdev_core_ops,
+	.video  = &mt9m114_subdev_video_ops,
+};
+
+static struct msm_sensor_fn_t mt9m114_func_tbl = {
+	.sensor_start_stream = msm_sensor_start_stream,
+	.sensor_stop_stream = mt9m114_stop_stream,
+	.sensor_setting = msm_sensor_setting,
+	.sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+	.sensor_mode_init = msm_sensor_mode_init,
+	.sensor_get_output_info = msm_sensor_get_output_info,
+	.sensor_config = mt9m114_sensor_config,
+	.sensor_open_init = mt9m114_sensor_open_init,
+	.sensor_release = mt9m114_sensor_release,
+	.sensor_power_up = msm_sensor_power_up,
+	.sensor_power_down = msm_sensor_power_down,
+	.sensor_probe = msm_sensor_probe,
+};
+
+static struct msm_sensor_reg_t mt9m114_regs = {
+	.default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+	.start_stream_conf = mt9m114_config_change_settings,
+	.start_stream_conf_size = ARRAY_SIZE(mt9m114_config_change_settings),
+	.init_settings = &mt9m114_init_conf[0],
+	.init_size = ARRAY_SIZE(mt9m114_init_conf),
+	.mode_settings = &mt9m114_confs[0],
+	.output_settings = &mt9m114_dimensions[0],
+	.num_conf = ARRAY_SIZE(mt9m114_confs),
+};
+
+static struct msm_sensor_ctrl_t mt9m114_s_ctrl = {
+	.msm_sensor_reg = &mt9m114_regs,
+	.msm_sensor_v4l2_ctrl_info = mt9m114_v4l2_ctrl_info,
+	.num_v4l2_ctrl = ARRAY_SIZE(mt9m114_v4l2_ctrl_info),
+	.sensor_i2c_client = &mt9m114_sensor_i2c_client,
+	.sensor_i2c_addr = 0x90,
+	.sensor_output_reg_addr = &mt9m114_reg_addr,
+	.sensor_id_info = &mt9m114_id_info,
+	.cam_mode = MSM_SENSOR_MODE_INVALID,
+	.csi_params = &mt9m114_csi_params_array[0],
+	.msm_sensor_mutex = &mt9m114_mut,
+	.sensor_i2c_driver = &mt9m114_i2c_driver,
+	.sensor_v4l2_subdev_info = mt9m114_subdev_info,
+	.sensor_v4l2_subdev_info_size = ARRAY_SIZE(mt9m114_subdev_info),
+	.sensor_v4l2_subdev_ops = &mt9m114_subdev_ops,
+	.func_tbl = &mt9m114_func_tbl,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Aptina 1.26MP YUV sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/pmic8901.c b/drivers/mfd/pmic8901.c
index 3d87f0b..9e8786e 100644
--- a/drivers/mfd/pmic8901.c
+++ b/drivers/mfd/pmic8901.c
@@ -11,51 +11,25 @@
  */
 
 #include <linux/interrupt.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/ratelimit.h>
-#include <linux/gpio.h>
+#include <linux/delay.h>
 #include <linux/mfd/core.h>
 #include <linux/msm_ssbi.h>
 #include <linux/mfd/pmic8901.h>
-#include <linux/platform_device.h>
-#include <linux/debugfs.h>
-#include <linux/delay.h>
+#include <linux/mfd/pm8xxx/core.h>
 
 /* PMIC8901 Revision */
-#define SSBI_REG_REV			0x002  /* PMIC4 revision */
+#define PM8901_REG_REV			0x002
+#define PM8901_VERSION_MASK		0xF0
+#define PM8901_REVISION_MASK		0x0F
+#define PM8901_VERSION_VALUE		0xF0
 
-/* PMIC8901 IRQ */
-#define	SSBI_REG_ADDR_IRQ_BASE		0xD5
+#define REG_IRQ_BASE			0xD5
+#define REG_MPP_BASE			0x27
 
-#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	PM8901_IRQF_LVL_SEL		0x01	/* level select */
-#define	PM8901_IRQF_MASK_FE		0x02	/* mask falling edge */
-#define	PM8901_IRQF_MASK_RE		0x04	/* mask rising edge */
-#define	PM8901_IRQF_CLR			0x08	/* clear interrupt */
-#define	PM8901_IRQF_BITS_MASK		0x70
-#define	PM8901_IRQF_BITS_SHIFT		4
-#define	PM8901_IRQF_WRITE		0x80
-
-#define	PM8901_IRQF_MASK_ALL		(PM8901_IRQF_MASK_FE | \
-					PM8901_IRQF_MASK_RE)
-#define PM8901_IRQF_W_C_M		(PM8901_IRQF_WRITE |	\
-					PM8901_IRQF_CLR |	\
-					PM8901_IRQF_MASK_ALL)
-
-#define	MAX_PM_IRQ			72
-#define	MAX_PM_BLOCKS			(MAX_PM_IRQ / 8 + 1)
-#define	MAX_PM_MASTERS			(MAX_PM_BLOCKS / 8 + 1)
-
-#define MPP_IRQ_BLOCK			1
+#define REG_TEMP_ALRM_CTRL		0x23
+#define REG_TEMP_ALRM_PWM		0x24
 
 /* FTS regulator PMR registers */
 #define SSBI_REG_ADDR_S1_PMR		(0xA7)
@@ -70,47 +44,24 @@
 #define DELAY_AFTER_REG_DISABLE_MS	4
 #define DELAY_BEFORE_SHUTDOWN_MS	8
 
+#define SINGLE_IRQ_RESOURCE(_name, _irq) \
+{ \
+	.name	= _name, \
+	.start	= _irq, \
+	.end	= _irq, \
+	.flags	= IORESOURCE_IRQ, \
+}
+
 struct pm8901_chip {
 	struct pm8901_platform_data	pdata;
 	struct device			*dev;
-
-	u8	irqs_allowed[MAX_PM_BLOCKS];
-	u8	blocks_allowed[MAX_PM_MASTERS];
-	u8	masters_allowed;
-	int	pm_max_irq;
-	int	pm_max_blocks;
-	int	pm_max_masters;
-
-	u8	config[MAX_PM_IRQ];
-	u8	wake_enable[MAX_PM_IRQ];
-	u16	count_wakeable;
-
-	u8	revision;
-
-	spinlock_t	pm_lock;
+	struct pm_irq_chip		*irq_chip;
+	struct mfd_cell			*mfd_regulators;
+	u8				revision;
 };
 
-#if defined(CONFIG_DEBUG_FS)
-struct pm8901_dbg_device {
-	struct mutex		dbg_mutex;
-	struct pm8901_chip	*pm_chip;
-	struct dentry		*dent;
-	int			addr;
-};
-
-static struct pm8901_dbg_device *pmic_dbg_device;
-#endif
-
 static struct pm8901_chip *pmic_chip;
 
-/* Helper Functions */
-DEFINE_RATELIMIT_STATE(pm8901_msg_ratelimit, 60 * HZ, 10);
-
-static inline int pm8901_can_print(void)
-{
-	return __ratelimit(&pm8901_msg_ratelimit);
-}
-
 static inline int
 ssbi_read(struct device *dev, u16 addr, u8 *buf, size_t len)
 {
@@ -123,80 +74,6 @@
 	return msm_ssbi_write(dev->parent, addr, buf, len);
 }
 
-/* External APIs */
-int pm8901_rev(struct pm8901_chip *chip)
-{
-	if (chip == NULL) {
-		if (pmic_chip != NULL)
-			return pmic_chip->revision;
-		else
-			return -EINVAL;
-	}
-
-	return chip->revision;
-}
-EXPORT_SYMBOL(pm8901_rev);
-
-int pm8901_read(struct pm8901_chip *chip, u16 addr, u8 *values,
-		unsigned int len)
-{
-	if (chip == NULL)
-		return -EINVAL;
-
-	return ssbi_read(chip->dev, addr, values, len);
-}
-EXPORT_SYMBOL(pm8901_read);
-
-int pm8901_write(struct pm8901_chip *chip, u16 addr, u8 *values,
-		 unsigned int len)
-{
-	if (chip == NULL)
-		return -EINVAL;
-
-	return ssbi_write(chip->dev, addr, values, len);
-}
-EXPORT_SYMBOL(pm8901_write);
-
-int pm8901_irq_get_rt_status(struct pm8901_chip *chip, int irq)
-{
-	int     rc;
-	u8      block, bits, bit;
-	unsigned long   irqsave;
-
-	if (chip == NULL || irq < chip->pdata.irq_base ||
-			irq >= chip->pdata.irq_base + MAX_PM_IRQ)
-		return -EINVAL;
-
-	irq -= chip->pdata.irq_base;
-
-	block = irq / 8;
-	bit = irq % 8;
-
-	spin_lock_irqsave(&chip->pm_lock, irqsave);
-
-	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, &block, 1);
-	if (rc) {
-		pr_err("%s: FAIL ssbi_write(): rc=%d (Select Block)\n",
-				__func__, rc);
-		goto bail_out;
-	}
-
-	rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits, 1);
-	if (rc) {
-		pr_err("%s: FAIL ssbi_read(): rc=%d (Read RT Status)\n",
-				__func__, rc);
-		goto bail_out;
-	}
-
-	rc = (bits & (1 << bit)) ? 1 : 0;
-
-bail_out:
-	spin_unlock_irqrestore(&chip->pm_lock, irqsave);
-
-	return rc;
-}
-EXPORT_SYMBOL(pm8901_irq_get_rt_status);
-
 int pm8901_reset_pwr_off(int reset)
 {
 	int rc = 0, i;
@@ -240,673 +117,283 @@
 }
 EXPORT_SYMBOL(pm8901_reset_pwr_off);
 
-/* Internal functions */
-static inline int
-pm8901_config_irq(struct pm8901_chip *chip, u8 *bp, u8 *cp)
+static int pm8901_readb(const struct device *dev, u16 addr, u8 *val)
 {
-	int	rc;
+	const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+	const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
 
-	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp, 1);
-	if (rc) {
-		pr_err("%s: ssbi_write: rc=%d (Select block)\n",
-			__func__, rc);
-		goto bail_out;
-	}
-
-	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp, 1);
-	if (rc)
-		pr_err("%s: ssbi_write: rc=%d (Configure IRQ)\n",
-			__func__, rc);
-
-bail_out:
-	return rc;
+	return msm_ssbi_read(pmic->dev->parent, addr, val, 1);
 }
 
-static void pm8901_irq_mask(struct irq_data *d)
+static int pm8901_writeb(const struct device *dev, u16 addr, u8 val)
 {
-	int	master, irq_bit;
-	struct	pm8901_chip *chip = irq_data_get_irq_handler_data(d);
-	u8	block, config;
-	unsigned int irq = d->irq;
+	const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+	const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
 
-	irq -= chip->pdata.irq_base;
-	block = irq / 8;
-	master = block / 8;
-	irq_bit = irq % 8;
-
-	chip->irqs_allowed[block] &= ~(1 << irq_bit);
-	if (!chip->irqs_allowed[block]) {
-		chip->blocks_allowed[master] &= ~(1 << (block % 8));
-
-		if (!chip->blocks_allowed[master])
-			chip->masters_allowed &= ~(1 << master);
-	}
-
-	config = PM8901_IRQF_WRITE | chip->config[irq] |
-		PM8901_IRQF_MASK_FE | PM8901_IRQF_MASK_RE;
-	pm8901_config_irq(chip, &block, &config);
+	return msm_ssbi_write(pmic->dev->parent, addr, &val, 1);
 }
 
-static void pm8901_irq_unmask(struct irq_data *d)
+static int pm8901_read_buf(const struct device *dev, u16 addr, u8 *buf,
+								int cnt)
 {
-	int	master, irq_bit;
-	struct	pm8901_chip *chip = irq_data_get_irq_handler_data(d);
-	u8	block, config, old_irqs_allowed, old_blocks_allowed;
-	unsigned int irq = d->irq;
+	const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+	const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
 
-	irq -= chip->pdata.irq_base;
-	block = irq / 8;
-	master = block / 8;
-	irq_bit = irq % 8;
-
-	old_irqs_allowed = chip->irqs_allowed[block];
-	chip->irqs_allowed[block] |= 1 << irq_bit;
-	if (!old_irqs_allowed) {
-		master = block / 8;
-
-		old_blocks_allowed = chip->blocks_allowed[master];
-		chip->blocks_allowed[master] |= 1 << (block % 8);
-
-		if (!old_blocks_allowed)
-			chip->masters_allowed |= 1 << master;
-	}
-
-	config = PM8901_IRQF_WRITE | chip->config[irq];
-	pm8901_config_irq(chip, &block, &config);
+	return msm_ssbi_read(pmic->dev->parent, addr, buf, cnt);
 }
 
-static void pm8901_irq_ack(struct irq_data *d)
+static int pm8901_write_buf(const struct device *dev, u16 addr, u8 *buf,
+								int cnt)
 {
-	struct	pm8901_chip *chip = irq_data_get_irq_handler_data(d);
-	u8	block, config;
-	unsigned int irq = d->irq;
+	const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+	const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
 
-	irq -= chip->pdata.irq_base;
-	block = irq / 8;
-
-	config = PM8901_IRQF_WRITE | chip->config[irq] | PM8901_IRQF_CLR;
-	pm8901_config_irq(chip, &block, &config);
+	return msm_ssbi_write(pmic->dev->parent, addr, buf, cnt);
 }
 
-static int pm8901_irq_set_type(struct irq_data *d, unsigned int flow_type)
+static int pm8901_read_irq_stat(const struct device *dev, int irq)
 {
-	int	master, irq_bit;
-	struct	pm8901_chip *chip = irq_data_get_irq_handler_data(d);
-	u8	block, config;
-	unsigned int irq = d->irq;
+	const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+	const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
 
-	irq -= chip->pdata.irq_base;
-	if (irq > chip->pm_max_irq) {
-		chip->pm_max_irq = irq;
-		chip->pm_max_blocks =
-			chip->pm_max_irq / 8 + 1;
-		chip->pm_max_masters =
-			chip->pm_max_blocks / 8 + 1;
-	}
-	block = irq / 8;
-	master = block / 8;
-	irq_bit = irq % 8;
-
-	chip->config[irq] = (irq_bit << PM8901_IRQF_BITS_SHIFT) |
-			PM8901_IRQF_MASK_RE | PM8901_IRQF_MASK_FE;
-	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
-		if (flow_type & IRQF_TRIGGER_RISING)
-			chip->config[irq] &= ~PM8901_IRQF_MASK_RE;
-		if (flow_type & IRQF_TRIGGER_FALLING)
-			chip->config[irq] &= ~PM8901_IRQF_MASK_FE;
-	} else {
-		chip->config[irq] |= PM8901_IRQF_LVL_SEL;
-
-		if (flow_type & IRQF_TRIGGER_HIGH)
-			chip->config[irq] &= ~PM8901_IRQF_MASK_RE;
-		else
-			chip->config[irq] &= ~PM8901_IRQF_MASK_FE;
-	}
-
-	config = PM8901_IRQF_WRITE | chip->config[irq] | PM8901_IRQF_CLR;
-	return pm8901_config_irq(chip, &block, &config);
-}
-
-static int pm8901_irq_set_wake(struct irq_data *d, unsigned int on)
-{
-	struct	pm8901_chip *chip = irq_data_get_irq_handler_data(d);
-	unsigned int irq = d->irq;
-
-	irq -= chip->pdata.irq_base;
-	if (on) {
-		if (!chip->wake_enable[irq]) {
-			chip->wake_enable[irq] = 1;
-			chip->count_wakeable++;
-		}
-	} else {
-		if (chip->wake_enable[irq]) {
-			chip->wake_enable[irq] = 0;
-			chip->count_wakeable--;
-		}
-	}
+	return pm8xxx_get_irq_stat(pmic->irq_chip, irq);
 
 	return 0;
 }
 
-static inline int
-pm8901_read_root(struct pm8901_chip *chip, u8 *rp)
+static enum pm8xxx_version pm8901_get_version(const struct device *dev)
 {
-	int	rc;
+	const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+	const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
+	enum pm8xxx_version version = -ENODEV;
 
-	rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_ROOT, rp, 1);
-	if (rc) {
-		pr_err("%s: FAIL ssbi_read(): rc=%d (Read Root)\n",
-			__func__, rc);
-		*rp = 0;
-	}
+	if ((pmic->revision & PM8901_VERSION_MASK) == PM8901_VERSION_VALUE)
+		version = PM8XXX_VERSION_8901;
 
-	return rc;
+	return version;
 }
 
-static inline int
-pm8901_read_master(struct pm8901_chip *chip, u8 m, u8 *bp)
+static int pm8901_get_revision(const struct device *dev)
 {
-	int	rc;
+	const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+	const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
 
-	rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp, 1);
-	if (rc) {
-		pr_err("%s: FAIL ssbi_read(): rc=%d (Read Master)\n",
-			__func__, rc);
-		*bp = 0;
-	}
-
-	return rc;
+	return pmic->revision & PM8901_REVISION_MASK;
 }
 
-static inline int
-pm8901_read_block(struct pm8901_chip *chip, u8 *bp, u8 *ip)
-{
-	int	rc;
-
-	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp, 1);
-	if (rc) {
-		pr_err("%s: FAIL ssbi_write(): rc=%d (Select Block)\n",
-		       __func__, rc);
-		*bp = 0;
-		goto bail_out;
-	}
-
-	rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip, 1);
-	if (rc)
-		pr_err("%s: FAIL ssbi_read(): rc=%d (Read Status)\n",
-		       __func__, rc);
-
-bail_out:
-	return rc;
-}
-
-static irqreturn_t pm8901_isr_thread(int irq_requested, void *data)
-{
-	struct pm8901_chip *chip = data;
-	int	i, j, k;
-	u8	root, block, config, bits;
-	u8	blocks[MAX_PM_MASTERS];
-	int	masters = 0, irq, handled = 0, spurious = 0;
-	u16     irqs_to_handle[MAX_PM_IRQ];
-	unsigned long	irqsave;
-
-	spin_lock_irqsave(&chip->pm_lock, irqsave);
-
-	/* Read root for masters */
-	if (pm8901_read_root(chip, &root))
-		goto bail_out;
-
-	masters = root >> 1;
-
-	if (!(masters & chip->masters_allowed) ||
-	    (masters & ~chip->masters_allowed)) {
-		spurious = 1000000;
-	}
-
-	/* Read allowed masters for blocks. */
-	for (i = 0; i < chip->pm_max_masters; i++) {
-		if (masters & (1 << i)) {
-			if (pm8901_read_master(chip, i, &blocks[i]))
-				goto bail_out;
-
-			if (!blocks[i]) {
-				if (pm8901_can_print())
-					pr_err("%s: Spurious master: %d "
-					       "(blocks=0)", __func__, i);
-				spurious += 10000;
-			}
-		} else
-			blocks[i] = 0;
-	}
-
-	/* Select block, read status and call isr */
-	for (i = 0; i < chip->pm_max_masters; i++) {
-		if (!blocks[i])
-			continue;
-
-		for (j = 0; j < 8; j++) {
-			if (!(blocks[i] & (1 << j)))
-				continue;
-
-			block = i * 8 + j;	/* block # */
-			if (pm8901_read_block(chip, &block, &bits))
-				goto bail_out;
-
-			if (!bits) {
-				if (pm8901_can_print())
-					pr_err("%s: Spurious block: "
-					       "[master, block]=[%d, %d] "
-					       "(bits=0)\n", __func__, i, j);
-				spurious += 100;
-				continue;
-			}
-
-			/* Check IRQ bits */
-			for (k = 0; k < 8; k++) {
-				if (!(bits & (1 << k)))
-					continue;
-
-				/* Check spurious interrupts */
-				if (((1 << i) & chip->masters_allowed) &&
-				    (blocks[i] & chip->blocks_allowed[i]) &&
-				    (bits & chip->irqs_allowed[block])) {
-
-					/* Found one */
-					irq = block * 8 + k;
-					irqs_to_handle[handled] = irq +
-						chip->pdata.irq_base;
-					handled++;
-				} else {
-					/* Clear and mask wrong one */
-					config = PM8901_IRQF_W_C_M |
-						(k < PM8901_IRQF_BITS_SHIFT);
-
-					pm8901_config_irq(chip,
-							  &block, &config);
-
-					if (pm8901_can_print())
-						pr_err("%s: Spurious IRQ: "
-						       "[master, block, bit]="
-						       "[%d, %d (%d), %d]\n",
-							__func__,
-						       i, j, block, k);
-					spurious++;
-				}
-			}
-		}
-
-	}
-
-bail_out:
-
-	spin_unlock_irqrestore(&chip->pm_lock, irqsave);
-
-	for (i = 0; i < handled; i++)
-		generic_handle_irq(irqs_to_handle[i]);
-
-	if (spurious) {
-		if (!pm8901_can_print())
-			return IRQ_HANDLED;
-
-		pr_err("%s: spurious = %d (handled = %d)\n",
-		       __func__, spurious, handled);
-		pr_err("   root = 0x%x (masters_allowed<<1 = 0x%x)\n",
-		       root, chip->masters_allowed << 1);
-		for (i = 0; i < chip->pm_max_masters; i++) {
-			if (masters & (1 << i))
-				pr_err("   blocks[%d]=0x%x, "
-				       "allowed[%d]=0x%x\n",
-				       i, blocks[i],
-				       i, chip->blocks_allowed[i]);
-		}
-	}
-
-	return IRQ_HANDLED;
-}
-
-#if defined(CONFIG_DEBUG_FS)
-
-static int check_addr(int addr, const char *func_name)
-{
-	if (addr < 0 || addr > 0x3FF) {
-		pr_err("%s: PMIC 8901 register address is invalid: %d\n",
-			func_name, addr);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int data_set(void *data, u64 val)
-{
-	struct pm8901_dbg_device *dbgdev = data;
-	u8 reg = val;
-	int rc;
-
-	mutex_lock(&dbgdev->dbg_mutex);
-
-	rc = check_addr(dbgdev->addr, __func__);
-	if (rc)
-		goto done;
-
-	rc = pm8901_write(dbgdev->pm_chip, dbgdev->addr, &reg, 1);
-
-	if (rc)
-		pr_err("%s: FAIL pm8901_write(0x%03X)=0x%02X: rc=%d\n",
-			__func__, dbgdev->addr, reg, rc);
-done:
-	mutex_unlock(&dbgdev->dbg_mutex);
-	return rc;
-}
-
-static int data_get(void *data, u64 *val)
-{
-	struct pm8901_dbg_device *dbgdev = data;
-	int rc;
-	u8 reg;
-
-	mutex_lock(&dbgdev->dbg_mutex);
-
-	rc = check_addr(dbgdev->addr, __func__);
-	if (rc)
-		goto done;
-
-	rc = pm8901_read(dbgdev->pm_chip, dbgdev->addr, &reg, 1);
-
-	if (rc) {
-		pr_err("%s: FAIL pm8901_read(0x%03X)=0x%02X: rc=%d\n",
-			__func__, dbgdev->addr, reg, rc);
-		goto done;
-	}
-
-	*val = reg;
-done:
-	mutex_unlock(&dbgdev->dbg_mutex);
-	return rc;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(dbg_data_fops, data_get, data_set, "0x%02llX\n");
-
-static int addr_set(void *data, u64 val)
-{
-	struct pm8901_dbg_device *dbgdev = data;
-	int rc;
-
-	rc = check_addr(val, __func__);
-	if (rc)
-		return rc;
-
-	mutex_lock(&dbgdev->dbg_mutex);
-	dbgdev->addr = val;
-	mutex_unlock(&dbgdev->dbg_mutex);
-
-	return 0;
-}
-
-static int addr_get(void *data, u64 *val)
-{
-	struct pm8901_dbg_device *dbgdev = data;
-	int rc;
-
-	mutex_lock(&dbgdev->dbg_mutex);
-
-	rc = check_addr(dbgdev->addr, __func__);
-	if (rc) {
-		mutex_unlock(&dbgdev->dbg_mutex);
-		return rc;
-	}
-	*val = dbgdev->addr;
-
-	mutex_unlock(&dbgdev->dbg_mutex);
-
-	return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(dbg_addr_fops, addr_get, addr_set, "0x%03llX\n");
-
-static int __devinit pmic8901_dbg_probe(struct pm8901_chip *chip)
-{
-	struct pm8901_dbg_device *dbgdev;
-	struct dentry *dent;
-	struct dentry *temp;
-	int rc;
-
-	if (chip == NULL) {
-		pr_err("%s: no parent data passed in.\n", __func__);
-		return -EINVAL;
-	}
-
-	dbgdev = kzalloc(sizeof *dbgdev, GFP_KERNEL);
-	if (dbgdev == NULL) {
-		pr_err("%s: kzalloc() failed.\n", __func__);
-		return -ENOMEM;
-	}
-
-	dbgdev->pm_chip = chip;
-	dbgdev->addr = -1;
-
-	dent = debugfs_create_dir("pm8901-dbg", NULL);
-	if (dent == NULL || IS_ERR(dent)) {
-		pr_err("%s: ERR debugfs_create_dir: dent=0x%X\n",
-					__func__, (unsigned)dent);
-		rc = PTR_ERR(dent);
-		goto dir_error;
-	}
-
-	temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, dent,
-					dbgdev, &dbg_addr_fops);
-	if (temp == NULL || IS_ERR(temp)) {
-		pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
-					__func__, (unsigned)temp);
-		rc = PTR_ERR(temp);
-		goto debug_error;
-	}
-
-	temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, dent,
-					dbgdev, &dbg_data_fops);
-	if (temp == NULL || IS_ERR(temp)) {
-		pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
-					__func__, (unsigned)temp);
-		rc = PTR_ERR(temp);
-		goto debug_error;
-	}
-
-	mutex_init(&dbgdev->dbg_mutex);
-
-	dbgdev->dent = dent;
-
-	pmic_dbg_device = dbgdev;
-
-	return 0;
-
-debug_error:
-	debugfs_remove_recursive(dent);
-dir_error:
-	kfree(dbgdev);
-
-	return rc;
-}
-
-static int __devexit pmic8901_dbg_remove(void)
-{
-	if (pmic_dbg_device) {
-		debugfs_remove_recursive(pmic_dbg_device->dent);
-		mutex_destroy(&pmic_dbg_device->dbg_mutex);
-		kfree(pmic_dbg_device);
-	}
-	return 0;
-}
-
-#else
-
-static int __devinit pmic8901_dbg_probe(struct pm8901_chip *chip)
-{
-	return 0;
-}
-
-static int __devexit pmic8901_dbg_remove(void)
-{
-	return 0;
-}
-
-#endif
-
-static struct irq_chip pm8901_irq_chip = {
-	.name      = "pm8901",
-	.irq_ack       = pm8901_irq_ack,
-	.irq_mask      = pm8901_irq_mask,
-	.irq_unmask    = pm8901_irq_unmask,
-	.irq_set_type  = pm8901_irq_set_type,
-	.irq_set_wake  = pm8901_irq_set_wake,
+static struct pm8xxx_drvdata pm8901_drvdata = {
+	.pmic_readb		= pm8901_readb,
+	.pmic_writeb		= pm8901_writeb,
+	.pmic_read_buf		= pm8901_read_buf,
+	.pmic_write_buf		= pm8901_write_buf,
+	.pmic_read_irq_stat	= pm8901_read_irq_stat,
+	.pmic_get_version	= pm8901_get_version,
+	.pmic_get_revision	= pm8901_get_revision,
 };
 
+static struct mfd_cell debugfs_cell = {
+	.name		= "pm8xxx-debug",
+	.id		= 1,
+	.platform_data	= "pm8901-dbg",
+	.pdata_size	= sizeof("pm8901-dbg"),
+};
+
+static const struct resource thermal_alarm_cell_resources[] = {
+	SINGLE_IRQ_RESOURCE("pm8901_tempstat_irq", PM8901_TEMPSTAT_IRQ),
+	SINGLE_IRQ_RESOURCE("pm8901_overtemp_irq", PM8901_OVERTEMP_IRQ),
+};
+
+static struct pm8xxx_tm_core_data thermal_alarm_cdata = {
+	.adc_type			= PM8XXX_TM_ADC_NONE,
+	.reg_addr_temp_alarm_ctrl	= REG_TEMP_ALRM_CTRL,
+	.reg_addr_temp_alarm_pwm	= REG_TEMP_ALRM_PWM,
+	.tm_name			= "pm8901_tz",
+	.irq_name_temp_stat		= "pm8901_tempstat_irq",
+	.irq_name_over_temp		= "pm8901_overtemp_irq",
+};
+
+static struct mfd_cell thermal_alarm_cell = {
+	.name		= PM8XXX_TM_DEV_NAME,
+	.id		= 1,
+	.resources	= thermal_alarm_cell_resources,
+	.num_resources	= ARRAY_SIZE(thermal_alarm_cell_resources),
+	.platform_data	= &thermal_alarm_cdata,
+	.pdata_size	= sizeof(struct pm8xxx_tm_core_data),
+};
+
+static const struct resource mpp_cell_resources[] = {
+	{
+		.start	= PM8901_IRQ_BLOCK_BIT(PM8901_MPP_BLOCK_START, 0),
+		.end	= PM8901_IRQ_BLOCK_BIT(PM8901_MPP_BLOCK_START, 0)
+			  + PM8901_MPPS - 1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct mfd_cell mpp_cell = {
+	.name		= PM8XXX_MPP_DEV_NAME,
+	.id		= 1,
+	.resources	= mpp_cell_resources,
+	.num_resources	= ARRAY_SIZE(mpp_cell_resources),
+};
+
+static int __devinit
+pm8901_add_subdevices(const struct pm8901_platform_data *pdata,
+				struct pm8901_chip *pmic)
+{
+	int rc = 0, irq_base = 0, i;
+	struct pm_irq_chip *irq_chip;
+	static struct mfd_cell *mfd_regulators;
+
+	if (pdata->irq_pdata) {
+		pdata->irq_pdata->irq_cdata.nirqs = PM8901_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);
+
+		if (IS_ERR(irq_chip)) {
+			pr_err("Failed to init interrupts ret=%ld\n",
+					PTR_ERR(irq_chip));
+			return PTR_ERR(irq_chip);
+		}
+		pmic->irq_chip = irq_chip;
+	}
+
+	if (pdata->mpp_pdata) {
+		pdata->mpp_pdata->core_data.nmpps = PM8901_MPPS;
+		pdata->mpp_pdata->core_data.base_addr = REG_MPP_BASE;
+		mpp_cell.platform_data = pdata->mpp_pdata;
+		mpp_cell.pdata_size = sizeof(struct pm8xxx_mpp_platform_data);
+		rc = mfd_add_devices(pmic->dev, 0, &mpp_cell, 1, NULL,
+					irq_base);
+		if (rc) {
+			pr_err("Failed to add mpp subdevice ret=%d\n", rc);
+			goto bail;
+		}
+	}
+
+	if (pdata->num_regulators > 0 && pdata->regulator_pdatas) {
+		mfd_regulators = kzalloc(sizeof(struct mfd_cell)
+					 * (pdata->num_regulators), GFP_KERNEL);
+		if (!mfd_regulators) {
+			pr_err("Cannot allocate %d bytes for pm8901 regulator "
+				"mfd cells\n", sizeof(struct mfd_cell)
+						* (pdata->num_regulators));
+			rc = -ENOMEM;
+			goto bail;
+		}
+		for (i = 0; i < pdata->num_regulators; i++) {
+			mfd_regulators[i].name = "pm8901-regulator";
+			mfd_regulators[i].id = pdata->regulator_pdatas[i].id;
+			mfd_regulators[i].platform_data =
+				&(pdata->regulator_pdatas[i]);
+			mfd_regulators[i].pdata_size =
+					sizeof(struct pm8901_vreg_pdata);
+		}
+		rc = mfd_add_devices(pmic->dev, 0, mfd_regulators,
+				pdata->num_regulators, NULL, irq_base);
+		if (rc) {
+			pr_err("Failed to add regulator subdevices ret=%d\n",
+				rc);
+			kfree(mfd_regulators);
+			goto bail;
+		}
+		pmic->mfd_regulators = mfd_regulators;
+	}
+
+	rc = mfd_add_devices(pmic->dev, 0, &thermal_alarm_cell, 1, NULL,
+							irq_base);
+	if (rc) {
+		pr_err("Failed to add thermal alarm subdevice ret=%d\n",
+			rc);
+		goto bail;
+	}
+
+	rc = mfd_add_devices(pmic->dev, 0, &debugfs_cell, 1, NULL, irq_base);
+	if (rc) {
+		pr_err("Failed to add debugfs subdevice ret=%d\n", rc);
+		goto bail;
+	}
+
+	return rc;
+
+bail:
+	if (pmic->irq_chip) {
+		pm8xxx_irq_exit(pmic->irq_chip);
+		pmic->irq_chip = NULL;
+	}
+	return rc;
+}
+
 static int pm8901_probe(struct platform_device *pdev)
 {
-	int i, rc;
+	int rc;
 	struct pm8901_platform_data *pdata = pdev->dev.platform_data;
-	struct pm8901_chip *chip;
+	struct pm8901_chip *pmic;
 
-	if (pdata == NULL || pdata->irq <= 0) {
+	if (pdata == NULL) {
 		pr_err("%s: No platform_data or IRQ.\n", __func__);
 		return -ENODEV;
 	}
 
-	chip = kzalloc(sizeof *chip, GFP_KERNEL);
-	if (chip == NULL) {
+	pmic = kzalloc(sizeof *pmic, GFP_KERNEL);
+	if (pmic == NULL) {
 		pr_err("%s: kzalloc() failed.\n", __func__);
 		return -ENOMEM;
 	}
 
-	chip->dev = &pdev->dev;
+	pmic->dev = &pdev->dev;
+
+	pm8901_drvdata.pm_chip_data = pmic;
+	platform_set_drvdata(pdev, &pm8901_drvdata);
+	pmic_chip = pmic;
 
 	/* Read PMIC chip revision */
-	rc = ssbi_read(chip->dev, SSBI_REG_REV, &chip->revision, 1);
+	rc = pm8901_readb(pmic->dev, PM8901_REG_REV, &pmic->revision);
 	if (rc)
-		pr_err("%s: Failed on ssbi_read for revision: rc=%d.\n",
+		pr_err("%s: Failed reading version register rc=%d.\n",
 			__func__, rc);
-	pr_info("%s: PMIC revision: %X\n", __func__, chip->revision);
 
-	(void) memcpy((void *)&chip->pdata, (const void *)pdata,
-		      sizeof(chip->pdata));
+	pr_info("%s: PMIC REVISION = %X\n", __func__, pmic->revision);
 
-	irq_set_handler_data(pdata->irq, (void *)chip);
-	irq_set_irq_wake(pdata->irq, 1);
+	(void) memcpy((void *)&pmic->pdata, (const void *)pdata,
+		      sizeof(pmic->pdata));
 
-	chip->pm_max_irq = 0;
-	chip->pm_max_blocks = 0;
-	chip->pm_max_masters = 0;
-
-	platform_set_drvdata(pdev, chip);
-
-	pmic_chip = chip;
-	spin_lock_init(&chip->pm_lock);
-
-	/* Register for all reserved IRQs */
-	for (i = pdata->irq_base; i < (pdata->irq_base + MAX_PM_IRQ); i++) {
-		irq_set_chip(i, &pm8901_irq_chip);
-		irq_set_handler(i, handle_edge_irq);
-		set_irq_flags(i, IRQF_VALID);
-		irq_set_handler_data(i, (void *)chip);
-	}
-
-	rc = mfd_add_devices(chip->dev, 0, pdata->sub_devices,
-			     pdata->num_subdevs, NULL, 0);
+	rc = pm8901_add_subdevices(pdata, pmic);
 	if (rc) {
-		pr_err("%s: could not add devices %d\n", __func__, rc);
-		return rc;
+		pr_err("Cannot add subdevices rc=%d\n", rc);
+		goto err;
 	}
 
-	rc = request_threaded_irq(pdata->irq, NULL, pm8901_isr_thread,
-			IRQF_ONESHOT | IRQF_DISABLED | pdata->irq_trigger_flags,
-			"pm8901-irq", chip);
-	if (rc)
-		pr_err("%s: could not request irq %d: %d\n", __func__,
-				pdata->irq, rc);
+	return 0;
 
-	rc = pmic8901_dbg_probe(chip);
-	if (rc < 0)
-		pr_err("%s: could not set up debugfs: %d\n", __func__, rc);
-
+err:
+	platform_set_drvdata(pdev, NULL);
+	kfree(pmic);
 	return rc;
 }
 
 static int __devexit pm8901_remove(struct platform_device *pdev)
 {
-	struct	pm8901_chip *chip;
+	struct pm8xxx_drvdata *drvdata;
+	struct pm8901_chip *pmic = NULL;
 
-	chip = platform_get_drvdata(pdev);
-	if (chip) {
-		if (chip->pm_max_irq) {
-			irq_set_irq_wake(chip->pdata.irq, 0);
-			free_irq(chip->pdata.irq, chip);
-		}
-
-		mfd_remove_devices(chip->dev);
-
-		chip->dev = NULL;
-
-		kfree(chip);
+	drvdata = platform_get_drvdata(pdev);
+	if (drvdata)
+		pmic = drvdata->pm_chip_data;
+	if (pmic) {
+		if (pmic->dev)
+			mfd_remove_devices(pmic->dev);
+		if (pmic->irq_chip)
+			pm8xxx_irq_exit(pmic->irq_chip);
+		kfree(pmic->mfd_regulators);
+		kfree(pmic);
 	}
-
-	pmic8901_dbg_remove();
+	platform_set_drvdata(pdev, NULL);
 
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int pm8901_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-	struct	pm8901_chip *chip;
-	int	i;
-	unsigned long	irqsave;
-
-	chip = platform_get_drvdata(pdev);
-
-	for (i = 0; i < MAX_PM_IRQ; i++) {
-		spin_lock_irqsave(&chip->pm_lock, irqsave);
-		if (chip->config[i] && !chip->wake_enable[i]) {
-			if (!((chip->config[i] & PM8901_IRQF_MASK_ALL)
-			      == PM8901_IRQF_MASK_ALL))
-				pm8901_irq_mask(irq_get_irq_data(i +
-							chip->pdata.irq_base));
-		}
-		spin_unlock_irqrestore(&chip->pm_lock, irqsave);
-	}
-
-	if (!chip->count_wakeable)
-		disable_irq(chip->pdata.irq);
-
-	return 0;
-}
-
-static int pm8901_resume(struct platform_device *pdev)
-{
-	struct	pm8901_chip *chip;
-	int	i;
-	unsigned long	irqsave;
-
-	chip = platform_get_drvdata(pdev);
-
-	for (i = 0; i < MAX_PM_IRQ; i++) {
-		spin_lock_irqsave(&chip->pm_lock, irqsave);
-		if (chip->config[i] && !chip->wake_enable[i]) {
-			if (!((chip->config[i] & PM8901_IRQF_MASK_ALL)
-			      == PM8901_IRQF_MASK_ALL))
-				pm8901_irq_unmask(irq_get_irq_data(i +
-							chip->pdata.irq_base));
-		}
-		spin_unlock_irqrestore(&chip->pm_lock, irqsave);
-	}
-
-	if (!chip->count_wakeable)
-		enable_irq(chip->pdata.irq);
-
-	return 0;
-}
-#else
-#define	pm8901_suspend		NULL
-#define	pm8901_resume		NULL
-#endif
-
 static struct platform_driver pm8901_driver = {
 	.probe		= pm8901_probe,
 	.remove		= __devexit_p(pm8901_remove),
@@ -914,15 +401,13 @@
 		.name	= "pm8901-core",
 		.owner	= THIS_MODULE,
 	},
-	.suspend	= pm8901_suspend,
-	.resume		= pm8901_resume,
 };
 
 static int __init pm8901_init(void)
 {
 	return  platform_driver_register(&pm8901_driver);
 }
-arch_initcall(pm8901_init);
+postcore_initcall(pm8901_init);
 
 static void __exit pm8901_exit(void)
 {
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
new file mode 100644
index 0000000..81c6b65
--- /dev/null
+++ b/drivers/misc/tspp.c
@@ -0,0 +1,2019 @@
+/* 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>			/* Needed by all modules */
+#include <linux/kernel.h>			/* Needed for KERN_INFO */
+#include <linux/init.h>				/* Needed for the macros */
+#include <linux/cdev.h>
+#include <linux/err.h>				/* IS_ERR */
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/sched.h>		/* TASK_INTERRUPTIBLE */
+#include <linux/uaccess.h>        /* copy_to_user */
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>          /* kfree, kzalloc */
+#include <linux/wakelock.h>
+#include <linux/io.h>            /* ioXXX */
+#include <linux/ioport.h>		/* XXX_ mem_region */
+#include <linux/dma-mapping.h>		/* dma_XXX */
+#include <linux/delay.h>		/* msleep */
+#include <linux/clk.h>
+#include <linux/poll.h>				/* poll() file op */
+#include <linux/wait.h>				/* wait() macros, sleeping */
+#include <linux/tspp.h>				/* tspp functions */
+#include <linux/bitops.h>        /* BIT() macro */
+#include <mach/sps.h>				/* BAM stuff */
+#include <mach/gpio.h>
+#include <mach/dma.h>
+#include <mach/msm_tspp.h>
+
+#define TSPP_USE_DEBUGFS
+#ifdef TSPP_USE_DEBUGFS
+#include <linux/debugfs.h>
+#endif /* TSPP_USE_DEBUGFS */
+
+/*
+ * General defines
+ */
+#define TSPP_USE_DMA_ALLOC_COHERENT
+#define TSPP_TSIF_INSTANCES            2
+#define TSPP_FILTER_TABLES             3
+#define TSPP_MAX_DEVICES               3
+#define TSPP_NUM_CHANNELS              16
+#define TSPP_NUM_PRIORITIES            16
+#define TSPP_NUM_KEYS                  8
+#define INVALID_CHANNEL                0xFFFFFFFF
+#define TSPP_SPS_DESCRIPTOR_COUNT      32
+#define TSPP_PACKET_LENGTH             188
+#define TSPP_MIN_BUFFER_SIZE           (TSPP_PACKET_LENGTH)
+#define TSPP_MAX_BUFFER_SIZE           (16 * 1024)	 /* maybe allow 64K? */
+#define TSPP_NUM_BUFFERS               16
+#define TSPP_TSIF_DEFAULT_TIME_LIMIT   60
+#define SPS_DESCRIPTOR_SIZE            8
+#define MIN_ACCEPTABLE_BUFFER_COUNT    2
+#define TSPP_DEBUG(msg...)             pr_info(msg)
+
+/*
+ * TSIF register offsets
+ */
+#define TSIF_STS_CTL_OFF               (0x0)
+#define TSIF_TIME_LIMIT_OFF            (0x4)
+#define TSIF_CLK_REF_OFF               (0x8)
+#define TSIF_LPBK_FLAGS_OFF            (0xc)
+#define TSIF_LPBK_DATA_OFF            (0x10)
+#define TSIF_TEST_CTL_OFF             (0x14)
+#define TSIF_TEST_MODE_OFF            (0x18)
+#define TSIF_TEST_RESET_OFF           (0x1c)
+#define TSIF_TEST_EXPORT_OFF          (0x20)
+#define TSIF_TEST_CURRENT_OFF         (0x24)
+
+#define TSIF_DATA_PORT_OFF            (0x100)
+
+/* bits for TSIF_STS_CTL register */
+#define TSIF_STS_CTL_EN_IRQ       BIT(28)
+#define TSIF_STS_CTL_PACK_AVAIL   BIT(27)
+#define TSIF_STS_CTL_1ST_PACKET   BIT(26)
+#define TSIF_STS_CTL_OVERFLOW     BIT(25)
+#define TSIF_STS_CTL_LOST_SYNC    BIT(24)
+#define TSIF_STS_CTL_TIMEOUT      BIT(23)
+#define TSIF_STS_CTL_INV_SYNC     BIT(21)
+#define TSIF_STS_CTL_INV_NULL     BIT(20)
+#define TSIF_STS_CTL_INV_ERROR    BIT(19)
+#define TSIF_STS_CTL_INV_ENABLE   BIT(18)
+#define TSIF_STS_CTL_INV_DATA     BIT(17)
+#define TSIF_STS_CTL_INV_CLOCK    BIT(16)
+#define TSIF_STS_CTL_SPARE        BIT(15)
+#define TSIF_STS_CTL_EN_NULL      BIT(11)
+#define TSIF_STS_CTL_EN_ERROR     BIT(10)
+#define TSIF_STS_CTL_LAST_BIT     BIT(9)
+#define TSIF_STS_CTL_EN_TIME_LIM  BIT(8)
+#define TSIF_STS_CTL_EN_TCR       BIT(7)
+#define TSIF_STS_CTL_TEST_MODE    BIT(6)
+#define TSIF_STS_CTL_EN_DM        BIT(4)
+#define TSIF_STS_CTL_STOP         BIT(3)
+#define TSIF_STS_CTL_START        BIT(0)
+
+/*
+ * TSPP register offsets
+ */
+#define TSPP_RST					0x00
+#define TSPP_CLK_CONTROL		0x04
+#define TSPP_CONFIG				0x08
+#define TSPP_CONTROL				0x0C
+#define TSPP_PS_DISABLE			0x10
+#define TSPP_MSG_IRQ_STATUS	0x14
+#define TSPP_MSG_IRQ_MASK		0x18
+#define TSPP_IRQ_STATUS			0x1C
+#define TSPP_IRQ_MASK			0x20
+#define TSPP_IRQ_CLEAR			0x24
+#define TSPP_PIPE_ERROR_STATUS(_n)	(0x28 + (_n << 2))
+#define TSPP_STATUS				0x68
+#define TSPP_CURR_TSP_HEADER	0x6C
+#define TSPP_CURR_PID_FILTER	0x70
+#define TSPP_SYSTEM_KEY(_n)	(0x74 + (_n << 2))
+#define TSPP_CBC_INIT_VAL(_n)	(0x94 + (_n << 2))
+#define TSPP_DATA_KEY_RESET	0x9C
+#define TSPP_KEY_VALID			0xA0
+#define TSPP_KEY_ERROR			0xA4
+#define TSPP_TEST_CTRL			0xA8
+#define TSPP_VERSION				0xAC
+#define TSPP_GENERICS			0xB0
+#define TSPP_NOP					0xB4
+
+/*
+ * Register bit definitions
+ */
+/* TSPP_RST */
+#define TSPP_RST_RESET                    BIT(0)
+
+/* TSPP_CLK_CONTROL	*/
+#define TSPP_CLK_CONTROL_FORCE_CRYPTO     BIT(9)
+#define TSPP_CLK_CONTROL_FORCE_PES_PL     BIT(8)
+#define TSPP_CLK_CONTROL_FORCE_PES_AF     BIT(7)
+#define TSPP_CLK_CONTROL_FORCE_RAW_CTRL   BIT(6)
+#define TSPP_CLK_CONTROL_FORCE_PERF_CNT   BIT(5)
+#define TSPP_CLK_CONTROL_FORCE_CTX_SEARCH BIT(4)
+#define TSPP_CLK_CONTROL_FORCE_TSP_PROC   BIT(3)
+#define TSPP_CLK_CONTROL_FORCE_CONS_AHB2MEM BIT(2)
+#define TSPP_CLK_CONTROL_FORCE_TS_AHB2MEM BIT(1)
+#define TSPP_CLK_CONTROL_SET_CLKON        BIT(0)
+
+/* TSPP_CONFIG	*/
+#define TSPP_CONFIG_SET_PACKET_LENGTH(_a, _b) (_a = (_a & 0xF0) | \
+((_b & 0xF) << 8))
+#define TSPP_CONFIG_GET_PACKET_LENGTH(_a) ((_a >> 8) & 0xF)
+#define TSPP_CONFIG_DUP_WITH_DISC_EN		BIT(7)
+#define TSPP_CONFIG_PES_SYNC_ERROR_MASK   BIT(6)
+#define TSPP_CONFIG_PS_LEN_ERR_MASK       BIT(5)
+#define TSPP_CONFIG_PS_CONT_ERR_UNSP_MASK BIT(4)
+#define TSPP_CONFIG_PS_CONT_ERR_MASK      BIT(3)
+#define TSPP_CONFIG_PS_DUP_TSP_MASK       BIT(2)
+#define TSPP_CONFIG_TSP_ERR_IND_MASK      BIT(1)
+#define TSPP_CONFIG_TSP_SYNC_ERR_MASK     BIT(0)
+
+/* TSPP_CONTROL */
+#define TSPP_CONTROL_PID_FILTER_LOCK      BIT(5)
+#define TSPP_CONTROL_FORCE_KEY_CALC       BIT(4)
+#define TSPP_CONTROL_TSP_CONS_SRC_DIS     BIT(3)
+#define TSPP_CONTROL_TSP_TSIF1_SRC_DIS    BIT(2)
+#define TSPP_CONTROL_TSP_TSIF0_SRC_DIS    BIT(1)
+#define TSPP_CONTROL_PERF_COUNT_INIT      BIT(0)
+
+/* TSPP_MSG_IRQ_STATUS + TSPP_MSG_IRQ_MASK */
+#define TSPP_MSG_TSPP_IRQ                 BIT(2)
+#define TSPP_MSG_TSIF_1_IRQ               BIT(1)
+#define TSPP_MSG_TSIF_0_IRQ               BIT(0)
+
+/* TSPP_IRQ_STATUS + TSPP_IRQ_MASK + TSPP_IRQ_CLEAR */
+#define TSPP_IRQ_STATUS_TSP_RD_CMPL			BIT(19)
+#define TSPP_IRQ_STATUS_KEY_ERROR			BIT(18)
+#define TSPP_IRQ_STATUS_KEY_SWITCHED_BAD	BIT(17)
+#define TSPP_IRQ_STATUS_KEY_SWITCHED		BIT(16)
+#define TSPP_IRQ_STATUS_PS_BROKEN(_n)		BIT((_n))
+
+/* TSPP_PIPE_ERROR_STATUS */
+#define TSPP_PIPE_PES_SYNC_ERROR				BIT(3)
+#define TSPP_PIPE_PS_LENGTH_ERROR			BIT(2)
+#define TSPP_PIPE_PS_CONTINUITY_ERROR		BIT(1)
+#define TSPP_PIP_PS_LOST_START				BIT(0)
+
+/* TSPP_STATUS			*/
+#define TSPP_STATUS_TSP_PKT_AVAIL			BIT(10)
+#define TSPP_STATUS_TSIF1_DM_REQ				BIT(6)
+#define TSPP_STATUS_TSIF0_DM_REQ				BIT(2)
+#define TSPP_CURR_FILTER_TABLE				BIT(0)
+
+/* TSPP_GENERICS		*/
+#define TSPP_GENERICS_CRYPTO_GEN				BIT(12)
+#define TSPP_GENERICS_MAX_CONS_PIPES		BIT(7)
+#define TSPP_GENERICS_MAX_PIPES				BIT(2)
+#define TSPP_GENERICS_TSIF_1_GEN				BIT(1)
+#define TSPP_GENERICS_TSIF_0_GEN				BIT(0)
+
+/*
+ * TSPP memory regions
+ */
+#define TSPP_PID_FILTER_TABLE0      0x800
+#define TSPP_PID_FILTER_TABLE1      0x880
+#define TSPP_PID_FILTER_TABLE2      0x900
+#define TSPP_GLOBAL_PERFORMANCE     0x980 /* see tspp_global_performance */
+#define TSPP_PIPE_CONTEXT           0x990 /* see tspp_pipe_context */
+#define TSPP_PIPE_PERFORMANCE       0x998 /* see tspp_pipe_performance */
+#define TSPP_TSP_BUFF_WORD(_n)      (0xC10 + (_n << 2))
+#define TSPP_DATA_KEY               0xCD0
+
+#ifdef TSPP_USE_DEBUGFS
+struct debugfs_entry {
+	const char *name;
+	mode_t mode;
+	int offset;
+};
+
+static const struct debugfs_entry debugfs_tsif_regs[] = {
+	{"sts_ctl",             S_IRUGO | S_IWUSR, TSIF_STS_CTL_OFF},
+	{"time_limit",          S_IRUGO | S_IWUSR, TSIF_TIME_LIMIT_OFF},
+	{"clk_ref",             S_IRUGO | S_IWUSR, TSIF_CLK_REF_OFF},
+	{"lpbk_flags",          S_IRUGO | S_IWUSR, TSIF_LPBK_FLAGS_OFF},
+	{"lpbk_data",           S_IRUGO | S_IWUSR, TSIF_LPBK_DATA_OFF},
+	{"test_ctl",            S_IRUGO | S_IWUSR, TSIF_TEST_CTL_OFF},
+	{"test_mode",           S_IRUGO | S_IWUSR, TSIF_TEST_MODE_OFF},
+	{"test_reset",                    S_IWUSR, TSIF_TEST_RESET_OFF},
+	{"test_export",         S_IRUGO | S_IWUSR, TSIF_TEST_EXPORT_OFF},
+	{"test_current",        S_IRUGO,           TSIF_TEST_CURRENT_OFF},
+	{"data_port",           S_IRUSR,           TSIF_DATA_PORT_OFF},
+};
+
+static const struct debugfs_entry debugfs_tspp_regs[] = {
+	{"rst",                 S_IRUGO | S_IWUSR, TSPP_RST},
+	{"clk_control",         S_IRUGO | S_IWUSR, TSPP_CLK_CONTROL},
+	{"config",              S_IRUGO | S_IWUSR, TSPP_CONFIG},
+	{"control",             S_IRUGO | S_IWUSR, TSPP_CONTROL},
+	{"ps_disable",          S_IRUGO | S_IWUSR, TSPP_PS_DISABLE},
+	{"msg_irq_status",      S_IRUGO | S_IWUSR, TSPP_MSG_IRQ_STATUS},
+	{"msg_irq_mask",        S_IRUGO | S_IWUSR, TSPP_MSG_IRQ_MASK},
+	{"irq_status",          S_IRUGO | S_IWUSR, TSPP_IRQ_STATUS},
+	{"irq_mask",            S_IRUGO | S_IWUSR, TSPP_IRQ_MASK},
+	{"irq_clear",           S_IRUGO | S_IWUSR, TSPP_IRQ_CLEAR},
+	/* {"pipe_error_status",S_IRUGO | S_IWUSR, TSPP_PIPE_ERROR_STATUS}, */
+	{"status",              S_IRUGO | S_IWUSR, TSPP_STATUS},
+	{"curr_tsp_header",     S_IRUGO | S_IWUSR, TSPP_CURR_TSP_HEADER},
+	{"curr_pid_filter",     S_IRUGO | S_IWUSR, TSPP_CURR_PID_FILTER},
+	/* {"system_key",       S_IRUGO | S_IWUSR, TSPP_SYSTEM_KEY}, */
+	/* {"cbc_init_val",     S_IRUGO | S_IWUSR, TSPP_CBC_INIT_VAL}, */
+	{"data_key_reset",      S_IRUGO | S_IWUSR, TSPP_DATA_KEY_RESET},
+	{"key_valid",           S_IRUGO | S_IWUSR, TSPP_KEY_VALID},
+	{"key_error",           S_IRUGO | S_IWUSR, TSPP_KEY_ERROR},
+	{"test_ctrl",           S_IRUGO | S_IWUSR, TSPP_TEST_CTRL},
+	{"version",             S_IRUGO | S_IWUSR, TSPP_VERSION},
+	{"generics",            S_IRUGO | S_IWUSR, TSPP_GENERICS},
+	{"pid_filter_table0",   S_IRUGO | S_IWUSR, TSPP_PID_FILTER_TABLE0},
+	{"pid_filter_table1",   S_IRUGO | S_IWUSR, TSPP_PID_FILTER_TABLE1},
+	{"pid_filter_table2",   S_IRUGO | S_IWUSR, TSPP_PID_FILTER_TABLE2},
+	{"global_performance",  S_IRUGO | S_IWUSR, TSPP_GLOBAL_PERFORMANCE},
+	{"pipe_context",        S_IRUGO | S_IWUSR, TSPP_PIPE_CONTEXT},
+	{"pipe_performance",    S_IRUGO | S_IWUSR, TSPP_PIPE_PERFORMANCE},
+	{"data_key",            S_IRUGO | S_IWUSR, TSPP_DATA_KEY}
+};
+
+#endif /* TSPP_USE_DEBUGFS */
+
+struct tspp_pid_filter {
+	u32 filter;			/* see FILTER_ macros */
+	u32 config;			/* see FILTER_ macros */
+};
+
+/* tsp_info */
+#define FILTER_HEADER_ERROR_MASK          BIT(7)
+#define FILTER_TRANS_END_DISABLE          BIT(6)
+#define FILTER_DEC_ON_ERROR_EN            BIT(5)
+#define FILTER_DECRYPT                    BIT(4)
+#define FILTER_HAS_ENCRYPTION(_p)         (_p->config & FILTER_DECRYPT)
+#define FILTER_GET_PIPE_NUMBER0(_p)       (_p->config & 0xF)
+#define FILTER_SET_PIPE_NUMBER0(_p, _b)   (_p->config = \
+			(_p->config & ~0xF) | (_b & 0xF))
+#define FILTER_GET_PIPE_PROCESS0(_p)      ((_p->filter >> 30) & 0x3)
+#define FILTER_SET_PIPE_PROCESS0(_p, _b)  (_p->filter = \
+			(_p->filter & ~(0x3<<30)) | ((_b & 0x3) << 30))
+#define FILTER_GET_PIPE_PID(_p)           ((_p->filter >> 13) & 0x1FFF)
+#define FILTER_SET_PIPE_PID(_p, _b)       (_p->filter = \
+			(_p->filter & ~(0x1FFF<<13)) | ((_b & 0x1FFF) << 13))
+#define FILTER_GET_PID_MASK(_p)           (_p->filter & 0x1FFF)
+#define FILTER_SET_PID_MASK(_p, _b)       (_p->filter = \
+			(_p->filter & ~0x1FFF) | (_b & 0x1FFF))
+#define FILTER_GET_PIPE_PROCESS1(_p)      ((_p->config >> 30) & 0x3)
+#define FILTER_SET_PIPE_PROCESS1(_p, _b)  (_p->config = \
+			(_p->config & ~(0x3<<30)) | ((_b & 0x3) << 30))
+#define FILTER_GET_KEY_NUMBER(_p)         ((_p->config >> 8) & 0x7)
+#define FILTER_SET_KEY_NUMBER(_p, _b)     (_p->config = \
+			(_p->config & ~(0x7<<8)) | ((_b & 0x7) << 8))
+
+struct tspp_global_performance_regs {
+	u32 tsp_total;
+	u32 tsp_ignored;
+	u32 tsp_error;
+	u32 tsp_sync;
+};
+
+struct tspp_pipe_context_regs {
+	u16 pes_bytes_left;
+	u16 count;
+	u32 tsif_suffix;
+} __packed;
+#define CONTEXT_GET_STATE(_a)					(_a & 0x3)
+#define CONTEXT_UNSPEC_LENGTH					BIT(11)
+#define CONTEXT_GET_CONT_COUNT(_a)			((_a >> 12) & 0xF)
+
+struct tspp_pipe_performance_regs {
+	u32 tsp_total;
+	u32 ps_duplicate_tsp;
+	u32 tsp_no_payload;
+	u32 tsp_broken_ps;
+	u32 ps_total_num;
+	u32 ps_continuity_error;
+	u32 ps_length_error;
+	u32 pes_sync_error;
+};
+
+struct tspp_tsif_device {
+	void __iomem *base;
+	u32 time_limit;
+	u32 ref_count;
+
+	/* debugfs */
+#ifdef TSPP_USE_DEBUGFS
+	struct dentry *dent_tsif;
+	struct dentry *debugfs_tsif_regs[ARRAY_SIZE(debugfs_tsif_regs)];
+#endif /* TSPP_USE_DEBUGFS */
+};
+
+/* this represents the actual hardware device */
+struct tspp_device {
+	struct platform_device *pdev;
+	void __iomem *base;
+	unsigned int tspp_irq;
+	unsigned int bam_irq;
+	u32 bam_handle;
+	struct sps_bam_props bam_props;
+	struct wake_lock wake_lock;
+	spinlock_t spinlock;
+	struct tasklet_struct tlet;
+	struct tspp_tsif_device tsif[TSPP_TSIF_INSTANCES];
+	/* clocks */
+	struct clk *tsif_pclk;
+	struct clk *tsif_ref_clk;
+
+#ifdef TSPP_USE_DEBUGFS
+	struct dentry *dent;
+	struct dentry *debugfs_regs[ARRAY_SIZE(debugfs_tspp_regs)];
+#endif /* TSPP_USE_DEBUGFS */
+};
+
+enum tspp_buf_state {
+	TSPP_BUF_STATE_EMPTY,	/* buffer has been allocated, but not waiting */
+	TSPP_BUF_STATE_WAITING, /* buffer is waiting to be filled */
+	TSPP_BUF_STATE_DATA     /* buffer is not empty and can be read */
+};
+
+struct tspp_mem_buffer {
+	struct sps_mem_buffer mem;
+	enum tspp_buf_state state;
+	size_t filled;          /* how much data this buffer is holding */
+	int read_index;         /* where to start reading data from */
+};
+
+/* this represents each char device 'channel' */
+struct tspp_channel {
+	struct cdev cdev;
+	struct device *dd;
+	struct tspp_device *pdev;
+	struct sps_pipe *pipe;
+	struct sps_connect config;
+	struct sps_register_event event;
+	struct tspp_mem_buffer buffer[TSPP_NUM_BUFFERS];
+	wait_queue_head_t in_queue; /* set when data is received */
+	int read;  /* index into mem showing buffers ready to be read by user */
+	int waiting;	/* index into mem showing outstanding transfers */
+	int id;			/* channel id (0-15) */
+	int used;		/* is this channel in use? */
+	int key;			/* which encryption key index is used */
+	u32 bufsize;	/* size of the sps transfer buffers */
+	int buffer_count; /* how many buffers are actually allocated */
+	int filter_count; /* how many filters have been added to this channel */
+	enum tspp_source src;
+	enum tspp_mode mode;
+};
+
+struct tspp_pid_filter_table {
+	struct tspp_pid_filter filter[TSPP_NUM_PRIORITIES];
+};
+
+struct tspp_key_entry {
+	u32 even_lsb;
+	u32 even_msb;
+	u32 odd_lsb;
+	u32 odd_msb;
+};
+
+struct tspp_key_table {
+	struct tspp_key_entry entry[TSPP_NUM_KEYS];
+};
+
+static struct tspp_pid_filter_table *tspp_filter_table[TSPP_FILTER_TABLES];
+static struct tspp_channel channel_list[TSPP_NUM_CHANNELS];
+static struct tspp_key_table *tspp_key_table;
+static struct tspp_global_performance_regs *tspp_global_performance;
+static struct tspp_pipe_context_regs *tspp_pipe_context;
+static struct tspp_pipe_performance_regs *tspp_pipe_performance;
+static struct class *tspp_class;
+static int tspp_key_entry;
+static dev_t tspp_minor;  /* next minor number to assign */
+static int loopback_mode; /* put tsif interfaces into loopback mode */
+
+/*** IRQ ***/
+static irqreturn_t tspp_isr(int irq, void *dev_id)
+{
+	struct tspp_device *device = dev_id;
+	u32 status, mask;
+	u32 data;
+
+	status = readl_relaxed(device->base + TSPP_IRQ_STATUS);
+	mask = readl_relaxed(device->base + TSPP_IRQ_MASK);
+	status &= mask;
+
+	if (!status) {
+		dev_warn(&device->pdev->dev, "Spurious interrupt");
+		return IRQ_NONE;
+	}
+
+	/* if (status & TSPP_IRQ_STATUS_TSP_RD_CMPL) */
+
+	if (status & TSPP_IRQ_STATUS_KEY_ERROR) {
+		/* read the key error info */
+		data = readl_relaxed(device->base + TSPP_KEY_ERROR);
+		dev_info(&device->pdev->dev, "key error 0x%x", data);
+	}
+	if (status & TSPP_IRQ_STATUS_KEY_SWITCHED_BAD) {
+		data = readl_relaxed(device->base + TSPP_KEY_VALID);
+		dev_info(&device->pdev->dev, "key invalidated: 0x%x", data);
+	}
+	if (status & TSPP_IRQ_STATUS_KEY_SWITCHED)
+		dev_info(&device->pdev->dev, "key switched");
+
+	if (status & 0xffff)
+		dev_info(&device->pdev->dev, "broken pipe");
+
+	writel_relaxed(status, device->base + TSPP_IRQ_CLEAR);
+	wmb();
+	return IRQ_HANDLED;
+}
+
+/*** callbacks ***/
+static void tspp_sps_complete_cb(struct sps_event_notify *notify)
+{
+	struct tspp_channel *channel = notify->user;
+	tasklet_schedule(&channel->pdev->tlet);
+}
+
+/*** tasklet ***/
+static void tspp_sps_complete_tlet(unsigned long data)
+{
+	int i;
+	int complete;
+	unsigned long flags;
+	struct sps_iovec iovec;
+	struct tspp_channel *channel;
+	struct tspp_device *device = (struct tspp_device *)data;
+	struct tspp_mem_buffer *buffer;
+
+	spin_lock_irqsave(&device->spinlock, flags);
+
+	for (i = 0; i < TSPP_NUM_CHANNELS; i++) {
+		complete = 0;
+		channel = &channel_list[i];
+		buffer = &channel->buffer[channel->waiting];
+
+		/* get completions */
+		if (buffer->state == TSPP_BUF_STATE_WAITING) {
+			if (sps_get_iovec(channel->pipe, &iovec) != 0) {
+				pr_err("tspp: Error in iovec on channel %i",
+					channel->id);
+				break;
+			}
+			if (iovec.size == 0)
+				break;
+
+			if (iovec.addr != buffer->mem.phys_base)
+				pr_err("tspp: buffer mismatch 0x%08x",
+					buffer->mem.phys_base);
+
+			complete = 1;
+			buffer->state = TSPP_BUF_STATE_DATA;
+			buffer->filled = iovec.size;
+			buffer->read_index = 0;
+			channel->waiting++;
+			if (channel->waiting == TSPP_NUM_BUFFERS)
+				channel->waiting = 0;
+		}
+
+		if (complete) {
+			/* wake any waiting processes */
+			wake_up_interruptible(&channel->in_queue);
+		}
+	}
+
+	spin_unlock_irqrestore(&device->spinlock, flags);
+}
+
+/*** GPIO functions ***/
+static void tspp_gpios_free(const struct msm_gpio *table, int size)
+{
+	int i;
+	const struct msm_gpio *g;
+	for (i = size-1; i >= 0; i--) {
+		g = table + i;
+		gpio_free(GPIO_PIN(g->gpio_cfg));
+	}
+}
+
+static int tspp_gpios_request(const struct msm_gpio *table, int size)
+{
+	int rc;
+	int i;
+	const struct msm_gpio *g;
+	for (i = 0; i < size; i++) {
+		g = table + i;
+		rc = gpio_request(GPIO_PIN(g->gpio_cfg), g->label);
+		if (rc) {
+			pr_err("tspp: gpio_request(%d) <%s> failed: %d\n",
+			       GPIO_PIN(g->gpio_cfg), g->label ?: "?", rc);
+			goto err;
+		}
+	}
+	return 0;
+err:
+	tspp_gpios_free(table, i);
+	return rc;
+}
+
+static int tspp_gpios_disable(const struct msm_gpio *table, int size)
+{
+	int rc = 0;
+	int i;
+	const struct msm_gpio *g;
+	for (i = size-1; i >= 0; i--) {
+		int tmp;
+		g = table + i;
+		tmp = gpio_tlmm_config(g->gpio_cfg, GPIO_CFG_DISABLE);
+		if (tmp) {
+			pr_err("tspp_gpios_disable(0x%08x, GPIO_CFG_DISABLE)"
+			       " <%s> failed: %d\n",
+			       g->gpio_cfg, g->label ?: "?", rc);
+			pr_err("tspp: pin %d func %d dir %d pull %d drvstr %d\n",
+			       GPIO_PIN(g->gpio_cfg), GPIO_FUNC(g->gpio_cfg),
+			       GPIO_DIR(g->gpio_cfg), GPIO_PULL(g->gpio_cfg),
+			       GPIO_DRVSTR(g->gpio_cfg));
+			if (!rc)
+				rc = tmp;
+		}
+	}
+
+	return rc;
+}
+
+static int tspp_gpios_enable(const struct msm_gpio *table, int size)
+{
+	int rc;
+	int i;
+	const struct msm_gpio *g;
+	for (i = 0; i < size; i++) {
+		g = table + i;
+		rc = gpio_tlmm_config(g->gpio_cfg, GPIO_CFG_ENABLE);
+		if (rc) {
+			pr_err("tspp: gpio_tlmm_config(0x%08x, GPIO_CFG_ENABLE)"
+			       " <%s> failed: %d\n",
+			       g->gpio_cfg, g->label ?: "?", rc);
+			pr_err("tspp: pin %d func %d dir %d pull %d drvstr %d\n",
+			       GPIO_PIN(g->gpio_cfg), GPIO_FUNC(g->gpio_cfg),
+			       GPIO_DIR(g->gpio_cfg), GPIO_PULL(g->gpio_cfg),
+			       GPIO_DRVSTR(g->gpio_cfg));
+			goto err;
+		}
+	}
+	return 0;
+err:
+	tspp_gpios_disable(table, i);
+	return rc;
+}
+
+static int tspp_gpios_request_enable(const struct msm_gpio *table, int size)
+{
+	int rc = tspp_gpios_request(table, size);
+	if (rc)
+		return rc;
+	rc = tspp_gpios_enable(table, size);
+	if (rc)
+		tspp_gpios_free(table, size);
+	return rc;
+}
+
+static void tspp_gpios_disable_free(const struct msm_gpio *table, int size)
+{
+	tspp_gpios_disable(table, size);
+	tspp_gpios_free(table, size);
+}
+
+static int tspp_start_gpios(struct tspp_device *device)
+{
+	struct msm_tspp_platform_data *pdata =
+		device->pdev->dev.platform_data;
+	return tspp_gpios_request_enable(pdata->gpios, pdata->num_gpios);
+}
+
+static void tspp_stop_gpios(struct tspp_device *device)
+{
+	struct msm_tspp_platform_data *pdata =
+		device->pdev->dev.platform_data;
+	tspp_gpios_disable_free(pdata->gpios, pdata->num_gpios);
+}
+
+/*** TSIF functions ***/
+static int tspp_start_tsif(struct tspp_tsif_device *tsif_device)
+{
+	int start_hardware = 0;
+	u32 ctl;
+
+	if (tsif_device->ref_count == 0) {
+		start_hardware = 1;
+	} else if (tsif_device->ref_count > 0) {
+		ctl = readl_relaxed(tsif_device->base + TSIF_STS_CTL_OFF);
+		if ((ctl & TSIF_STS_CTL_START) != 1) {
+			/* this hardware should already be running */
+			pr_warn("tspp: tsif hw not started but ref count > 0");
+			start_hardware = 1;
+		}
+	}
+
+	if (start_hardware) {
+		if (loopback_mode) {
+			ctl = TSIF_STS_CTL_EN_IRQ |
+				TSIF_STS_CTL_EN_NULL |
+				TSIF_STS_CTL_EN_ERROR |
+				TSIF_STS_CTL_TEST_MODE |
+				TSIF_STS_CTL_EN_DM;
+	TSPP_DEBUG("tspp: starting tsif hw in loopback mode 0x%x", ctl);
+		} else {
+			ctl = TSIF_STS_CTL_EN_IRQ |
+				TSIF_STS_CTL_EN_TIME_LIM |
+				TSIF_STS_CTL_EN_TCR |
+				TSIF_STS_CTL_EN_DM;
+		}
+		writel_relaxed(ctl, tsif_device->base + TSIF_STS_CTL_OFF);
+		writel_relaxed(tsif_device->time_limit,
+			  tsif_device->base + TSIF_TIME_LIMIT_OFF);
+		wmb();
+		writel_relaxed(ctl | TSIF_STS_CTL_START,
+			  tsif_device->base + TSIF_STS_CTL_OFF);
+		wmb();
+		ctl = readl_relaxed(tsif_device->base + TSIF_STS_CTL_OFF);
+	}
+
+	tsif_device->ref_count++;
+
+	return (ctl & TSIF_STS_CTL_START) ? 0 : -EFAULT;
+}
+
+static void tspp_stop_tsif(struct tspp_tsif_device *tsif_device)
+{
+	if (tsif_device->ref_count == 0)
+		return;
+
+	tsif_device->ref_count--;
+
+	if (tsif_device->ref_count == 0) {
+		writel_relaxed(TSIF_STS_CTL_STOP,
+			tsif_device->base + TSIF_STS_CTL_OFF);
+		wmb();
+	}
+}
+
+/*** TSPP functions ***/
+static int tspp_get_key_entry(void)
+{
+	int i;
+	for (i = 0; i < TSPP_NUM_KEYS; i++) {
+		if (!(tspp_key_entry & (1 << i))) {
+			tspp_key_entry |= (1 << i);
+			return i;
+		}
+	}
+	return 1;
+}
+
+static void tspp_free_key_entry(int entry)
+{
+	if (entry > TSPP_NUM_KEYS) {
+		pr_err("tspp_free_key_entry: index out of bounds");
+		return;
+	}
+
+	tspp_key_entry &= ~(1 << entry);
+}
+
+static int tspp_alloc_buffer(struct sps_mem_buffer *mem,
+	struct tspp_channel *channel)
+{
+	if (channel->bufsize < TSPP_MIN_BUFFER_SIZE ||
+		channel->bufsize > TSPP_MAX_BUFFER_SIZE) {
+		pr_err("tspp: bad buffer size");
+		return 1;
+	}
+
+	switch (channel->mode) {
+	case TSPP_MODE_DISABLED:
+		mem->size = 0;
+		pr_err("tspp: channel is disabled");
+		return 1;
+
+	case TSPP_MODE_PES:
+		/* give the user what he asks for */
+		mem->size = channel->bufsize;
+		break;
+
+	case TSPP_MODE_RAW:
+		/* must be a multiple of 192 */
+		if (channel->bufsize < (TSPP_PACKET_LENGTH+4))
+			mem->size = (TSPP_PACKET_LENGTH+4);
+		else
+			mem->size = (channel->bufsize /
+				(TSPP_PACKET_LENGTH+4)) *
+				(TSPP_PACKET_LENGTH+4);
+		break;
+
+	case TSPP_MODE_RAW_NO_SUFFIX:
+		/* must be a multiple of 188 */
+		mem->size = (channel->bufsize / TSPP_PACKET_LENGTH) *
+			TSPP_PACKET_LENGTH;
+		break;
+	}
+
+#ifdef TSPP_USE_DMA_ALLOC_COHERENT
+	mem->base = dma_alloc_coherent(NULL, mem->size,
+		&mem->phys_base, GFP_KERNEL);
+	if (mem->base == 0) {
+		pr_err("tspp dma alloc coherent failed %i", mem->size);
+		return -ENOMEM;
+	}
+#else
+	mem->base = kmalloc(mem->size, GFP_KERNEL);
+	if (mem->base == 0) {
+		pr_err("tspp buffer allocation failed %i", mem->size);
+		return -ENOMEM;
+	}
+	mem->phys_base = dma_map_single(NULL,
+		mem->base,
+		mem->size,
+		DMA_FROM_DEVICE);
+#endif
+
+	return 0;
+}
+
+static int tspp_global_reset(struct tspp_device *pdev)
+{
+	u32 i, val;
+
+	/* stop all TSIFs */
+	for (i = 0; i < TSPP_TSIF_INSTANCES; i++) {
+		pdev->tsif[i].ref_count = 1; /* allows stopping hw */
+		tspp_stop_tsif(&pdev->tsif[i]); /* will reset ref_count to 0 */
+		pdev->tsif[i].time_limit = TSPP_TSIF_DEFAULT_TIME_LIMIT;
+	}
+	writel_relaxed(TSPP_RST_RESET, pdev->base + TSPP_RST);
+	wmb();
+
+	/* BAM */
+	if (sps_device_reset(pdev->bam_handle) != 0) {
+		pr_err("tspp: error resetting bam");
+		return 1;
+	}
+
+	/* TSPP tables */
+	for (i = 0; i < TSPP_FILTER_TABLES; i++)
+		memset(tspp_filter_table[i],
+			0, sizeof(struct tspp_pid_filter_table));
+
+	/* disable all filters */
+	val = (2 << TSPP_NUM_CHANNELS) - 1;
+	writel_relaxed(val, pdev->base + TSPP_PS_DISABLE);
+
+	/* TSPP registers */
+	val = readl_relaxed(pdev->base + TSPP_CONTROL);
+	writel_relaxed(val | TSPP_CLK_CONTROL_FORCE_PERF_CNT,
+		pdev->base + TSPP_CONTROL);
+	wmb();
+	memset(tspp_global_performance, 0,
+		sizeof(struct tspp_global_performance_regs));
+	memset(tspp_pipe_context, 0,
+		sizeof(struct tspp_pipe_context_regs));
+	memset(tspp_pipe_performance, 0,
+		sizeof(struct tspp_pipe_performance_regs));
+	wmb();
+	writel_relaxed(val & ~TSPP_CLK_CONTROL_FORCE_PERF_CNT,
+		pdev->base + TSPP_CONTROL);
+	wmb();
+
+	val = readl_relaxed(pdev->base + TSPP_CONFIG);
+	val &= ~(TSPP_CONFIG_PS_LEN_ERR_MASK |
+			TSPP_CONFIG_PS_CONT_ERR_UNSP_MASK |
+			TSPP_CONFIG_PS_CONT_ERR_MASK);
+	TSPP_CONFIG_SET_PACKET_LENGTH(val, TSPP_PACKET_LENGTH);
+	writel_relaxed(val, pdev->base + TSPP_CONFIG);
+	writel_relaxed(0x000fffff, pdev->base + TSPP_IRQ_MASK);
+	writel_relaxed(0x000fffff, pdev->base + TSPP_IRQ_CLEAR);
+	writel_relaxed(0, pdev->base + TSPP_RST);
+	wmb();
+
+	tspp_key_entry = 0;
+
+	return 0;
+}
+
+int tspp_open_stream(struct tspp_channel *channel, enum tspp_source src)
+{
+	u32 val;
+	struct tspp_device *pdev;
+
+	if (!channel)
+		return 1;
+
+	pdev = channel->pdev;
+
+	switch (src) {
+	case TSPP_SOURCE_TSIF0:
+		/* make sure TSIF0 is running & enabled */
+		if (tspp_start_tsif(&pdev->tsif[0]) != 0) {
+			pr_err("tspp: error starting tsif0");
+			return 1;
+		}
+		val = readl_relaxed(pdev->base + TSPP_CONTROL);
+		writel_relaxed(val & ~TSPP_CONTROL_TSP_TSIF0_SRC_DIS,
+			pdev->base + TSPP_CONTROL);
+		wmb();
+		break;
+	case TSPP_SOURCE_TSIF1:
+		/* make sure TSIF1 is running & enabled */
+		if (tspp_start_tsif(&pdev->tsif[1]) != 0) {
+			pr_err("tspp: error starting tsif1");
+			return 1;
+		}
+		val = readl_relaxed(pdev->base + TSPP_CONTROL);
+		writel_relaxed(val & ~TSPP_CONTROL_TSP_TSIF1_SRC_DIS,
+			pdev->base + TSPP_CONTROL);
+		wmb();
+		break;
+	case TSPP_SOURCE_MEM:
+		break;
+	default:
+		pr_warn("tspp: channel %i invalid source %i", channel->id, src);
+		return 1;
+	}
+
+	channel->src = src;
+
+	return 0;
+}
+EXPORT_SYMBOL(tspp_open_stream);
+
+int tspp_close_stream(struct tspp_channel *channel)
+{
+	u32 val;
+	struct tspp_device *pdev;
+
+	pdev = channel->pdev;
+
+	switch (channel->src) {
+	case TSPP_SOURCE_TSIF0:
+		tspp_stop_tsif(&pdev->tsif[0]);
+		val = readl_relaxed(pdev->base + TSPP_CONTROL);
+		writel_relaxed(val | TSPP_CONTROL_TSP_TSIF0_SRC_DIS,
+			pdev->base + TSPP_CONTROL);
+		wmb();
+		break;
+	case TSPP_SOURCE_TSIF1:
+		tspp_stop_tsif(&pdev->tsif[1]);
+		val = readl_relaxed(pdev->base + TSPP_CONTROL);
+		writel_relaxed(val | TSPP_CONTROL_TSP_TSIF1_SRC_DIS,
+			pdev->base + TSPP_CONTROL);
+		break;
+	case TSPP_SOURCE_MEM:
+		break;
+	case TSPP_SOURCE_NONE:
+		break;
+	}
+
+	channel->src = -1;
+	return 0;
+}
+EXPORT_SYMBOL(tspp_close_stream);
+
+int tspp_open_channel(struct tspp_channel *channel)
+{
+	int rc = 0;
+	struct sps_connect *config = &channel->config;
+	struct sps_register_event *event = &channel->event;
+
+	if (channel->used) {
+		pr_err("tspp channel already in use");
+		return 1;
+	}
+
+	/* mark it as used */
+	channel->used = 1;
+
+	/* start the bam  */
+	channel->pipe = sps_alloc_endpoint();
+	if (channel->pipe == 0) {
+		pr_err("tspp: error allocating endpoint");
+		rc = -ENOMEM;
+		goto err_sps_alloc;
+	}
+
+	/* get default configuration */
+	sps_get_config(channel->pipe, config);
+
+	config->source = channel->pdev->bam_handle;
+	config->destination = SPS_DEV_HANDLE_MEM;
+	config->mode = SPS_MODE_SRC;
+	config->options = SPS_O_AUTO_ENABLE |
+		SPS_O_EOT | SPS_O_ACK_TRANSFERS;
+	config->src_pipe_index = channel->id;
+	config->desc.size =
+		(TSPP_SPS_DESCRIPTOR_COUNT + 1) * SPS_DESCRIPTOR_SIZE;
+	config->desc.base = dma_alloc_coherent(NULL,
+						config->desc.size,
+						&config->desc.phys_base,
+						GFP_KERNEL);
+	if (config->desc.base == 0) {
+		pr_err("tspp: error allocating sps descriptors");
+		rc = -ENOMEM;
+		goto err_desc_alloc;
+	}
+
+	memset(config->desc.base, 0, config->desc.size);
+
+	rc = sps_connect(channel->pipe, config);
+	if (rc) {
+		pr_err("tspp: error connecting bam");
+		goto err_connect;
+	}
+
+	event->mode = SPS_TRIGGER_CALLBACK;
+	event->options = SPS_O_EOT;
+	event->callback = tspp_sps_complete_cb;
+	event->xfer_done = NULL;
+	event->user = channel;
+
+	rc = sps_register_event(channel->pipe, event);
+	if (rc) {
+		pr_err("tspp: error registering event");
+		goto err_event;
+	}
+
+	rc = pm_runtime_get(&channel->pdev->pdev->dev);
+	if (rc < 0) {
+		dev_err(&channel->pdev->pdev->dev,
+			"Runtime PM: Unable to wake up tspp device, rc = %d",
+			rc);
+	}
+
+	wake_lock(&channel->pdev->wake_lock);
+	return 0;
+
+err_event:
+	sps_disconnect(channel->pipe);
+err_connect:
+	dma_free_coherent(NULL, config->desc.size, config->desc.base,
+		config->desc.phys_base);
+err_desc_alloc:
+	sps_free_endpoint(channel->pipe);
+err_sps_alloc:
+	return rc;
+}
+EXPORT_SYMBOL(tspp_open_channel);
+
+int tspp_close_channel(struct tspp_channel *channel)
+{
+	int i;
+	int id;
+	u32 val;
+	struct sps_connect *config = &channel->config;
+	struct tspp_device *pdev = channel->pdev;
+
+	TSPP_DEBUG("tspp_close_channel");
+	channel->used = 0;
+
+	/* disable pipe (channel) */
+	val = readl_relaxed(pdev->base + TSPP_PS_DISABLE);
+	writel_relaxed(val | channel->id, pdev->base + TSPP_PS_DISABLE);
+	wmb();
+
+	/* unregister all filters for this channel */
+	for (i = 0; i < TSPP_NUM_PRIORITIES; i++) {
+		struct tspp_pid_filter *tspp_filter =
+			&tspp_filter_table[channel->src]->filter[i];
+		id = FILTER_GET_PIPE_NUMBER0(tspp_filter);
+		if (id == channel->id) {
+			if (FILTER_HAS_ENCRYPTION(tspp_filter))
+				tspp_free_key_entry(
+					FILTER_GET_KEY_NUMBER(tspp_filter));
+			tspp_filter->config = 0;
+			tspp_filter->filter = 0;
+		}
+	}
+	channel->filter_count = 0;
+
+	/* stop the stream */
+	tspp_close_stream(channel);
+
+	/* disconnect the bam */
+	if (sps_disconnect(channel->pipe) != 0)
+		pr_warn("tspp: Error freeing sps endpoint (%i)", channel->id);
+
+	/* destroy the buffers */
+	dma_free_coherent(NULL, config->desc.size, config->desc.base,
+		config->desc.phys_base);
+
+	for (i = 0; i < TSPP_NUM_BUFFERS; i++) {
+		if (channel->buffer[i].mem.phys_base) {
+#ifdef TSPP_USE_DMA_ALLOC_COHERENT
+			dma_free_coherent(NULL,
+				channel->buffer[i].mem.size,
+				channel->buffer[i].mem.base,
+				channel->buffer[i].mem.phys_base);
+#else
+			dma_unmap_single(channel->dd,
+			channel->buffer[i].mem.phys_base,
+			channel->buffer[i].mem.size,
+			0);
+			kfree(channel->buffer[i].mem.base);
+#endif
+			channel->buffer[i].mem.phys_base = 0;
+		}
+		channel->buffer[i].mem.base = 0;
+		channel->buffer[i].state = TSPP_BUF_STATE_EMPTY;
+	}
+	channel->buffer_count = 0;
+
+	wake_unlock(&channel->pdev->wake_lock);
+	return 0;
+}
+EXPORT_SYMBOL(tspp_close_channel);
+
+/* picks a stream for this channel */
+int tspp_select_source(struct tspp_channel *channel,
+	struct tspp_select_source *src)
+{
+	/* make sure the requested src id is in bounds */
+	if (src->source > TSPP_SOURCE_MEM) {
+		pr_err("tspp source out of bounds");
+		return 1;
+	}
+
+	/* open the stream */
+	tspp_open_stream(channel, src->source);
+
+	return 0;
+}
+EXPORT_SYMBOL(tspp_select_source);
+
+int tspp_add_filter(struct tspp_channel *channel,
+	struct tspp_filter *filter)
+{
+	int i;
+	int other_channel;
+	int entry;
+	u32 val, pid, enabled;
+	struct tspp_device *pdev = channel->pdev;
+	struct tspp_pid_filter p;
+
+	TSPP_DEBUG("tspp_add_filter");
+	if (filter->source > TSPP_SOURCE_MEM) {
+		pr_err("tspp invalid source");
+		return 1;
+	}
+
+	if (filter->priority >= TSPP_NUM_PRIORITIES) {
+		pr_err("tspp invalid source");
+		return 1;
+	}
+
+	/* make sure this filter mode matches the channel mode */
+	switch (channel->mode) {
+	case TSPP_MODE_DISABLED:
+		channel->mode = filter->mode;
+		break;
+	case TSPP_MODE_RAW:
+	case TSPP_MODE_PES:
+	case TSPP_MODE_RAW_NO_SUFFIX:
+		if (filter->mode != channel->mode) {
+			pr_err("tspp: wrong filter mode");
+			return 1;
+		}
+	}
+
+	if (filter->mode == TSPP_MODE_PES) {
+		for (i = 0; i < TSPP_NUM_PRIORITIES; i++) {
+			struct tspp_pid_filter *tspp_filter =
+				&tspp_filter_table[channel->src]->filter[i];
+			pid = FILTER_GET_PIPE_PID((tspp_filter));
+			enabled = FILTER_GET_PIPE_PROCESS0(tspp_filter);
+			if (enabled && (pid == filter->pid)) {
+				other_channel =
+					FILTER_GET_PIPE_NUMBER0(tspp_filter);
+				pr_err("tspp: pid 0x%x already in use by channel %i",
+					filter->pid, other_channel);
+				return 1;
+			}
+		}
+	}
+
+	/* make sure this priority is not already in use */
+	enabled = FILTER_GET_PIPE_PROCESS0(
+		(&(tspp_filter_table[channel->src]->filter[filter->priority])));
+	if (enabled) {
+		pr_err("tspp: filter priority %i source %i is already enabled\n",
+			filter->priority, channel->src);
+		return 1;
+	}
+
+	if (channel->mode == TSPP_MODE_PES) {
+		/* if we are already processing in PES mode, disable pipe
+		(channel) and filter to be updated */
+		val = readl_relaxed(pdev->base + TSPP_PS_DISABLE);
+		writel_relaxed(val | (1 << channel->id),
+			pdev->base + TSPP_PS_DISABLE);
+		wmb();
+	}
+
+	/* update entry */
+	p.filter = 0;
+	p.config = 0;
+	FILTER_SET_PIPE_PROCESS0((&p), filter->mode);
+	FILTER_SET_PIPE_PID((&p), filter->pid);
+	FILTER_SET_PID_MASK((&p), filter->mask);
+	FILTER_SET_PIPE_NUMBER0((&p), channel->id);
+	FILTER_SET_PIPE_PROCESS1((&p), TSPP_MODE_DISABLED);
+	if (filter->decrypt) {
+		entry = tspp_get_key_entry();
+		if (entry == -1) {
+			pr_err("tspp: no more keys available!");
+		} else {
+			p.config |= FILTER_DECRYPT;
+			FILTER_SET_KEY_NUMBER((&p), entry);
+		}
+	}
+	TSPP_DEBUG("tspp_add_filter: mode=%i pid=%i mask=%i channel=%i",
+		filter->mode, filter->pid, filter->mask, channel->id);
+
+	tspp_filter_table[channel->src]->
+		filter[filter->priority].config = p.config;
+	tspp_filter_table[channel->src]->
+		filter[filter->priority].filter = p.filter;
+
+	/* reenable pipe */
+	val = readl_relaxed(pdev->base + TSPP_PS_DISABLE);
+	writel_relaxed(val & ~(1 << channel->id), pdev->base + TSPP_PS_DISABLE);
+	wmb();
+	val = readl_relaxed(pdev->base + TSPP_PS_DISABLE);
+
+	/* allocate buffers if needed */
+	if (channel->buffer_count == 0) {
+		TSPP_DEBUG("tspp: no buffers need %i", TSPP_NUM_BUFFERS);
+		for (i = 0; i < TSPP_NUM_BUFFERS; i++) {
+			if (tspp_alloc_buffer(&channel->buffer[i].mem,
+				channel) != 0) {
+				pr_warn("tspp: Can't allocate buffer %i", i);
+			} else {
+				channel->buffer[i].filled = 0;
+				channel->buffer[i].read_index = 0;
+				channel->buffer_count++;
+
+				/* start the transfer */
+				if (sps_transfer_one(channel->pipe,
+					channel->buffer[i].mem.phys_base,
+					channel->buffer[i].mem.size,
+					channel,
+					SPS_IOVEC_FLAG_INT |
+					SPS_IOVEC_FLAG_EOB))
+					pr_err("tspp: can't submit transfer");
+				else
+					channel->buffer[i].state =
+						TSPP_BUF_STATE_WAITING;
+			}
+		}
+	}
+
+	if (channel->buffer_count < MIN_ACCEPTABLE_BUFFER_COUNT) {
+		pr_err("failed to allocate at least %i buffers",
+			MIN_ACCEPTABLE_BUFFER_COUNT);
+		return -ENOMEM;
+	}
+
+	channel->filter_count++;
+
+	return 0;
+}
+EXPORT_SYMBOL(tspp_add_filter);
+
+int tspp_remove_filter(struct tspp_channel *channel,
+	struct tspp_filter *filter)
+{
+	int entry;
+	u32 val;
+	struct tspp_device *pdev = channel->pdev;
+	int src = channel->src;
+	struct tspp_pid_filter *tspp_filter =
+		&(tspp_filter_table[src]->filter[filter->priority]);
+
+	/* disable pipe (channel) */
+	val = readl_relaxed(pdev->base + TSPP_PS_DISABLE);
+	writel_relaxed(val | channel->id, pdev->base + TSPP_PS_DISABLE);
+	wmb();
+
+	/* update data keys */
+	if (tspp_filter->config & FILTER_DECRYPT) {
+		entry = FILTER_GET_KEY_NUMBER(tspp_filter);
+		tspp_free_key_entry(entry);
+	}
+
+	/* update pid table */
+	tspp_filter->config = 0;
+	tspp_filter->filter = 0;
+
+	channel->filter_count--;
+
+	/* reenable pipe */
+	val = readl_relaxed(pdev->base + TSPP_PS_DISABLE);
+	writel_relaxed(val & ~(1 << channel->id),
+		pdev->base + TSPP_PS_DISABLE);
+	wmb();
+	val = readl_relaxed(pdev->base + TSPP_PS_DISABLE);
+
+	return 0;
+}
+EXPORT_SYMBOL(tspp_remove_filter);
+
+int tspp_set_key(struct tspp_channel *channel, struct tspp_key* key)
+{
+	int i;
+	int id;
+	int key_index;
+	int data;
+
+	/* read the key index used by this channel */
+	for (i = 0; i < TSPP_NUM_PRIORITIES; i++) {
+		struct tspp_pid_filter *tspp_filter =
+			&(tspp_filter_table[channel->src]->filter[i]);
+		id = FILTER_GET_PIPE_NUMBER0(tspp_filter);
+		if (id == channel->id) {
+			if (FILTER_HAS_ENCRYPTION(tspp_filter)) {
+				key_index = FILTER_GET_KEY_NUMBER(tspp_filter);
+				break;
+			}
+		}
+	}
+	if (i == TSPP_NUM_PRIORITIES) {
+		pr_err("tspp: no encryption on this channel");
+		return 1;
+	}
+
+	if (key->parity == TSPP_KEY_PARITY_EVEN) {
+		tspp_key_table->entry[key_index].even_lsb = key->lsb;
+		tspp_key_table->entry[key_index].even_msb = key->msb;
+	} else {
+		tspp_key_table->entry[key_index].odd_lsb = key->lsb;
+		tspp_key_table->entry[key_index].odd_msb = key->msb;
+	}
+	data = readl_relaxed(channel->pdev->base + TSPP_KEY_VALID);
+
+	return 0;
+}
+EXPORT_SYMBOL(tspp_set_key);
+
+static int tspp_set_iv(struct tspp_channel *channel, struct tspp_iv *iv)
+{
+	struct tspp_device *pdev = channel->pdev;
+
+	writel_relaxed(iv->data[0], pdev->base + TSPP_CBC_INIT_VAL(0));
+	writel_relaxed(iv->data[1], pdev->base + TSPP_CBC_INIT_VAL(1));
+	return 0;
+}
+
+static int tspp_set_system_keys(struct tspp_channel *channel,
+	struct tspp_system_keys *keys)
+{
+	int i;
+	struct tspp_device *pdev = channel->pdev;
+
+	for (i = 0; i < TSPP_NUM_SYSTEM_KEYS; i++)
+		writel_relaxed(keys->data[i], pdev->base + TSPP_SYSTEM_KEY(i));
+
+	return 0;
+}
+
+static int tspp_set_buffer_size(struct tspp_channel *channel,
+	struct tspp_buffer *buf)
+{
+	if (buf->size < TSPP_MIN_BUFFER_SIZE)
+		channel->bufsize = TSPP_MIN_BUFFER_SIZE;
+	else if (buf->size > TSPP_MAX_BUFFER_SIZE)
+		channel->bufsize = TSPP_MAX_BUFFER_SIZE;
+	else
+		channel->bufsize = buf->size;
+
+	TSPP_DEBUG("tspp channel %i buffer size %i",
+		channel->id, channel->bufsize);
+
+	return 0;
+}
+
+/*** File Operations ***/
+static ssize_t tspp_open(struct inode *inode, struct file *filp)
+{
+	struct tspp_channel *channel;
+	channel = container_of(inode->i_cdev, struct tspp_channel, cdev);
+	filp->private_data = channel;
+
+	/* if this channel is already in use, quit */
+	if (channel->used) {
+		pr_err("tspp channel %i already in use",
+			MINOR(channel->cdev.dev));
+		return -EACCES;
+	}
+
+	if (tspp_open_channel(channel) != 0) {
+		pr_err("tspp: error opening channel");
+		return -EACCES;
+	}
+
+	return 0;
+}
+
+static unsigned int tspp_poll(struct file *filp, struct poll_table_struct *p)
+{
+	unsigned long flags;
+	unsigned int mask = 0;
+	struct tspp_channel *channel;
+	channel = filp->private_data;
+
+	/* register the wait queue for this channel */
+	poll_wait(filp, &channel->in_queue, p);
+
+	spin_lock_irqsave(&channel->pdev->spinlock, flags);
+	if (channel->buffer[channel->read].state == TSPP_BUF_STATE_DATA)
+		mask = POLLIN | POLLRDNORM;
+
+	spin_unlock_irqrestore(&channel->pdev->spinlock, flags);
+
+	return mask;
+}
+
+static ssize_t tspp_release(struct inode *inode, struct file *filp)
+{
+	struct tspp_channel *channel;
+	channel = filp->private_data;
+
+	pr_info("tspp_release");
+	tspp_close_channel(channel);
+
+	return 0;
+}
+
+static ssize_t tspp_read(struct file *filp, char __user *buf, size_t count,
+			 loff_t *f_pos)
+{
+	size_t size = 0;
+	size_t transferred = 0;
+	struct tspp_channel *channel;
+	struct tspp_mem_buffer *buffer;
+	channel = filp->private_data;
+
+	TSPP_DEBUG("tspp_read");
+	buffer = &channel->buffer[channel->read];
+	/* see if we have any buffers ready to read */
+	while (buffer->state != TSPP_BUF_STATE_DATA) {
+		if (filp->f_flags & O_NONBLOCK) {
+			pr_warn("tspp: nothing to read on channel %i!",
+				channel->id);
+			return -EAGAIN;
+		}
+		/* go to sleep if there is nothing to read */
+	   TSPP_DEBUG("tspp: sleeping");
+		if (wait_event_interruptible(channel->in_queue,
+			(buffer->state == TSPP_BUF_STATE_DATA))) {
+			pr_err("tspp: rude awakening\n");
+			return -ERESTARTSYS;
+		}
+	}
+
+	while (buffer->state == TSPP_BUF_STATE_DATA) {
+		size = min(count, buffer->filled);
+		TSPP_DEBUG("tspp: reading channel %i buffer %i size %i",
+			channel->id, channel->read, size);
+		if (size == 0)
+			break;
+
+#ifndef TSPP_USE_DMA_ALLOC_COHERENT
+		/* unmap buffer (invalidates processor cache) */
+		if (buffer->mem.phys_base) {
+			dma_unmap_single(NULL,
+				buffer->mem.phys_base,
+				buffer->mem.size,
+				DMA_FROM_DEVICE);
+			buffer->mem.phys_base = 0;
+		}
+#endif
+
+		if (copy_to_user(buf, buffer->mem.base +
+			buffer->read_index, size)) {
+			pr_err("tspp: error copying to user buffer");
+			return -EFAULT;
+		}
+		buf += size;
+		count -= size;
+		transferred += size;
+		buffer->read_index += size;
+
+		/* after reading the end of the buffer, requeue it,
+			and set up for reading the next one */
+		if (buffer->read_index ==
+			channel->buffer[channel->read].filled) {
+			buffer->state = TSPP_BUF_STATE_WAITING;
+#ifndef TSPP_USE_DMA_ALLOC_COHERENT
+			buffer->mem.phys_base = dma_map_single(NULL,
+				buffer->mem.base,
+				buffer->mem.size,
+				DMA_FROM_DEVICE);
+			if (!dma_mapping_error(NULL,
+			buffer->mem.phys_base)) {
+#endif
+				if (sps_transfer_one(channel->pipe,
+					buffer->mem.phys_base,
+					buffer->mem.size,
+					channel,
+					SPS_IOVEC_FLAG_INT |
+					SPS_IOVEC_FLAG_EOT))
+					pr_err("tspp: can't submit transfer");
+				else {
+					channel->read++;
+					if (channel->read == TSPP_NUM_BUFFERS)
+						channel->read = 0;
+				}
+#ifndef TSPP_USE_DMA_ALLOC_COHERENT
+			}
+#endif
+		}
+	}
+
+	return transferred;
+}
+
+static long tspp_ioctl(struct file *filp,
+			unsigned int param0, unsigned long param1)
+{
+	int rc = -1;
+	struct tspp_channel *channel;
+	channel = filp->private_data;
+
+	if (!param1)
+		return -EINVAL;
+
+	switch (param0) {
+	case TSPP_IOCTL_SELECT_SOURCE:
+		rc = tspp_select_source(channel,
+			(struct tspp_select_source *)param1);
+		break;
+	case TSPP_IOCTL_ADD_FILTER:
+		rc = tspp_add_filter(channel,
+			(struct tspp_filter *)param1);
+		break;
+	case TSPP_IOCTL_REMOVE_FILTER:
+		rc = tspp_remove_filter(channel,
+			(struct tspp_filter *)param1);
+		break;
+	case TSPP_IOCTL_SET_KEY:
+		rc = tspp_set_key(channel,
+			(struct tspp_key *)param1);
+		break;
+	case TSPP_IOCTL_SET_IV:
+		rc = tspp_set_iv(channel,
+			(struct tspp_iv *)param1);
+		break;
+	case TSPP_IOCTL_SET_SYSTEM_KEYS:
+		rc = tspp_set_system_keys(channel,
+			(struct tspp_system_keys *)param1);
+		break;
+	case TSPP_IOCTL_BUFFER_SIZE:
+		rc = tspp_set_buffer_size(channel,
+			(struct tspp_buffer *)param1);
+		break;
+	case TSPP_IOCTL_LOOPBACK:
+		loopback_mode = param1;
+		rc = 0;
+		break;
+	default:
+		pr_err("tspp: Unknown ioctl %i", param0);
+	}
+
+	/* normalize the return code in case one of the subfunctions does
+		something weird */
+	if (rc != 0)
+		rc = 1;
+
+	return rc;
+}
+
+/*** debugfs ***/
+#ifdef TSPP_USE_DEBUGFS
+static int debugfs_iomem_x32_set(void *data, u64 val)
+{
+	writel_relaxed(val, data);
+	wmb();
+	return 0;
+}
+
+static int debugfs_iomem_x32_get(void *data, u64 *val)
+{
+	*val = readl_relaxed(data);
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32, debugfs_iomem_x32_get,
+			debugfs_iomem_x32_set, "0x%08llx");
+
+static void tsif_debugfs_init(struct tspp_tsif_device *tsif_device,
+	int instance)
+{
+	char name[10];
+	snprintf(name, 10, "tsif%i", instance);
+	tsif_device->dent_tsif = debugfs_create_dir(
+	      name, NULL);
+	if (tsif_device->dent_tsif) {
+		int i;
+		void __iomem *base = tsif_device->base;
+		for (i = 0; i < ARRAY_SIZE(debugfs_tsif_regs); i++) {
+			tsif_device->debugfs_tsif_regs[i] =
+			   debugfs_create_file(
+				debugfs_tsif_regs[i].name,
+				debugfs_tsif_regs[i].mode,
+				tsif_device->dent_tsif,
+				base + debugfs_tsif_regs[i].offset,
+				&fops_iomem_x32);
+		}
+	}
+}
+
+static void tsif_debugfs_exit(struct tspp_tsif_device *tsif_device)
+{
+	if (tsif_device->dent_tsif) {
+		int i;
+		debugfs_remove_recursive(tsif_device->dent_tsif);
+		tsif_device->dent_tsif = NULL;
+		for (i = 0; i < ARRAY_SIZE(debugfs_tsif_regs); i++)
+			tsif_device->debugfs_tsif_regs[i] = NULL;
+	}
+}
+
+static void tspp_debugfs_init(struct tspp_device *device, int instance)
+{
+	char name[10];
+	snprintf(name, 10, "tspp%i", instance);
+	device->dent = debugfs_create_dir(
+	      name, NULL);
+	if (device->dent) {
+		int i;
+		void __iomem *base = device->base;
+		for (i = 0; i < ARRAY_SIZE(debugfs_tspp_regs); i++) {
+			device->debugfs_regs[i] =
+			   debugfs_create_file(
+				debugfs_tspp_regs[i].name,
+				debugfs_tspp_regs[i].mode,
+				device->dent,
+				base + debugfs_tspp_regs[i].offset,
+				&fops_iomem_x32);
+		}
+	}
+}
+
+static void tspp_debugfs_exit(struct tspp_device *device)
+{
+	if (device->dent) {
+		int i;
+		debugfs_remove_recursive(device->dent);
+		device->dent = NULL;
+		for (i = 0; i < ARRAY_SIZE(debugfs_tspp_regs); i++)
+			device->debugfs_regs[i] = NULL;
+	}
+}
+#endif /* TSPP_USE_DEBUGFS */
+
+static const struct file_operations tspp_fops = {
+	.owner   = THIS_MODULE,
+	.read    = tspp_read,
+	.open    = tspp_open,
+	.poll    = tspp_poll,
+	.release = tspp_release,
+	.unlocked_ioctl   = tspp_ioctl,
+};
+
+static int tspp_channel_init(struct tspp_channel *channel)
+{
+	channel->bufsize = TSPP_MIN_BUFFER_SIZE;
+	channel->read = 0;
+	channel->waiting = 0;
+	cdev_init(&channel->cdev, &tspp_fops);
+	channel->cdev.owner = THIS_MODULE;
+	channel->id = MINOR(tspp_minor);
+	init_waitqueue_head(&channel->in_queue);
+	channel->buffer_count = 0;
+	channel->filter_count = 0;
+
+	if (cdev_add(&channel->cdev, tspp_minor++, 1) != 0) {
+		pr_err("tspp: cdev_add failed");
+		return 1;
+	}
+
+	channel->dd = device_create(tspp_class, NULL, channel->cdev.dev,
+		channel, "tspp%02d", channel->id);
+	if (IS_ERR(channel->dd)) {
+		pr_err("tspp: device_create failed: %i",
+			(int)PTR_ERR(channel->dd));
+		cdev_del(&channel->cdev);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int __devinit msm_tspp_probe(struct platform_device *pdev)
+{
+	int rc = -ENODEV;
+	u32 version;
+	u32 i;
+	struct msm_tspp_platform_data *data;
+	struct tspp_device *device;
+	struct resource *mem_tsif0;
+	struct resource *mem_tsif1;
+	struct resource *mem_tspp;
+	struct resource *mem_bam;
+	struct tspp_channel *channel;
+
+	/* must have platform data */
+	data = pdev->dev.platform_data;
+	if (!data) {
+		pr_err("tspp: Platform data not available");
+		rc = -EINVAL;
+		goto out;
+	}
+
+	/* check for valid device id */
+	if ((pdev->id < 0) || (pdev->id >= 1)) {
+		pr_err("tspp: Invalid device ID %d", pdev->id);
+		rc = -EINVAL;
+		goto out;
+	}
+
+	/* OK, we will use this device */
+	device = kzalloc(sizeof(struct tspp_device), GFP_KERNEL);
+	if (!device) {
+		pr_err("tspp: Failed to allocate memory for device");
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	/* set up references */
+	device->pdev = pdev;
+	platform_set_drvdata(pdev, device);
+
+	/* map clocks */
+	if (data->tsif_pclk) {
+		device->tsif_pclk = clk_get(NULL, data->tsif_pclk);
+		if (IS_ERR(device->tsif_pclk)) {
+			pr_err("tspp: failed to get %s",
+				data->tsif_pclk);
+			rc = PTR_ERR(device->tsif_pclk);
+			device->tsif_pclk = NULL;
+			goto err_pclock;
+		}
+	}
+	if (data->tsif_ref_clk) {
+		device->tsif_ref_clk = clk_get(NULL, data->tsif_ref_clk);
+		if (IS_ERR(device->tsif_ref_clk)) {
+			pr_err("tspp: failed to get %s",
+				data->tsif_ref_clk);
+			rc = PTR_ERR(device->tsif_ref_clk);
+			device->tsif_ref_clk = NULL;
+			goto err_refclock;
+		}
+	}
+
+	/* map I/O memory */
+	mem_tsif0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem_tsif0) {
+		pr_err("tspp: Missing tsif0 MEM resource");
+		rc = -ENXIO;
+		goto err_res_tsif0;
+	}
+	device->tsif[0].base = ioremap(mem_tsif0->start,
+		resource_size(mem_tsif0));
+	if (!device->tsif[0].base) {
+		pr_err("tspp: ioremap failed");
+		goto err_map_tsif0;
+	}
+
+	mem_tsif1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!mem_tsif1) {
+		dev_err(&pdev->dev, "Missing tsif1 MEM resource");
+		rc = -ENXIO;
+		goto err_res_tsif1;
+	}
+	device->tsif[1].base = ioremap(mem_tsif1->start,
+		resource_size(mem_tsif1));
+	if (!device->tsif[1].base) {
+		dev_err(&pdev->dev, "ioremap failed");
+		goto err_map_tsif1;
+	}
+
+	mem_tspp = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (!mem_tspp) {
+		dev_err(&pdev->dev, "Missing MEM resource");
+		rc = -ENXIO;
+		goto err_res_dev;
+	}
+	device->base = ioremap(mem_tspp->start, resource_size(mem_tspp));
+	if (!device->base) {
+		dev_err(&pdev->dev, "ioremap failed");
+		goto err_map_dev;
+	}
+
+	mem_bam = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+	if (!mem_bam) {
+		pr_err("tspp: Missing bam MEM resource");
+		rc = -ENXIO;
+		goto err_res_bam;
+	}
+	memset(&device->bam_props, 0, sizeof(device->bam_props));
+	device->bam_props.phys_addr = mem_bam->start;
+	device->bam_props.virt_addr = ioremap(mem_bam->start,
+		resource_size(mem_bam));
+	if (!device->bam_props.virt_addr) {
+		dev_err(&pdev->dev, "ioremap failed");
+		goto err_map_bam;
+	}
+
+	/* map TSPP IRQ */
+	rc = platform_get_irq(pdev, 0);
+	if (rc > 0) {
+		device->tspp_irq = rc;
+		rc = request_irq(device->tspp_irq, tspp_isr, IRQF_SHARED,
+				 dev_name(&pdev->dev), device);
+		if (rc) {
+			dev_err(&pdev->dev, "failed to request IRQ %d : %d",
+				device->tspp_irq, rc);
+			goto err_irq;
+		}
+	} else {
+		dev_err(&pdev->dev, "failed to get tspp IRQ");
+		goto err_irq;
+	}
+
+	/* BAM IRQ */
+	device->bam_irq = TSIF_BAM_IRQ;
+
+	/* GPIOs */
+	rc = tspp_start_gpios(device);
+	if (rc)
+		goto err_gpio;
+
+	/* power management */
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+#ifdef TSPP_USE_DEBUGFS
+	tspp_debugfs_init(device, 0);
+
+	for (i = 0; i < TSPP_TSIF_INSTANCES; i++)
+		tsif_debugfs_init(&device->tsif[i], i);
+#endif /* TSPP_USE_DEBUGFS */
+
+	wake_lock_init(&device->wake_lock, WAKE_LOCK_SUSPEND,
+		dev_name(&pdev->dev));
+
+	/* set up pointers to ram-based 'registers' */
+	tspp_filter_table[0] = TSPP_PID_FILTER_TABLE0 + device->base;
+	tspp_filter_table[1] = TSPP_PID_FILTER_TABLE1 + device->base;
+	tspp_filter_table[2] = TSPP_PID_FILTER_TABLE2 + device->base;
+	tspp_key_table = TSPP_DATA_KEY + device->base;
+	tspp_global_performance = TSPP_GLOBAL_PERFORMANCE + device->base;
+	tspp_pipe_context = TSPP_PIPE_CONTEXT + device->base;
+	tspp_pipe_performance = TSPP_PIPE_PERFORMANCE + device->base;
+
+	device->bam_props.summing_threshold = 0x10;
+	device->bam_props.irq = device->bam_irq;
+	device->bam_props.manage = SPS_BAM_MGR_LOCAL;
+
+	if (sps_register_bam_device(&device->bam_props,
+		&device->bam_handle) != 0) {
+		pr_err("tspp: failed to register bam");
+		goto err_bam;
+	}
+
+	if (device->tsif_pclk && clk_enable(device->tsif_pclk) != 0) {
+		dev_err(&pdev->dev, "Can't start pclk");
+		goto err_pclk;
+	}
+	if (device->tsif_ref_clk && clk_enable(device->tsif_ref_clk) != 0) {
+		dev_err(&pdev->dev, "Can't start ref clk");
+		goto err_refclk;
+	}
+
+	spin_lock_init(&device->spinlock);
+	tasklet_init(&device->tlet, tspp_sps_complete_tlet,
+			(unsigned long)device);
+
+	/* initialize everything to a known state */
+	tspp_global_reset(device);
+
+	version = readl_relaxed(device->base + TSPP_VERSION);
+	if (version != 1)
+		pr_warn("tspp: unrecognized hw version=%i", version);
+
+	/* update the channels with the device */
+	for (i = 0; i < TSPP_NUM_CHANNELS; i++) {
+		channel = &channel_list[i];
+		channel->pdev = device;
+	}
+
+	/* everything is ok */
+	return 0;
+
+err_refclk:
+	if (device->tsif_pclk)
+		clk_disable(device->tsif_pclk);
+err_pclk:
+	sps_deregister_bam_device(device->bam_handle);
+err_bam:
+#ifdef TSPP_USE_DEBUGFS
+	tspp_debugfs_exit(device);
+	for (i = 0; i < TSPP_TSIF_INSTANCES; i++)
+		tsif_debugfs_exit(&device->tsif[i]);
+#endif /* TSPP_USE_DEBUGFS */
+err_gpio:
+err_irq:
+	tspp_stop_gpios(device);
+	iounmap(device->bam_props.virt_addr);
+err_map_bam:
+err_res_bam:
+	iounmap(device->base);
+err_map_dev:
+err_res_dev:
+	iounmap(device->tsif[1].base);
+err_map_tsif1:
+err_res_tsif1:
+	iounmap(device->tsif[0].base);
+err_map_tsif0:
+err_res_tsif0:
+	if (device->tsif_ref_clk)
+		clk_put(device->tsif_ref_clk);
+err_refclock:
+	if (device->tsif_pclk)
+		clk_put(device->tsif_pclk);
+err_pclock:
+	kfree(device);
+
+out:
+	return rc;
+}
+
+static int __devexit msm_tspp_remove(struct platform_device *pdev)
+{
+#ifdef TSPP_USE_DEBUGFS
+	u32 i;
+#endif /* TSPP_USE_DEBUGFS */
+
+	struct tspp_device *device = platform_get_drvdata(pdev);
+
+	sps_deregister_bam_device(device->bam_handle);
+
+#ifdef TSPP_USE_DEBUGFS
+	for (i = 0; i < TSPP_TSIF_INSTANCES; i++)
+		tsif_debugfs_exit(&device->tsif[i]);
+#endif /* TSPP_USE_DEBUGFS */
+
+	wake_lock_destroy(&device->wake_lock);
+	free_irq(device->tspp_irq, device);
+	tspp_stop_gpios(device);
+
+	iounmap(device->bam_props.virt_addr);
+	iounmap(device->base);
+	for (i = 0; i < TSPP_TSIF_INSTANCES; i++)
+		iounmap(device->tsif[i].base);
+
+	if (device->tsif_ref_clk)
+		clk_put(device->tsif_ref_clk);
+
+	if (device->tsif_pclk)
+		clk_put(device->tsif_pclk);
+
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_put(&pdev->dev);
+	kfree(device);
+
+	return 0;
+}
+
+/*** power management ***/
+
+static int tspp_runtime_suspend(struct device *dev)
+{
+	dev_dbg(dev, "pm_runtime: suspending...");
+	return 0;
+}
+
+static int tspp_runtime_resume(struct device *dev)
+{
+	dev_dbg(dev, "pm_runtime: resuming...");
+	return 0;
+}
+
+static const struct dev_pm_ops tspp_dev_pm_ops = {
+	.runtime_suspend = tspp_runtime_suspend,
+	.runtime_resume = tspp_runtime_resume,
+};
+
+static struct platform_driver msm_tspp_driver = {
+	.probe          = msm_tspp_probe,
+	.remove         = __exit_p(msm_tspp_remove),
+	.driver         = {
+		.name   = "msm_tspp",
+		.pm     = &tspp_dev_pm_ops,
+	},
+};
+
+
+static int __init mod_init(void)
+{
+	u32 i;
+	int rc;
+
+	/* first register the driver, and check hardware */
+	rc = platform_driver_register(&msm_tspp_driver);
+	if (rc) {
+		pr_err("tspp: platform_driver_register failed: %d", rc);
+		goto err_register;
+	}
+
+	/* now make the char devs (channels) */
+	rc = alloc_chrdev_region(&tspp_minor, 0, TSPP_NUM_CHANNELS, "tspp");
+	if (rc) {
+		pr_err("tspp: alloc_chrdev_region failed: %d", rc);
+		goto err_devrgn;
+	}
+
+	tspp_class = class_create(THIS_MODULE, "tspp");
+	if (IS_ERR(tspp_class)) {
+		rc = PTR_ERR(tspp_class);
+		pr_err("tspp: Error creating class: %d", rc);
+		goto err_class;
+	}
+
+	for (i = 0; i < TSPP_NUM_CHANNELS; i++) {
+		if (tspp_channel_init(&channel_list[i]) != 0) {
+			pr_err("tspp_channel_init failed");
+			break;
+		}
+	}
+
+	return 0;
+
+err_class:
+	unregister_chrdev_region(0, TSPP_NUM_CHANNELS);
+err_devrgn:
+	platform_driver_unregister(&msm_tspp_driver);
+err_register:
+	return rc;
+}
+
+static void __exit mod_exit(void)
+{
+	u32 i;
+	struct tspp_channel *channel;
+
+	/* first delete upper layer interface */
+	for (i = 0; i < TSPP_NUM_CHANNELS; i++) {
+		channel = &channel_list[i];
+		device_destroy(tspp_class, channel->cdev.dev);
+		cdev_del(&channel->cdev);
+	}
+	class_destroy(tspp_class);
+	unregister_chrdev_region(0, TSPP_NUM_CHANNELS);
+
+	/* now delete low level driver */
+	platform_driver_unregister(&msm_tspp_driver);
+}
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_DESCRIPTION("TSPP character device interface");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/wireless/wcnss/wcnss_riva.c b/drivers/net/wireless/wcnss/wcnss_riva.c
index 9f69f12..b0eac55 100644
--- a/drivers/net/wireless/wcnss/wcnss_riva.c
+++ b/drivers/net/wireless/wcnss/wcnss_riva.c
@@ -18,10 +18,10 @@
 #include <linux/regulator/consumer.h>
 #include <linux/mfd/pm8xxx/pm8921.h>
 #include <linux/mfd/pm8xxx/gpio.h>
+#include <linux/wcnss_wlan.h>
 #include <mach/msm_xo.h>
 #include <mach/msm_iomap.h>
 
-#include "wcnss_riva.h"
 
 static void __iomem *msm_riva_base;
 static struct msm_xo_voter *wlan_clock;
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 7453068..7217434 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -22,7 +22,6 @@
 #include <linux/jiffies.h>
 #include <linux/gpio.h>
 #include <mach/peripheral-loader.h>
-#include "wcnss_riva.h"
 
 #define DEVICE "wcnss_wlan"
 #define VERSION "1.01"
@@ -128,6 +127,22 @@
 }
 EXPORT_SYMBOL(wcnss_wlan_get_device);
 
+struct platform_device *wcnss_get_platform_device(void)
+{
+	if (penv && penv->pdev)
+		return penv->pdev;
+	return NULL;
+}
+EXPORT_SYMBOL(wcnss_get_platform_device);
+
+struct wcnss_wlan_config *wcnss_get_wlan_config(void)
+{
+	if (penv && penv->pdev)
+		return &penv->wlan_config;
+	return NULL;
+}
+EXPORT_SYMBOL(wcnss_get_wlan_config);
+
 struct resource *wcnss_wlan_get_memory_map(struct device *dev)
 {
 	if (penv && dev && (dev == &penv->pdev->dev) && penv->smd_channel_ready)
diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig
index 26441cd..23efb00 100644
--- a/drivers/platform/msm/Kconfig
+++ b/drivers/platform/msm/Kconfig
@@ -23,6 +23,14 @@
 		2. Peripheral-to-Memory.
 		3. Memory-to-Memory.
 
+config USB_BAM
+	boolean "USB BAM Driver"
+	depends on SPS && USB_GADGET
+	help
+	  Enabling this option adds USB BAM Driver.
+	  USB BAM driver was added to supports SPS Peripheral-to-Peripheral
+	  transfers between the USB and other peripheral.
+
 config SPS_SUPPORT_BAMDMA
 	bool "SPS support BAM DMA"
 	depends on SPS
diff --git a/drivers/platform/msm/Makefile b/drivers/platform/msm/Makefile
index f6f212e..92eb492 100644
--- a/drivers/platform/msm/Makefile
+++ b/drivers/platform/msm/Makefile
@@ -2,4 +2,5 @@
 # Makefile for the MSM specific device drivers.
 #
 obj-$(CONFIG_MSM_SSBI) += ssbi.o
+obj-$(CONFIG_USB_BAM) += usb_bam.o
 obj-$(CONFIG_SPS) += sps/
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
new file mode 100644
index 0000000..b34c35e
--- /dev/null
+++ b/drivers/platform/msm/usb_bam.c
@@ -0,0 +1,238 @@
+/* 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/types.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/usb/msm_hsusb.h>
+#include <mach/usb_bam.h>
+#include <mach/sps.h>
+
+#define USB_SUMMING_THRESHOLD 512
+#define CONNECTIONS_NUM		4
+
+static struct sps_bam_props usb_props;
+static struct sps_pipe *sps_pipes[CONNECTIONS_NUM][2];
+static struct sps_connect sps_connections[CONNECTIONS_NUM][2];
+static struct sps_mem_buffer data_mem_buf[CONNECTIONS_NUM][2];
+static struct sps_mem_buffer desc_mem_buf[CONNECTIONS_NUM][2];
+static struct platform_device *usb_bam_pdev;
+
+struct usb_bam_connect_info {
+	u8 idx;
+	u8 *src_pipe;
+	u8 *dst_pipe;
+	bool enabled;
+};
+
+static struct usb_bam_connect_info usb_bam_connections[CONNECTIONS_NUM];
+
+static int connect_pipe(u8 connection_idx, enum usb_bam_pipe_dir pipe_dir,
+						u8 *usb_pipe_idx)
+{
+	int ret;
+	struct sps_pipe *pipe = sps_pipes[connection_idx][pipe_dir];
+	struct sps_connect *connection =
+		&sps_connections[connection_idx][pipe_dir];
+	struct msm_usb_bam_platform_data *pdata =
+		(struct msm_usb_bam_platform_data *)
+			(usb_bam_pdev->dev.platform_data);
+	struct usb_bam_pipe_connect *pipe_connection =
+			(struct usb_bam_pipe_connect *)(pdata->connections +
+						(2*connection_idx+pipe_dir));
+
+	pipe = sps_alloc_endpoint();
+	if (pipe == NULL) {
+		pr_err("%s: sps_alloc_endpoint failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	ret = sps_get_config(pipe, connection);
+	if (ret) {
+		pr_err("%s: tx get config failed %d\n", __func__, ret);
+		goto get_config_failed;
+	}
+
+	ret = sps_phy2h(pipe_connection->src_phy_addr, &(connection->source));
+	if (ret) {
+		pr_err("%s: sps_phy2h failed (src BAM) %d\n", __func__, ret);
+		goto get_config_failed;
+	}
+
+	connection->src_pipe_index = pipe_connection->src_pipe_index;
+	ret = sps_phy2h(pipe_connection->dst_phy_addr,
+					&(connection->destination));
+	if (ret) {
+		pr_err("%s: sps_phy2h failed (dst BAM) %d\n", __func__, ret);
+		goto get_config_failed;
+	}
+	connection->dest_pipe_index = pipe_connection->dst_pipe_index;
+
+	if (pipe_dir == USB_TO_PEER_PERIPHERAL) {
+		connection->mode = SPS_MODE_SRC;
+		*usb_pipe_idx = connection->src_pipe_index;
+	} else {
+		connection->mode = SPS_MODE_DEST;
+		*usb_pipe_idx = connection->dest_pipe_index;
+	}
+
+	ret = sps_setup_bam2bam_fifo(
+				&data_mem_buf[connection_idx][pipe_dir],
+				pipe_connection->data_fifo_base_offset,
+				pipe_connection->data_fifo_size, 1);
+	if (ret) {
+		pr_err("%s: data fifo setup failure %d\n", __func__, ret);
+		goto fifo_setup_error;
+	}
+	connection->data = data_mem_buf[connection_idx][pipe_dir];
+
+	ret = sps_setup_bam2bam_fifo(
+				&desc_mem_buf[connection_idx][pipe_dir],
+				pipe_connection->desc_fifo_base_offset,
+				pipe_connection->desc_fifo_size, 1);
+	if (ret) {
+		pr_err("%s: desc. fifo setup failure %d\n", __func__, ret);
+		goto fifo_setup_error;
+	}
+	connection->desc = desc_mem_buf[connection_idx][pipe_dir];
+	connection->event_thresh = 512;
+
+	ret = sps_connect(pipe, connection);
+	if (ret < 0) {
+		pr_err("%s: tx connect error %d\n", __func__, ret);
+		goto error;
+	}
+	return 0;
+
+error:
+	sps_disconnect(pipe);
+fifo_setup_error:
+get_config_failed:
+	sps_free_endpoint(pipe);
+	return ret;
+}
+
+int usb_bam_connect(u8 idx, u8 *src_pipe_idx, u8 *dst_pipe_idx)
+{
+	struct usb_bam_connect_info *connection = &usb_bam_connections[idx];
+	int ret;
+
+	if (idx >= CONNECTIONS_NUM) {
+		pr_err("%s: Invalid connection index\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (connection->enabled) {
+		pr_info("%s: connection %d was already established\n",
+			__func__, idx);
+		return 0;
+	}
+	connection->src_pipe = src_pipe_idx;
+	connection->dst_pipe = dst_pipe_idx;
+	connection->idx = idx;
+
+	/* open USB -> Peripheral pipe */
+	ret = connect_pipe(connection->idx, USB_TO_PEER_PERIPHERAL,
+					   connection->src_pipe);
+	if (ret) {
+		pr_err("%s: src pipe connection failure\n", __func__);
+		return ret;
+	}
+	/* open Peripheral -> USB pipe */
+	ret = connect_pipe(connection->idx, PEER_PERIPHERAL_TO_USB,
+				 connection->dst_pipe);
+	if (ret) {
+		pr_err("%s: dst pipe connection failure\n", __func__);
+		return ret;
+	}
+	connection->enabled = 1;
+
+	return 0;
+}
+static int usb_bam_init(void)
+{
+	u32 h_usb;
+	int ret;
+	void *usb_virt_addr;
+	struct msm_usb_bam_platform_data *pdata =
+		(struct msm_usb_bam_platform_data *)
+			(usb_bam_pdev->dev.platform_data);
+
+	usb_virt_addr = ioremap_nocache(
+						pdata->usb_bam_phy_base,
+						pdata->usb_bam_phy_size);
+	if (!usb_virt_addr) {
+		pr_err("%s: ioremap failed\n", __func__);
+		return -ENOMEM;
+	}
+	usb_props.phys_addr = pdata->usb_bam_phy_base;
+	usb_props.virt_addr = usb_virt_addr;
+	usb_props.virt_size = pdata->usb_bam_phy_size;
+	usb_props.irq = USB1_HS_BAM_IRQ;
+	usb_props.num_pipes = pdata->usb_bam_num_pipes;
+	usb_props.summing_threshold = USB_SUMMING_THRESHOLD;
+	ret = sps_register_bam_device(&usb_props, &h_usb);
+	if (ret < 0) {
+		pr_err("%s: register bam error %d\n", __func__, ret);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int usb_bam_probe(struct platform_device *pdev)
+{
+	int ret, i;
+
+	dev_dbg(&pdev->dev, "usb_bam_probe\n");
+
+	for (i = 0; i < CONNECTIONS_NUM; i++)
+		usb_bam_connections[i].enabled = 0;
+
+	if (!pdev->dev.platform_data) {
+		dev_err(&pdev->dev, "missing platform_data\n");
+		return -ENODEV;
+	}
+	usb_bam_pdev = pdev;
+
+	ret = usb_bam_init();
+	if (ret) {
+		dev_err(&pdev->dev, "failed to get platform resource mem\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct platform_driver usb_bam_driver = {
+	.probe = usb_bam_probe,
+	.driver = { .name = "usb_bam", },
+};
+
+static int __init init(void)
+{
+	return platform_driver_register(&usb_bam_driver);
+}
+module_init(init);
+
+static void __exit cleanup(void)
+{
+	platform_driver_unregister(&usb_bam_driver);
+}
+module_exit(cleanup);
+
+MODULE_DESCRIPTION("MSM USB BAM DRIVER");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index e908799..47a5d47 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -239,6 +239,7 @@
 	struct dentry			*dent;
 	struct bms_notify		bms_notify;
 	struct ext_chg_pm8921		*ext;
+	bool				keep_btm_on_suspend;
 	bool				ext_charging;
 	bool				ext_charge_done;
 	DECLARE_BITMAP(enabled_irqs, PM_CHG_MAX_INTS);
@@ -2671,6 +2672,37 @@
 	}
 }
 
+static int pm8921_charger_resume(struct device *dev)
+{
+	int rc;
+	struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
+
+	if (!(chip->cool_temp == 0 && chip->warm_temp == 0)
+		&& !(chip->keep_btm_on_suspend)) {
+		rc = pm8xxx_adc_btm_configure(&btm_config);
+		if (rc)
+			pr_err("couldn't reconfigure btm rc=%d\n", rc);
+
+		rc = pm8xxx_adc_btm_start();
+		if (rc)
+			pr_err("couldn't restart btm rc=%d\n", rc);
+	}
+	return 0;
+}
+
+static int pm8921_charger_suspend(struct device *dev)
+{
+	int rc;
+	struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
+
+	if (!(chip->cool_temp == 0 && chip->warm_temp == 0)
+		&& !(chip->keep_btm_on_suspend)) {
+		rc = pm8xxx_adc_btm_end();
+		if (rc)
+			pr_err("Failed to disable BTM on suspend rc=%d\n", rc);
+	}
+	return 0;
+}
 static int __devinit pm8921_charger_probe(struct platform_device *pdev)
 {
 	int rc = 0;
@@ -2711,6 +2743,7 @@
 	chip->warm_bat_chg_current = pdata->warm_bat_chg_current;
 	chip->cool_bat_voltage = pdata->cool_bat_voltage;
 	chip->warm_bat_voltage = pdata->warm_bat_voltage;
+	chip->keep_btm_on_suspend = pdata->keep_btm_on_suspend;
 	chip->trkl_voltage = pdata->trkl_voltage;
 	chip->weak_voltage = pdata->weak_voltage;
 	chip->trkl_current = pdata->trkl_current;
@@ -2837,13 +2870,17 @@
 	kfree(chip);
 	return 0;
 }
-
+static const struct dev_pm_ops pm8921_pm_ops = {
+	.suspend	= pm8921_charger_suspend,
+	.resume		= pm8921_charger_resume,
+};
 static struct platform_driver pm8921_charger_driver = {
-	.probe	= pm8921_charger_probe,
-	.remove	= __devexit_p(pm8921_charger_remove),
-	.driver	= {
-		.name	= PM8921_CHARGER_DEV_NAME,
-		.owner	= THIS_MODULE,
+	.probe		= pm8921_charger_probe,
+	.remove		= __devexit_p(pm8921_charger_remove),
+	.driver		= {
+			.name	= PM8921_CHARGER_DEV_NAME,
+			.owner	= THIS_MODULE,
+			.pm	= &pm8921_pm_ops,
 	},
 };
 
diff --git a/drivers/regulator/pmic8901-regulator.c b/drivers/regulator/pmic8901-regulator.c
index 5b4b907..6fd0a05 100644
--- a/drivers/regulator/pmic8901-regulator.c
+++ b/drivers/regulator/pmic8901-regulator.c
@@ -16,14 +16,13 @@
 #include <linux/init.h>
 #include <linux/mfd/pmic8901.h>
 #include <linux/regulator/driver.h>
+#include <linux/mfd/pm8xxx/core.h>
 #include <linux/regulator/pmic8901-regulator.h>
-#include <mach/mpp.h>
 
 /* Regulator types */
 #define REGULATOR_TYPE_LDO		0
 #define REGULATOR_TYPE_SMPS		1
 #define REGULATOR_TYPE_VS		2
-#define REGULATOR_TYPE_MPP		3
 
 /* Bank select/write macros */
 #define REGULATOR_BANK_SEL(n)           ((n) << 4)
@@ -140,9 +139,9 @@
 #define VS_PULL_DOWN_ENABLE		0x20
 
 struct pm8901_vreg {
+	struct device			*dev;
 	struct pm8901_vreg_pdata	*pdata;
 	struct regulator_dev		*rdev;
-	struct pm8901_chip		*chip;
 	int				hpm_min_load;
 	unsigned			pc_vote;
 	unsigned			optimum;
@@ -159,7 +158,6 @@
 	u8				pfm_ctrl_reg;
 	u8				pwr_cnfg_reg;
 	u8				is_nmos;
-	u8				mpp_id;
 	u8				state;
 };
 
@@ -167,8 +165,8 @@
  * These are used to compensate for the PMIC 8901 v1 FTS regulators which
  * output ~10% higher than the programmed set point.
  */
-#define IS_PMIC_8901_V1(rev)		((rev) == PM_8901_REV_1p0 || \
-					 (rev) == PM_8901_REV_1p1)
+#define IS_PMIC_8901_V1(rev)		((rev) == PM8XXX_REVISION_8901_1p0 || \
+					 (rev) == PM8XXX_REVISION_8901_1p1)
 
 #define PMIC_8901_V1_SCALE(uV)		((((uV) - 62100) * 23) / 25)
 
@@ -207,12 +205,6 @@
 		.type = REGULATOR_TYPE_VS, \
 	}
 
-#define MPP(_id, _mpp_id) \
-	[_id] = { \
-		.mpp_id = _mpp_id, \
-		.type = REGULATOR_TYPE_MPP, \
-	}
-
 static struct pm8901_vreg pm8901_vreg[] = {
 	/*  id                 ctrl   pmr    tst    n/p */
 	LDO(PM8901_VREG_ID_L0, 0x02F, 0x0AB, 0x030, 1),
@@ -230,9 +222,6 @@
 	SMPS(PM8901_VREG_ID_S3, 0x088, 0x0A9, 0x089, 0x0F6),
 	SMPS(PM8901_VREG_ID_S4, 0x097, 0x0AA, 0x098, 0x0FB),
 
-	/* id			  MPP ID */
-	MPP(PM8901_VREG_ID_MPP0,    0),
-
 	/* id                       ctrl   pmr */
 	VS(PM8901_VREG_ID_LVS0,     0x046, 0x0B2),
 	VS(PM8901_VREG_ID_LVS1,     0x048, 0x0B3),
@@ -246,7 +235,7 @@
 static void print_write_error(struct pm8901_vreg *vreg, int rc,
 				const char *func);
 
-static int pm8901_vreg_write(struct pm8901_chip *chip,
+static int pm8901_vreg_write(struct pm8901_vreg *vreg,
 		u16 addr, u8 val, u8 mask, u8 *reg_save)
 {
 	int rc = 0;
@@ -254,7 +243,7 @@
 
 	reg = (*reg_save & ~mask) | (val & mask);
 	if (reg != *reg_save)
-		rc = pm8901_write(chip, addr, &reg, 1);
+		rc = pm8xxx_writeb(vreg->dev->parent, addr, reg);
 	if (!rc)
 		*reg_save = reg;
 	return rc;
@@ -283,7 +272,6 @@
 static int pm8901_vreg_enable(struct regulator_dev *dev)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 	u8 val = VREG_PMR_STATE_HPM;
 	int rc;
 
@@ -298,7 +286,7 @@
 
 	pm8901_vreg_select_pin_ctrl(vreg, &val);
 
-	rc = pm8901_vreg_write(chip, vreg->pmr_addr,
+	rc = pm8901_vreg_write(vreg, vreg->pmr_addr,
 			val,
 			VREG_PMR_STATE_MASK | VREG_PMR_PIN_CTRL_ALL_MASK,
 			&vreg->pmr_reg);
@@ -311,10 +299,9 @@
 static int pm8901_vreg_disable(struct regulator_dev *dev)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 	int rc;
 
-	rc = pm8901_vreg_write(chip, vreg->pmr_addr,
+	rc = pm8901_vreg_write(vreg, vreg->pmr_addr,
 			VREG_PMR_STATE_OFF | VREG_PMR_PIN_CTRL_ALL_MASKED,
 			VREG_PMR_STATE_MASK | VREG_PMR_PIN_CTRL_ALL_MASK,
 			&vreg->pmr_reg);
@@ -359,11 +346,10 @@
 static int pm8901_ldo_disable(struct regulator_dev *dev)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 	int rc;
 
 	/* Disassert local enable bit in CTRL register. */
-	rc = pm8901_vreg_write(chip, vreg->ctrl_addr, 0, LDO_LOCAL_ENABLE_MASK,
+	rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, 0, LDO_LOCAL_ENABLE_MASK,
 			&vreg->ctrl_reg);
 	if (rc)
 		print_write_error(vreg, rc, __func__);
@@ -374,8 +360,7 @@
 	return rc;
 }
 
-static int pm8901_pldo_set_voltage(struct pm8901_chip *chip,
-		struct pm8901_vreg *vreg, int uV)
+static int pm8901_pldo_set_voltage(struct pm8901_vreg *vreg, int uV)
 {
 	int vmin, rc = 0;
 	unsigned vprog, fine_step;
@@ -414,7 +399,7 @@
 		|| ((range_sel ^ vreg->test_reg[2]) & LDO_TEST_RANGE_SEL_MASK)
 		|| ((fine_step_reg ^ vreg->test_reg[2])
 			& LDO_TEST_FINE_STEP_MASK))) {
-		rc = pm8901_vreg_write(chip, vreg->test_addr,
+		rc = pm8901_vreg_write(vreg, vreg->test_addr,
 			REGULATOR_BANK_SEL(2) | REGULATOR_BANK_WRITE,
 			REGULATOR_BANK_MASK | LDO_TEST_VPROG_UPDATE_MASK,
 			&vreg->test_reg[2]);
@@ -423,13 +408,13 @@
 	}
 
 	/* Write new voltage. */
-	rc = pm8901_vreg_write(chip, vreg->ctrl_addr, vprog,
+	rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, vprog,
 				LDO_CTRL_VPROG_MASK, &vreg->ctrl_reg);
 	if (rc)
 		goto bail;
 
 	/* Write range extension. */
-	rc = pm8901_vreg_write(chip, vreg->test_addr,
+	rc = pm8901_vreg_write(vreg, vreg->test_addr,
 			range_ext | REGULATOR_BANK_SEL(4)
 			 | REGULATOR_BANK_WRITE,
 			LDO_TEST_RANGE_EXT_MASK | REGULATOR_BANK_MASK,
@@ -438,7 +423,7 @@
 		goto bail;
 
 	/* Write fine step, range select and program voltage update. */
-	rc = pm8901_vreg_write(chip, vreg->test_addr,
+	rc = pm8901_vreg_write(vreg, vreg->test_addr,
 			fine_step_reg | range_sel | REGULATOR_BANK_SEL(2)
 			 | REGULATOR_BANK_WRITE | LDO_TEST_VPROG_UPDATE_MASK,
 			LDO_TEST_FINE_STEP_MASK | LDO_TEST_RANGE_SEL_MASK
@@ -451,8 +436,7 @@
 	return rc;
 }
 
-static int pm8901_nldo_set_voltage(struct pm8901_chip *chip,
-		struct pm8901_vreg *vreg, int uV)
+static int pm8901_nldo_set_voltage(struct pm8901_vreg *vreg, int uV)
 {
 	unsigned vprog, fine_step_reg;
 	int rc;
@@ -465,13 +449,13 @@
 	vprog >>= 1;
 
 	/* Write new voltage. */
-	rc = pm8901_vreg_write(chip, vreg->ctrl_addr, vprog,
+	rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, vprog,
 				LDO_CTRL_VPROG_MASK, &vreg->ctrl_reg);
 	if (rc)
 		print_write_error(vreg, rc, __func__);
 
 	/* Write fine step. */
-	rc = pm8901_vreg_write(chip, vreg->test_addr,
+	rc = pm8901_vreg_write(vreg, vreg->test_addr,
 			fine_step_reg | REGULATOR_BANK_SEL(2)
 			 | REGULATOR_BANK_WRITE | LDO_TEST_VPROG_UPDATE_MASK,
 			LDO_TEST_FINE_STEP_MASK | REGULATOR_BANK_MASK
@@ -487,12 +471,11 @@
 		int min_uV, int max_uV, unsigned *selector)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 
 	if (vreg->is_nmos)
-		return pm8901_nldo_set_voltage(chip, vreg, min_uV);
+		return pm8901_nldo_set_voltage(vreg, min_uV);
 	else
-		return pm8901_pldo_set_voltage(chip, vreg, min_uV);
+		return pm8901_pldo_set_voltage(vreg, min_uV);
 }
 
 static int pm8901_pldo_get_voltage(struct pm8901_vreg *vreg)
@@ -560,7 +543,6 @@
 static int pm8901_vreg_set_mode(struct regulator_dev *dev, unsigned int mode)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 	unsigned optimum = vreg->optimum;
 	unsigned pc_vote = vreg->pc_vote;
 	unsigned mode_initialized = vreg->mode_initialized;
@@ -614,7 +596,7 @@
 
 	/* Only apply mode setting to hardware if currently enabled. */
 	if (pm8901_vreg_is_enabled(dev))
-		rc = pm8901_vreg_write(chip, vreg->pmr_addr, val,
+		rc = pm8901_vreg_write(vreg, vreg->pmr_addr, val,
 			       VREG_PMR_STATE_MASK | VREG_PMR_PIN_CTRL_ALL_MASK,
 			       &vreg->pmr_reg);
 
@@ -678,11 +660,10 @@
 		int min_uV, int max_uV, unsigned *selector)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 	int rc;
 	u8 val, band;
 
-	if (IS_PMIC_8901_V1(pm8901_rev(chip)))
+	if (IS_PMIC_8901_V1(pm8xxx_get_revision(vreg->dev->parent)))
 		min_uV = PMIC_8901_V1_SCALE(min_uV);
 
 	if (min_uV < SMPS_BAND_1_UV_MIN || min_uV > SMPS_BAND_3_UV_MAX)
@@ -707,13 +688,13 @@
 		band = SMPS_VCTRL_BAND_3;
 	}
 
-	rc = pm8901_vreg_write(chip, vreg->ctrl_addr, band | val,
+	rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, band | val,
 			SMPS_VCTRL_BAND_MASK | SMPS_VCTRL_VPROG_MASK,
 			&vreg->ctrl_reg);
 	if (rc)
 		goto bail;
 
-	rc = pm8901_vreg_write(chip, vreg->pfm_ctrl_addr, band | val,
+	rc = pm8901_vreg_write(vreg, vreg->pfm_ctrl_addr, band | val,
 			SMPS_VCTRL_BAND_MASK | SMPS_VCTRL_VPROG_MASK,
 			&vreg->pfm_ctrl_reg);
 bail:
@@ -726,7 +707,6 @@
 static int pm8901_smps_get_voltage(struct regulator_dev *dev)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 	u8 vprog, band;
 	int ret = 0;
 
@@ -745,7 +725,7 @@
 	else
 		ret = vprog * SMPS_BAND_3_UV_STEP + SMPS_BAND_3_UV_MIN;
 
-	if (IS_PMIC_8901_V1(pm8901_rev(chip)))
+	if (IS_PMIC_8901_V1(pm8xxx_get_revision(vreg->dev->parent)))
 		ret = PMIC_8901_V1_SCALE_INV(ret);
 
 	return ret;
@@ -754,14 +734,13 @@
 static int pm8901_vs_enable(struct regulator_dev *dev)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 	int rc;
 
 	/* Assert enable bit in PMR register. */
 	rc = pm8901_vreg_enable(dev);
 
 	/* Make sure that switch is controlled via PMR register */
-	rc = pm8901_vreg_write(chip, vreg->ctrl_addr, VS_CTRL_USE_PMR,
+	rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, VS_CTRL_USE_PMR,
 			VS_CTRL_ENABLE_MASK, &vreg->ctrl_reg);
 	if (rc)
 		print_write_error(vreg, rc, __func__);
@@ -772,14 +751,13 @@
 static int pm8901_vs_disable(struct regulator_dev *dev)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 	int rc;
 
 	/* Disassert enable bit in PMR register. */
 	rc = pm8901_vreg_disable(dev);
 
 	/* Make sure that switch is controlled via PMR register */
-	rc = pm8901_vreg_write(chip, vreg->ctrl_addr, VS_CTRL_USE_PMR,
+	rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, VS_CTRL_USE_PMR,
 			VS_CTRL_ENABLE_MASK, &vreg->ctrl_reg);
 	if (rc)
 		print_write_error(vreg, rc, __func__);
@@ -787,52 +765,6 @@
 	return rc;
 }
 
-static int pm8901_mpp_enable(struct regulator_dev *dev)
-{
-	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	int out_val;
-	int rc;
-
-	out_val = (vreg->pdata->active_high
-		   ? PM_MPP_DOUT_CTL_HIGH : PM_MPP_DOUT_CTL_LOW);
-
-	rc = pm8901_mpp_config(vreg->mpp_id, PM_MPP_TYPE_D_OUTPUT,
-			PM8901_MPP_DIG_LEVEL_VPH, out_val);
-
-	if (rc)
-		pr_err("%s: pm8901_mpp_config failed, rc=%d\n", __func__, rc);
-	else
-		vreg->state = 1;
-
-	return rc;
-}
-
-static int pm8901_mpp_disable(struct regulator_dev *dev)
-{
-	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	int out_val;
-	int rc;
-
-	out_val = (vreg->pdata->active_high
-		   ? PM_MPP_DOUT_CTL_LOW : PM_MPP_DOUT_CTL_HIGH);
-
-	rc = pm8901_mpp_config(vreg->mpp_id, PM_MPP_TYPE_D_OUTPUT,
-			PM8901_MPP_DIG_LEVEL_VPH, out_val);
-
-	if (rc)
-		pr_err("%s: pm8901_mpp_config failed, rc=%d\n", __func__, rc);
-	else
-		vreg->state = 0;
-
-	return rc;
-}
-
-static int pm8901_mpp_is_enabled(struct regulator_dev *dev)
-{
-	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	return vreg->state;
-}
-
 static struct regulator_ops pm8901_ldo_ops = {
 	.enable = pm8901_vreg_enable,
 	.disable = pm8901_ldo_disable,
@@ -863,12 +795,6 @@
 	.get_mode = pm8901_vreg_get_mode,
 };
 
-static struct regulator_ops pm8901_mpp_ops = {
-	.enable = pm8901_mpp_enable,
-	.disable = pm8901_mpp_disable,
-	.is_enabled = pm8901_mpp_is_enabled,
-};
-
 #define VREG_DESCRIP(_id, _name, _ops) \
 	[_id] = { \
 		.name = _name, \
@@ -893,8 +819,6 @@
 	VREG_DESCRIP(PM8901_VREG_ID_S3, "8901_s3", &pm8901_smps_ops),
 	VREG_DESCRIP(PM8901_VREG_ID_S4, "8901_s4", &pm8901_smps_ops),
 
-	VREG_DESCRIP(PM8901_VREG_ID_MPP0,     "8901_mpp0",     &pm8901_mpp_ops),
-
 	VREG_DESCRIP(PM8901_VREG_ID_LVS0,     "8901_lvs0",     &pm8901_vs_ops),
 	VREG_DESCRIP(PM8901_VREG_ID_LVS1,     "8901_lvs1",     &pm8901_vs_ops),
 	VREG_DESCRIP(PM8901_VREG_ID_LVS2,     "8901_lvs2",     &pm8901_vs_ops),
@@ -904,7 +828,7 @@
 	VREG_DESCRIP(PM8901_VREG_ID_HDMI_MVS, "8901_hdmi_mvs", &pm8901_vs_ops),
 };
 
-static int pm8901_init_ldo(struct pm8901_chip *chip, struct pm8901_vreg *vreg)
+static int pm8901_init_ldo(struct pm8901_vreg *vreg)
 {
 	int rc = 0, i;
 	u8 bank;
@@ -912,11 +836,12 @@
 	/* Store current regulator register values. */
 	for (i = 0; i < LDO_TEST_BANKS; i++) {
 		bank = REGULATOR_BANK_SEL(i);
-		rc = pm8901_write(chip, vreg->test_addr, &bank, 1);
+		rc = pm8xxx_writeb(vreg->dev->parent, vreg->test_addr, bank);
 		if (rc)
 			goto bail;
 
-		rc = pm8901_read(chip, vreg->test_addr, &vreg->test_reg[i], 1);
+		rc = pm8xxx_readb(vreg->dev->parent, vreg->test_addr,
+							&vreg->test_reg[i]);
 		if (rc)
 			goto bail;
 
@@ -924,30 +849,30 @@
 	}
 
 	/* Set pull down enable based on platform data. */
-	rc = pm8901_vreg_write(chip, vreg->ctrl_addr,
+	rc = pm8901_vreg_write(vreg, vreg->ctrl_addr,
 		     (vreg->pdata->pull_down_enable ? LDO_PULL_DOWN_ENABLE : 0),
 		     LDO_PULL_DOWN_ENABLE_MASK, &vreg->ctrl_reg);
 bail:
 	return rc;
 }
 
-static int pm8901_init_smps(struct pm8901_chip *chip, struct pm8901_vreg *vreg)
+static int pm8901_init_smps(struct pm8901_vreg *vreg)
 {
 	int rc;
 
 	/* Store current regulator register values. */
-	rc = pm8901_read(chip, vreg->pfm_ctrl_addr,
-			 &vreg->pfm_ctrl_reg, 1);
+	rc = pm8xxx_readb(vreg->dev->parent, vreg->pfm_ctrl_addr,
+					 &vreg->pfm_ctrl_reg);
 	if (rc)
 		goto bail;
 
-	rc = pm8901_read(chip, vreg->pwr_cnfg_addr,
-			 &vreg->pwr_cnfg_reg, 1);
+	rc = pm8xxx_readb(vreg->dev->parent, vreg->pwr_cnfg_addr,
+				 &vreg->pwr_cnfg_reg);
 	if (rc)
 		goto bail;
 
 	/* Set pull down enable based on platform data. */
-	rc = pm8901_vreg_write(chip, vreg->pwr_cnfg_addr,
+	rc = pm8901_vreg_write(vreg, vreg->pwr_cnfg_addr,
 		    (vreg->pdata->pull_down_enable ? SMPS_PULL_DOWN_ENABLE : 0),
 		    SMPS_PULL_DOWN_ENABLE_MASK, &vreg->pwr_cnfg_reg);
 
@@ -955,33 +880,30 @@
 	return rc;
 }
 
-static int pm8901_init_vs(struct pm8901_chip *chip, struct pm8901_vreg *vreg)
+static int pm8901_init_vs(struct pm8901_vreg *vreg)
 {
 	int rc = 0;
 
 	/* Set pull down enable based on platform data. */
-	rc = pm8901_vreg_write(chip, vreg->ctrl_addr,
+	rc = pm8901_vreg_write(vreg, vreg->ctrl_addr,
 		      (vreg->pdata->pull_down_enable ? VS_PULL_DOWN_ENABLE : 0),
 		      VS_PULL_DOWN_ENABLE_MASK, &vreg->ctrl_reg);
 
 	return rc;
 }
 
-static int pm8901_init_regulator(struct pm8901_chip *chip,
-		struct pm8901_vreg *vreg)
+static int pm8901_init_regulator(struct pm8901_vreg *vreg)
 {
 	int rc;
 
 	/* Store current regulator register values. */
-	if (vreg->type != REGULATOR_TYPE_MPP) {
-		rc = pm8901_read(chip, vreg->ctrl_addr, &vreg->ctrl_reg, 1);
-		if (rc)
-			goto bail;
+	rc = pm8xxx_readb(vreg->dev->parent, vreg->ctrl_addr, &vreg->ctrl_reg);
+	if (rc)
+		goto bail;
 
-		rc = pm8901_read(chip, vreg->pmr_addr, &vreg->pmr_reg, 1);
-		if (rc)
-			goto bail;
-	}
+	rc = pm8xxx_readb(vreg->dev->parent, vreg->pmr_addr, &vreg->pmr_reg);
+	if (rc)
+		goto bail;
 
 	/* Set initial mode based on hardware state. */
 	if ((vreg->pmr_reg & VREG_PMR_STATE_MASK) == VREG_PMR_STATE_LPM)
@@ -992,11 +914,11 @@
 	vreg->mode_initialized = 0;
 
 	if (vreg->type == REGULATOR_TYPE_LDO)
-		rc = pm8901_init_ldo(chip, vreg);
+		rc = pm8901_init_ldo(vreg);
 	else if (vreg->type == REGULATOR_TYPE_SMPS)
-		rc = pm8901_init_smps(chip, vreg);
+		rc = pm8901_init_smps(vreg);
 	else if (vreg->type == REGULATOR_TYPE_VS)
-		rc = pm8901_init_vs(chip, vreg);
+		rc = pm8901_init_vs(vreg);
 bail:
 	if (rc)
 		pr_err("%s: pm8901_read/write failed; initial register states "
@@ -1008,7 +930,6 @@
 static int __devinit pm8901_vreg_probe(struct platform_device *pdev)
 {
 	struct regulator_desc *rdesc;
-	struct pm8901_chip *chip;
 	struct pm8901_vreg *vreg;
 	const char *reg_name = NULL;
 	int rc = 0;
@@ -1017,14 +938,13 @@
 		return -EINVAL;
 
 	if (pdev->id >= 0 && pdev->id < PM8901_VREG_MAX) {
-		chip = dev_get_drvdata(pdev->dev.parent);
 		rdesc = &pm8901_vreg_descrip[pdev->id];
 		vreg = &pm8901_vreg[pdev->id];
 		vreg->pdata = pdev->dev.platform_data;
-		vreg->chip = chip;
 		reg_name = pm8901_vreg_descrip[pdev->id].name;
+		vreg->dev = &pdev->dev;
 
-		rc = pm8901_init_regulator(chip, vreg);
+		rc = pm8901_init_regulator(vreg);
 		if (rc)
 			goto bail;
 
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index d8003bf..a541d8b 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -1876,7 +1876,7 @@
 			*ctrlw = maxctrlw1;
 		}
 	} else {
-		struct slim_ich *slc1;
+		struct slim_ich *slc1 = NULL;
 		struct slim_ich *slc3 = ctrl->sched.chc3[coeff3];
 		u32 expshft = SLIM_MAX_CLK_GEAR - clkgear;
 		int curexp, finalexp, exp1;
diff --git a/drivers/thermal/msm_tsens.c b/drivers/thermal/msm_tsens.c
index d9a6efc..401ad88 100644
--- a/drivers/thermal/msm_tsens.c
+++ b/drivers/thermal/msm_tsens.c
@@ -511,7 +511,6 @@
 	reg = readl_relaxed(TSENS_CNTL_ADDR);
 	writel_relaxed(reg | TSENS_SW_RST, TSENS_CNTL_ADDR);
 	reg |= TSENS_SLP_CLK_ENA | TSENS_EN | (TSENS_MEASURE_PERIOD << 16) |
-		TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR |
 		TSENS_MIN_STATUS_MASK | TSENS_MAX_STATUS_MASK |
 		(((1 << TSENS_NUM_SENSORS) - 1) << 3);
 
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index a094b4e..9e1e388 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -642,9 +642,6 @@
 	vid = msm_hsl_port->ver_id;
 	msm_hsl_write(port, baud_code, regmap[vid][UARTDM_CSR]);
 
-	if (vid == UARTDM_VERSION_14)
-		rxstale = 5000;
-
 	/* RX stale watermark */
 	watermark = UARTDM_IPR_STALE_LSB_BMSK & rxstale;
 	watermark |= UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK & (rxstale << 2);
diff --git a/drivers/usb/gadget/msm72k_udc.c b/drivers/usb/gadget/msm72k_udc.c
index 0c42292..ea62262 100644
--- a/drivers/usb/gadget/msm72k_udc.c
+++ b/drivers/usb/gadget/msm72k_udc.c
@@ -116,6 +116,9 @@
 	*/
 	unsigned char bit;
 	unsigned char num;
+	unsigned long dTD_update_fail_count;
+	unsigned long false_prime_fail_count;
+	unsigned actual_prime_fail_count;
 
 	unsigned wedged:1;
 	/* pointers to DMA transfer list area */
@@ -195,6 +198,7 @@
 	unsigned phy_status;
 	unsigned phy_fail_count;
 	unsigned prime_fail_count;
+	unsigned long dTD_update_fail_count;
 
 	struct usb_gadget		gadget;
 	struct usb_gadget_driver	*driver;
@@ -585,6 +589,7 @@
 
 	spin_lock_irqsave(&ui->lock, flags);
 
+	ept->false_prime_fail_count++;
 	if ((readl_relaxed(USB_ENDPTPRIME) & n)) {
 		/*
 		 * ---- UNLIKELY ---
@@ -602,6 +607,7 @@
 	rmb();
 	if (ept->req && (ept->req->item->info & INFO_ACTIVE)) {
 		ui->prime_fail_count++;
+		ept->actual_prime_fail_count++;
 		pr_err("%s(): ept%d%s prime failed. ept: config: %x"
 				"active: %x next: %x info: %x\n",
 				__func__, ept->num,
@@ -1131,6 +1137,8 @@
 		if (info & INFO_ACTIVE) {
 			if (req_dequeue) {
 				req_dequeue = 0;
+				ui->dTD_update_fail_count++;
+				ept->dTD_update_fail_count++;
 				udelay(10);
 				goto dequeue;
 			} else {
@@ -1886,21 +1894,91 @@
 	.write = debug_write_release_wlocks,
 };
 
+static ssize_t debug_reprime_ep(struct file *file, const char __user *ubuf,
+				 size_t count, loff_t *ppos)
+{
+	struct usb_info *ui = file->private_data;
+	struct msm_endpoint *ept;
+	char kbuf[10];
+	unsigned int ep_num, dir;
+	unsigned long flags;
+	unsigned n, i;
+
+	memset(kbuf, 0, 10);
+
+	if (copy_from_user(kbuf, ubuf, count > 10 ? 10 : count))
+		return -EFAULT;
+
+	if (sscanf(kbuf, "%u %u", &ep_num, &dir) != 2)
+		return -EINVAL;
+
+	if (dir)
+		i = ep_num + 16;
+	else
+		i = ep_num;
+
+	spin_lock_irqsave(&ui->lock, flags);
+	ept = ui->ept + i;
+	n = 1 << ept->bit;
+
+	if ((readl_relaxed(USB_ENDPTPRIME) & n))
+		goto out;
+
+	if (readl_relaxed(USB_ENDPTSTAT) & n)
+		goto out;
+
+	/* clear speculative loads on item->info */
+	rmb();
+	if (ept->req && (ept->req->item->info & INFO_ACTIVE)) {
+		pr_err("%s(): ept%d%s prime failed. ept: config: %x"
+				"active: %x next: %x info: %x\n",
+				__func__, ept->num,
+				ept->flags & EPT_FLAG_IN ? "in" : "out",
+				ept->head->config, ept->head->active,
+				ept->head->next, ept->head->info);
+		writel_relaxed(n, USB_ENDPTPRIME);
+	}
+out:
+	spin_unlock_irqrestore(&ui->lock, flags);
+
+	return count;
+}
+
+static char buffer[512];
 static ssize_t debug_prime_fail_read(struct file *file, char __user *ubuf,
 				 size_t count, loff_t *ppos)
 {
 	struct usb_info *ui = file->private_data;
-	char kbuf[10];
-	size_t c = 0;
+	char *buf = buffer;
+	unsigned long flags;
+	struct msm_endpoint *ept;
+	int n;
+	int i = 0;
 
-	memset(kbuf, 0, 10);
+	spin_lock_irqsave(&ui->lock, flags);
+	for (n = 0; n < 32; n++) {
+		ept = ui->ept + n;
+		if (ept->ep.maxpacket == 0)
+			continue;
 
-	c = scnprintf(kbuf, 10, "%d", ui->prime_fail_count);
+		i += scnprintf(buf + i, PAGE_SIZE - i,
+			"ept%d %s false_prime_count=%lu prime_fail_count=%d dtd_fail_count=%lu\n",
+			ept->num, (ept->flags & EPT_FLAG_IN) ? "in " : "out",
+			ept->false_prime_fail_count,
+			ept->actual_prime_fail_count,
+			ept->dTD_update_fail_count);
+	}
 
-	if (copy_to_user(ubuf, kbuf, c))
-		return -EFAULT;
+	i += scnprintf(buf + i, PAGE_SIZE - i,
+			   "dTD_update_fail count: %lu\n",
+			    ui->dTD_update_fail_count);
 
-	return c;
+	i += scnprintf(buf + i, PAGE_SIZE - i,
+			   "prime_fail count: %d\n", ui->prime_fail_count);
+
+	spin_unlock_irqrestore(&ui->lock, flags);
+
+	return simple_read_from_buffer(ubuf, count, ppos, buf, i);
 }
 
 static int debug_prime_fail_open(struct inode *inode, struct file *file)
@@ -1912,6 +1990,7 @@
 const struct file_operations prime_fail_ops = {
 	.open = debug_prime_fail_open,
 	.read = debug_prime_fail_read,
+	.write = debug_reprime_ep,
 };
 
 static void usb_debugfs_init(struct usb_info *ui)
@@ -1926,7 +2005,7 @@
 	debugfs_create_file("cycle", 0222, dent, ui, &debug_cycle_ops);
 	debugfs_create_file("release_wlocks", 0666, dent, ui,
 						&debug_wlocks_ops);
-	debugfs_create_file("prime_fail_countt", 0222, dent, ui,
+	debugfs_create_file("prime_fail_countt", 0666, dent, ui,
 						&prime_fail_ops);
 }
 #else
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index c55ba6e..2466246 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1850,7 +1850,7 @@
 	struct msm_otg *motg = the_msm_otg;
 
 	/* We depend on PMIC for only VBUS ON interrupt */
-	if (!atomic_read(&motg->in_lpm) || !online)
+	if (!atomic_read(&motg->in_lpm) || !online || motg->async_int)
 		return;
 
 	/*
diff --git a/drivers/video/msm/mdp4_overlay_writeback.c b/drivers/video/msm/mdp4_overlay_writeback.c
index 4fcff20..cd027e9 100644
--- a/drivers/video/msm/mdp4_overlay_writeback.c
+++ b/drivers/video/msm/mdp4_overlay_writeback.c
@@ -85,7 +85,7 @@
 		ptype = mdp4_overlay_format2type(format);
 		if (ptype < 0)
 			pr_err("%s: format2type failed\n", __func__);
-		pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER1, 0);
+		pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER1);
 		if (pipe == NULL)
 			pr_info("%s: pipe_alloc failed\n", __func__);
 		pipe->pipe_used++;
@@ -331,8 +331,6 @@
 				(unsigned int)writeback_pipe->blt_addr);
 		mdp4_writeback_kickoff_ui(mfd, writeback_pipe);
 
-		mdp4_stat.kickoff_writeback++;
-
 		/* signal if pan function is waiting for the
 		 * update completion */
 		if (mfd->pan_waiting) {
diff --git a/drivers/net/wireless/wcnss/wcnss_riva.h b/drivers/video/msm/mhl_api.h
similarity index 61%
copy from drivers/net/wireless/wcnss/wcnss_riva.h
copy to drivers/video/msm/mhl_api.h
index e037f58..3f70dac 100644
--- a/drivers/net/wireless/wcnss/wcnss_riva.h
+++ b/drivers/video/msm/mhl_api.h
@@ -1,3 +1,4 @@
+
 /* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -8,24 +9,18 @@
  * 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 __MHL_API_H__
+#define __MHL_API_H__
 
-#ifndef _WCNSS_RIVA_H_
-#define _WCNSS_RIVA_H_
+#ifdef CONFIG_MHL
+bool mhl_is_connected(void);
+#else
+static bool mhl_is_connected(void)
+{
+	return false;
+}
+#endif
 
-#include <linux/device.h>
-
-enum wcnss_opcode {
-	WCNSS_WLAN_SWITCH_OFF = 0,
-	WCNSS_WLAN_SWITCH_ON,
-};
-
-struct wcnss_wlan_config {
-	int		use_48mhz_xo;
-};
-
-int wcnss_wlan_power(struct device *dev,
-		struct wcnss_wlan_config *cfg,
-		enum wcnss_opcode opcode);
-
-#endif /* _WCNSS_RIVA_H_ */
+#endif /* __MHL_API_H__ */
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index a8aa44a..29f178d 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -901,6 +901,9 @@
 			property_value);
 		vcd_status = VCD_S_SUCCESS;
 	break;
+	case VCD_I_META_BUFFER_MODE:
+		vcd_status = VCD_S_SUCCESS;
+		break;
 	default:
 		DDL_MSG_ERROR("INVALID ID %d\n", (int)property_hdr->prop_id);
 		vcd_status = VCD_ERR_ILLEGAL_OP;
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index 184da27..65f9b54 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -36,14 +36,9 @@
 
 
 
-#if DEBUG
-#define DBG(x...) printk(KERN_DEBUG x)
-#else
-#define DBG(x...)
-#endif
-
-#define INFO(x...) printk(KERN_INFO x)
-#define ERR(x...) printk(KERN_ERR x)
+#define DBG(x...) pr_debug(x)
+#define INFO(x...) pr_info(x)
+#define ERR(x...) pr_err(x)
 
 #define VID_DEC_NAME		"msm_vidc_dec"
 
@@ -359,49 +354,49 @@
 
 	switch (event) {
 	case VCD_EVT_IND_OUTPUT_RECONFIG:
-		INFO("msm_vidc_dec: Sending VDEC_MSG_EVT_CONFIG_CHANGED"
+		DBG("msm_vidc_dec: Sending VDEC_MSG_EVT_CONFIG_CHANGED"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_EVT_CONFIG_CHANGED;
 		break;
 	case VCD_EVT_IND_RESOURCES_LOST:
-		INFO("msm_vidc_dec: Sending VDEC_EVT_RESOURCES_LOST"
+		DBG("msm_vidc_dec: Sending VDEC_EVT_RESOURCES_LOST"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode = VDEC_EVT_RESOURCES_LOST;
 		break;
 	case VCD_EVT_RESP_FLUSH_INPUT_DONE:
-		INFO("msm_vidc_dec: Sending VDEC_MSG_RESP_FLUSH_INPUT_DONE"
+		DBG("msm_vidc_dec: Sending VDEC_MSG_RESP_FLUSH_INPUT_DONE"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode =
 		    VDEC_MSG_RESP_FLUSH_INPUT_DONE;
 		break;
 	case VCD_EVT_RESP_FLUSH_OUTPUT_DONE:
-		INFO("msm_vidc_dec: Sending VDEC_MSG_RESP_FLUSH_OUTPUT_DONE"
+		DBG("msm_vidc_dec: Sending VDEC_MSG_RESP_FLUSH_OUTPUT_DONE"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode =
 		    VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
 		break;
 	case VCD_EVT_IND_HWERRFATAL:
-		INFO("msm_vidc_dec: Sending VDEC_MSG_EVT_HW_ERROR"
+		DBG("msm_vidc_dec: Sending VDEC_MSG_EVT_HW_ERROR"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_EVT_HW_ERROR;
 		break;
 	case VCD_EVT_RESP_START:
-		INFO("msm_vidc_dec: Sending VDEC_MSG_RESP_START_DONE"
+		DBG("msm_vidc_dec: Sending VDEC_MSG_RESP_START_DONE"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_RESP_START_DONE;
 		break;
 	case VCD_EVT_RESP_STOP:
-		INFO("msm_vidc_dec: Sending VDEC_MSG_RESP_STOP_DONE"
+		DBG("msm_vidc_dec: Sending VDEC_MSG_RESP_STOP_DONE"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_RESP_STOP_DONE;
 		break;
 	case VCD_EVT_RESP_PAUSE:
-		INFO("msm_vidc_dec: Sending VDEC_MSG_RESP_PAUSE_DONE"
+		DBG("msm_vidc_dec: Sending VDEC_MSG_RESP_PAUSE_DONE"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_RESP_PAUSE_DONE;
 		break;
 	case VCD_EVT_IND_INFO_OUTPUT_RECONFIG:
-		INFO("msm_vidc_dec: Sending VDEC_MSG_EVT_INFO_CONFIG_CHANGED"
+		DBG("msm_vidc_dec: Sending VDEC_MSG_EVT_INFO_CONFIG_CHANGED"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode =
 			 VDEC_MSG_EVT_INFO_CONFIG_CHANGED;
@@ -1027,11 +1022,11 @@
 	}
 
 	if (pause) {
-		INFO("msm_vidc_dec: PAUSE command from client = %p\n",
+		DBG("msm_vidc_dec: PAUSE command from client = %p\n",
 			 client_ctx);
 		vcd_status = vcd_pause(client_ctx->vcd_handle);
 	} else{
-		INFO("msm_vidc_dec: RESUME command from client = %p\n",
+		DBG("msm_vidc_dec: RESUME command from client = %p\n",
 			 client_ctx);
 		vcd_status = vcd_resume(client_ctx->vcd_handle);
 	}
@@ -1048,7 +1043,7 @@
 	struct vid_dec_msg *vdec_msg = NULL;
 	u32 vcd_status;
 
-	INFO("msm_vidc_dec: Inside %s()", __func__);
+	DBG("msm_vidc_dec: Inside %s()", __func__);
 	if (!client_ctx) {
 		ERR("\n Invalid client_ctx");
 		return false;
@@ -1056,7 +1051,7 @@
 
 	if (start) {
 		if (client_ctx->seq_header_set) {
-			INFO("%s(): Seq Hdr set: Send START_DONE to client",
+			DBG("%s(): Seq Hdr set: Send START_DONE to client",
 				 __func__);
 			vdec_msg = kzalloc(sizeof(*vdec_msg), GFP_KERNEL);
 			if (!vdec_msg) {
@@ -1078,7 +1073,7 @@
 			    client_ctx);
 
 		} else {
-			INFO("%s(): Calling decode_start()", __func__);
+			DBG("%s(): Calling decode_start()", __func__);
 			vcd_status =
 			    vcd_decode_start(client_ctx->vcd_handle, NULL);
 
@@ -1089,7 +1084,7 @@
 			}
 		}
 	} else {
-		INFO("%s(): Calling vcd_stop()", __func__);
+		DBG("%s(): Calling vcd_stop()", __func__);
 		mutex_lock(&vid_dec_device_p->lock);
 		vcd_status = VCD_ERR_FAIL;
 		if (!client_ctx->stop_called) {
@@ -1207,7 +1202,7 @@
 {
 	u32 vcd_status = VCD_ERR_FAIL;
 
-	INFO("msm_vidc_dec: %s() called with dir = %u", __func__,
+	DBG("msm_vidc_dec: %s() called with dir = %u", __func__,
 		 flush_dir);
 	if (!client_ctx) {
 		ERR("\n Invalid client_ctx");
@@ -1802,7 +1797,7 @@
 	struct vid_dec_msg *vdec_msg;
 	u32 vcd_status;
 
-	INFO("msm_vidc_dec: Inside %s()", __func__);
+	DBG("msm_vidc_dec: Inside %s()", __func__);
 	if (!client_ctx || (!client_ctx->vcd_handle)) {
 		ERR("\n Invalid client_ctx");
 		return false;
@@ -1849,7 +1844,7 @@
 	u32 vcd_status = VCD_ERR_FAIL;
 	u8 client_count = 0;
 
-	INFO("msm_vidc_dec: Inside %s()", __func__);
+	DBG("msm_vidc_dec: Inside %s()", __func__);
 	mutex_lock(&vid_dec_device_p->lock);
 
 	client_count = vcd_get_num_of_clients();
@@ -1912,13 +1907,13 @@
 {
 	struct video_client_ctx *client_ctx = file->private_data;
 
-	INFO("msm_vidc_dec: Inside %s()", __func__);
+	DBG("msm_vidc_dec: Inside %s()", __func__);
 	vid_dec_close_client(client_ctx);
 	vidc_release_firmware();
 #ifndef USE_RES_TRACKER
 	vidc_disable_clk();
 #endif
-	INFO("msm_vidc_dec: Return from %s()", __func__);
+	DBG("msm_vidc_dec: Return from %s()", __func__);
 	return 0;
 }
 
@@ -1953,7 +1948,7 @@
 	u32 i;
 
 	/* init_timer(&hw_timer); */
-	INFO("msm_vidc_dec: Inside %s()", __func__);
+	DBG("msm_vidc_dec: Inside %s()", __func__);
 	vid_dec_device_p->num_clients = 0;
 
 	for (i = 0; i < VIDC_MAX_NUM_CLIENTS; i++) {
@@ -1995,7 +1990,7 @@
 	int rc = 0;
 	struct device *class_devp;
 
-	INFO("msm_vidc_dec: Inside %s()", __func__);
+	DBG("msm_vidc_dec: Inside %s()", __func__);
 	vid_dec_device_p = kzalloc(sizeof(struct vid_dec_dev), GFP_KERNEL);
 	if (!vid_dec_device_p) {
 		ERR("%s Unable to allocate memory for vid_dec_dev\n",
@@ -2056,13 +2051,13 @@
 
 static void __exit vid_dec_exit(void)
 {
-	INFO("msm_vidc_dec: Inside %s()", __func__);
+	DBG("msm_vidc_dec: Inside %s()", __func__);
 	cdev_del(&(vid_dec_device_p->cdev));
 	device_destroy(vid_dec_class, vid_dec_dev_num);
 	class_destroy(vid_dec_class);
 	unregister_chrdev_region(vid_dec_dev_num, 1);
 	kfree(vid_dec_device_p);
-	INFO("msm_vidc_dec: Return from %s()", __func__);
+	DBG("msm_vidc_dec: Return from %s()", __func__);
 }
 
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index 1435b86..5ee315f 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -1540,6 +1540,29 @@
 			return -EFAULT;
 		break;
 	}
+	case VEN_IOCTL_SET_METABUFFER_MODE:
+	{
+		u32 metabuffer_mode, vcd_status;
+		struct vcd_property_hdr vcd_property_hdr;
+		struct vcd_property_live live_mode;
+
+		if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+			return -EFAULT;
+		if (copy_from_user(&metabuffer_mode, venc_msg.in,
+			sizeof(metabuffer_mode)))
+			return -EFAULT;
+		vcd_property_hdr.prop_id = VCD_I_META_BUFFER_MODE;
+		vcd_property_hdr.sz =
+			sizeof(struct vcd_property_live);
+		live_mode.live = metabuffer_mode;
+		vcd_status = vcd_set_property(client_ctx->vcd_handle,
+					&vcd_property_hdr, &live_mode);
+		if (vcd_status) {
+			pr_err(" Setting metabuffer mode failed");
+			return -EIO;
+		}
+		break;
+	}
 	case VEN_IOCTL_SET_AC_PREDICTION:
 	case VEN_IOCTL_GET_AC_PREDICTION:
 	case VEN_IOCTL_SET_RVLC:
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
index 973ed48..e00e85f 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -90,13 +90,13 @@
 		return VCD_ERR_ILLEGAL_OP;
 	}
 
-	if (!cctxt->in_buf_pool.entries ||
+	if ((!cctxt->meta_mode && !cctxt->in_buf_pool.entries) ||
 	    !cctxt->out_buf_pool.entries ||
-	    cctxt->in_buf_pool.validated != cctxt->in_buf_pool.count ||
+	    (!cctxt->meta_mode &&
+		 cctxt->in_buf_pool.validated != cctxt->in_buf_pool.count) ||
 	    cctxt->out_buf_pool.validated !=
 	    cctxt->out_buf_pool.count) {
 		VCD_MSG_ERROR("Buffer pool is not completely setup yet");
-
 		return VCD_ERR_BAD_STATE;
 	}
 
@@ -495,6 +495,13 @@
 	rc = ddl_set_property(cctxt->ddl_handle, prop_hdr, prop_val);
 	VCD_FAILED_RETURN(rc, "Failed: ddl_set_property");
 	switch (prop_hdr->prop_id) {
+	case VCD_I_META_BUFFER_MODE:
+		{
+			struct vcd_property_live *live =
+			    (struct vcd_property_live *)prop_val;
+			cctxt->meta_mode = live->live;
+			break;
+		}
 	case VCD_I_LIVE:
 		{
 			struct vcd_property_live *live =
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index b424059..64dec2d 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -208,6 +208,7 @@
 	struct ion_client *vcd_ion_client;
 	u32 vcd_enable_ion;
 	struct vcd_clnt_ctxt *next;
+	u32 meta_mode;
 };
 
 #define VCD_BUFFERPOOL_INUSE_DECREMENT(val) \
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_property.h b/drivers/video/msm/vidc/common/vcd/vcd_property.h
index f51d226..3f7b131 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_property.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_property.h
@@ -47,6 +47,7 @@
 #define VCD_I_GET_H264_MV_SIZE (VCD_START_BASE + 0x1F)
 #define VCD_I_DEC_PICTYPE (VCD_START_BASE + 0x20)
 #define VCD_I_CONT_ON_RECONFIG (VCD_START_BASE + 0x21)
+#define VCD_I_META_BUFFER_MODE (VCD_START_BASE + 0x22)
 
 #define VCD_START_REQ      (VCD_START_BASE + 0x1000)
 #define VCD_I_REQ_IFRAME   (VCD_START_REQ + 0x1)
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 75e0acf..217030f 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -653,7 +653,7 @@
 	VCD_FAILED_RETURN(rc, "Invalid buffer type provided");
 
 	first_frm_recvd &= cctxt->status.mask;
-	if (first_frm_recvd) {
+	if (first_frm_recvd && !cctxt->meta_mode) {
 		VCD_MSG_ERROR(
 			"VCD free buffer called when data path is active");
 		return VCD_ERR_BAD_STATE;
diff --git a/include/linux/fmem.h b/include/linux/fmem.h
new file mode 100644
index 0000000..d4d5cc7
--- /dev/null
+++ b/include/linux/fmem.h
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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 _FMEM_H_
+#define _FMEM_H_
+
+struct fmem_platform_data {
+	unsigned long phys;
+	unsigned long size;
+};
+
+struct fmem_data {
+	unsigned long phys;
+	void *virt;
+	unsigned long size;
+};
+
+enum fmem_state {
+	FMEM_UNINITIALIZED = 0,
+	FMEM_C_STATE,
+	FMEM_T_STATE,
+	FMEM_O_STATE,
+};
+
+struct fmem_data *fmem_get_info(void);
+int fmem_set_state(enum fmem_state);
+void lock_fmem_state(void);
+void unlock_fmem_state(void);
+
+#endif
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 150107b..c22f9b0 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -95,6 +95,7 @@
  * @flags:	flags (see IRQF_* above)
  * @name:	name of the device
  * @dev_id:	cookie to identify the device
+ * @percpu_dev_id:	cookie to identify the device
  * @next:	pointer to the next irqaction for shared interrupts
  * @irq:	interrupt number
  * @dir:	pointer to the proc/irq/NN/name entry
@@ -104,17 +105,18 @@
  * @thread_mask:	bitmask for keeping track of @thread activity
  */
 struct irqaction {
-	irq_handler_t handler;
-	unsigned long flags;
-	void *dev_id;
-	struct irqaction *next;
-	int irq;
-	irq_handler_t thread_fn;
-	struct task_struct *thread;
-	unsigned long thread_flags;
-	unsigned long thread_mask;
-	const char *name;
-	struct proc_dir_entry *dir;
+	irq_handler_t		handler;
+	unsigned long		flags;
+	void			*dev_id;
+	void __percpu		*percpu_dev_id;
+	struct irqaction	*next;
+	int			irq;
+	irq_handler_t		thread_fn;
+	struct task_struct	*thread;
+	unsigned long		thread_flags;
+	unsigned long		thread_mask;
+	const char		*name;
+	struct proc_dir_entry	*dir;
 } ____cacheline_internodealigned_in_smp;
 
 extern irqreturn_t no_action(int cpl, void *dev_id);
@@ -136,6 +138,10 @@
 request_any_context_irq(unsigned int irq, irq_handler_t handler,
 			unsigned long flags, const char *name, void *dev_id);
 
+extern int __must_check
+request_percpu_irq(unsigned int irq, irq_handler_t handler,
+		   const char *devname, void __percpu *percpu_dev_id);
+
 extern void exit_irq_thread(void);
 #else
 
@@ -164,10 +170,18 @@
 	return request_irq(irq, handler, flags, name, dev_id);
 }
 
+static inline int __must_check
+request_percpu_irq(unsigned int irq, irq_handler_t handler,
+		   const char *devname, void __percpu *percpu_dev_id)
+{
+	return request_irq(irq, handler, 0, devname, percpu_dev_id);
+}
+
 static inline void exit_irq_thread(void) { }
 #endif
 
 extern void free_irq(unsigned int, void *);
+extern void free_percpu_irq(unsigned int, void __percpu *);
 
 struct device;
 
@@ -207,7 +221,9 @@
 
 extern void disable_irq_nosync(unsigned int irq);
 extern void disable_irq(unsigned int irq);
+extern void disable_percpu_irq(unsigned int irq);
 extern void enable_irq(unsigned int irq);
+extern void enable_percpu_irq(unsigned int irq, unsigned int type);
 
 /* The following three functions are for the core kernel use only. */
 #ifdef CONFIG_GENERIC_HARDIRQS
diff --git a/include/linux/irq.h b/include/linux/irq.h
index d03bc09..93c601f 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -23,6 +23,7 @@
 #include <linux/errno.h>
 #include <linux/topology.h>
 #include <linux/wait.h>
+#include <linux/module.h>
 
 #include <asm/irq.h>
 #include <asm/ptrace.h>
@@ -65,6 +66,7 @@
  * IRQ_NO_BALANCING		- Interrupt cannot be balanced (affinity set)
  * IRQ_MOVE_PCNTXT		- Interrupt can be migrated from process context
  * IRQ_NESTED_TRHEAD		- Interrupt nests into another thread
+ * IRQ_PER_CPU_DEVID		- Dev_id is a per-cpu variable
  */
 enum {
 	IRQ_TYPE_NONE		= 0x00000000,
@@ -87,12 +89,13 @@
 	IRQ_MOVE_PCNTXT		= (1 << 14),
 	IRQ_NESTED_THREAD	= (1 << 15),
 	IRQ_NOTHREAD		= (1 << 16),
+	IRQ_PER_CPU_DEVID	= (1 << 17),
 };
 
 #define IRQF_MODIFY_MASK	\
 	(IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
 	 IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \
-	 IRQ_PER_CPU | IRQ_NESTED_THREAD)
+	 IRQ_PER_CPU | IRQ_NESTED_THREAD | IRQ_NOTHREAD | IRQ_PER_CPU_DEVID)
 
 #define IRQ_NO_BALANCING_MASK	(IRQ_PER_CPU | IRQ_NO_BALANCING)
 
@@ -371,6 +374,8 @@
 struct irqaction;
 extern int setup_irq(unsigned int irq, struct irqaction *new);
 extern void remove_irq(unsigned int irq, struct irqaction *act);
+extern int setup_percpu_irq(unsigned int irq, struct irqaction *new);
+extern void remove_percpu_irq(unsigned int irq, struct irqaction *act);
 
 extern void irq_cpu_online(void);
 extern void irq_cpu_offline(void);
@@ -398,6 +403,7 @@
 extern void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_simple_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_percpu_irq(unsigned int irq, struct irq_desc *desc);
+extern void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_nested_irq(unsigned int irq);
 
@@ -428,6 +434,8 @@
 	irq_set_chip_and_handler_name(irq, chip, handle, NULL);
 }
 
+extern int irq_set_percpu_devid(unsigned int irq);
+
 extern void
 __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
 		  const char *name);
@@ -489,6 +497,13 @@
 		irq_clear_status_flags(irq, IRQ_NESTED_THREAD);
 }
 
+static inline void irq_set_percpu_devid_flags(unsigned int irq)
+{
+	irq_set_status_flags(irq,
+			     IRQ_NOAUTOEN | IRQ_PER_CPU | IRQ_NOTHREAD |
+			     IRQ_NOPROBE | IRQ_PER_CPU_DEVID);
+}
+
 /* Handle dynamic irq creation and destruction */
 extern unsigned int create_irq_nr(unsigned int irq_want, int node);
 extern int create_irq(void);
@@ -556,7 +571,15 @@
 	return d->msi_desc;
 }
 
-int irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node);
+int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
+		struct module *owner);
+
+static inline int irq_alloc_descs(int irq, unsigned int from, unsigned int cnt,
+		int node)
+{
+	return __irq_alloc_descs(irq, from, cnt, node, THIS_MODULE);
+}
+
 void irq_free_descs(unsigned int irq, unsigned int cnt);
 int irq_reserve_irqs(unsigned int from, unsigned int cnt);
 
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
index 2d921b3..6b69c2c 100644
--- a/include/linux/irqdesc.h
+++ b/include/linux/irqdesc.h
@@ -53,6 +53,7 @@
 	unsigned long		last_unhandled;	/* Aging timer for unhandled count */
 	unsigned int		irqs_unhandled;
 	raw_spinlock_t		lock;
+	struct cpumask		*percpu_enabled;
 #ifdef CONFIG_SMP
 	const struct cpumask	*affinity_hint;
 	struct irq_affinity_notify *affinity_notify;
@@ -66,6 +67,7 @@
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry	*dir;
 #endif
+	struct module		*owner;
 	const char		*name;
 } ____cacheline_internodealigned_in_smp;
 
diff --git a/include/linux/mfd/pm8xxx/pm8921-charger.h b/include/linux/mfd/pm8xxx/pm8921-charger.h
index ef08c47..31fa537 100644
--- a/include/linux/mfd/pm8xxx/pm8921-charger.h
+++ b/include/linux/mfd/pm8xxx/pm8921-charger.h
@@ -104,6 +104,7 @@
 	unsigned int			(*get_batt_capacity_percent) (void);
 	int64_t				batt_id_min;
 	int64_t				batt_id_max;
+	bool				keep_btm_on_suspend;
 	int				trkl_voltage;
 	int				weak_voltage;
 	int				trkl_current;
diff --git a/include/linux/mfd/pmic8901.h b/include/linux/mfd/pmic8901.h
index 5d23edc..932f8da 100644
--- a/include/linux/mfd/pmic8901.h
+++ b/include/linux/mfd/pmic8901.h
@@ -19,51 +19,33 @@
 
 #include <linux/irq.h>
 #include <linux/mfd/core.h>
-
-/* PM8901 interrupt numbers */
-
-#define PM8901_MPPS		4
+#include <linux/mfd/pm8xxx/irq.h>
+#include <linux/mfd/pm8xxx/mpp.h>
+#include <linux/mfd/pm8xxx/tm.h>
+#include <linux/regulator/pmic8901-regulator.h>
 
 #define PM8901_IRQ_BLOCK_BIT(block, bit) ((block) * 8 + (bit))
 
-/* MPPs [0,N) */
-#define PM8901_MPP_IRQ(base, mpp)	((base) + \
-					PM8901_IRQ_BLOCK_BIT(6, (mpp)))
+#define PM8901_NR_IRQS			72
 
-#define PM8901_TEMP_ALARM_IRQ(base)	((base) + PM8901_IRQ_BLOCK_BIT(6, 4))
-#define PM8901_TEMP_HI_ALARM_IRQ(base)	((base) + PM8901_IRQ_BLOCK_BIT(6, 5))
+/* PM8901 MPP */
+#define PM8901_MPP_BLOCK_START		6
+#define PM8901_MPPS			4
+
+/* PM8901 IRQs */
+#define PM8901_MPP_IRQ(mpp)		PM8901_IRQ_BLOCK_BIT(6, (mpp))
+#define PM8901_TEMPSTAT_IRQ		PM8901_IRQ_BLOCK_BIT(6, 4)
+#define PM8901_OVERTEMP_IRQ		PM8901_IRQ_BLOCK_BIT(6, 5)
 
 struct pm8901_chip;
 
 struct pm8901_platform_data {
-	/* This table is only needed for misc interrupts. */
-	int		irq_base;
-	int		irq;
-
-	int		num_subdevs;
-	struct mfd_cell *sub_devices;
-	int		irq_trigger_flags;
+	struct pm8xxx_irq_platform_data *irq_pdata;
+	struct pm8xxx_mpp_platform_data *mpp_pdata;
+	struct pm8901_vreg_pdata	*regulator_pdatas;
+	int				num_regulators;
 };
 
-struct pm8901_gpio_platform_data {
-	int	gpio_base;
-	int	irq_base;
-};
-
-/* chip revision */
-#define PM_8901_REV_1p0			0xF1
-#define PM_8901_REV_1p1			0xF2
-#define PM_8901_REV_2p0			0xF3
-
-int pm8901_read(struct pm8901_chip *pm_chip, u16 addr, u8 *values,
-		unsigned int len);
-int pm8901_write(struct pm8901_chip *pm_chip, u16 addr, u8 *values,
-		 unsigned int len);
-
-int pm8901_rev(struct pm8901_chip *pm_chip);
-
-int pm8901_irq_get_rt_status(struct pm8901_chip *pm_chip, int irq);
-
 #ifdef CONFIG_PMIC8901
 int pm8901_reset_pwr_off(int reset);
 #else
diff --git a/include/linux/msm_vidc_enc.h b/include/linux/msm_vidc_enc.h
index 12c7afd..45199cb 100644
--- a/include/linux/msm_vidc_enc.h
+++ b/include/linux/msm_vidc_enc.h
@@ -435,6 +435,9 @@
 #define VEN_IOCTL_GET_NUMBER_INSTANCES \
 	_IOR(VEN_IOCTLBASE_ENC, 46, struct venc_ioctl_msg)
 
+#define VEN_IOCTL_SET_METABUFFER_MODE \
+	_IOW(VEN_IOCTLBASE_ENC, 47, struct venc_ioctl_msg)
+
 struct venc_switch{
 	unsigned char	status;
 };
diff --git a/include/linux/regulator/pmic8901-regulator.h b/include/linux/regulator/pmic8901-regulator.h
index 953c4ad..ec842bc 100644
--- a/include/linux/regulator/pmic8901-regulator.h
+++ b/include/linux/regulator/pmic8901-regulator.h
@@ -32,23 +32,20 @@
 #define PM8901_VREG_ID_S3	10
 #define PM8901_VREG_ID_S4	11
 
-/* External regulator controlled by MPP pin ids */
-#define PM8901_VREG_ID_MPP0	12
-
 /* Low voltage switch regulator ids */
-#define PM8901_VREG_ID_LVS0	13
-#define PM8901_VREG_ID_LVS1	14
-#define PM8901_VREG_ID_LVS2	15
-#define PM8901_VREG_ID_LVS3	16
+#define PM8901_VREG_ID_LVS0	12
+#define PM8901_VREG_ID_LVS1	13
+#define PM8901_VREG_ID_LVS2	14
+#define PM8901_VREG_ID_LVS3	15
 
 /* Medium voltage switch regulator ids */
-#define PM8901_VREG_ID_MVS0	17
+#define PM8901_VREG_ID_MVS0	16
 
 /* USB OTG voltage switch regulator ids */
-#define PM8901_VREG_ID_USB_OTG	18
+#define PM8901_VREG_ID_USB_OTG	17
 
 /* HDMI medium voltage switch regulator ids */
-#define PM8901_VREG_ID_HDMI_MVS	19
+#define PM8901_VREG_ID_HDMI_MVS	18
 
 #define PM8901_VREG_MAX		(PM8901_VREG_ID_HDMI_MVS + 1)
 
@@ -70,10 +67,10 @@
 
 struct pm8901_vreg_pdata {
 	struct regulator_init_data	init_data;
+	int				id;
 	unsigned			pull_down_enable;
 	unsigned			pin_ctrl;
 	enum pm8901_vreg_pin_fn		pin_fn;
-	unsigned			active_high; /* For use with MPP. */
 };
 
 #endif
diff --git a/include/linux/tspp.h b/include/linux/tspp.h
new file mode 100644
index 0000000..d5a5ffc
--- /dev/null
+++ b/include/linux/tspp.h
@@ -0,0 +1,84 @@
+#ifndef _TSPP_H_
+#define _TSPP_H_
+
+#include <linux/ioctl.h>
+
+#define TSPP_NUM_SYSTEM_KEYS 8
+
+enum tspp_key_parity {
+	TSPP_KEY_PARITY_EVEN,
+	TSPP_KEY_PARITY_ODD
+};
+
+enum tspp_source {
+	TSPP_SOURCE_TSIF0,
+	TSPP_SOURCE_TSIF1,
+	TSPP_SOURCE_MEM,
+	TSPP_SOURCE_NONE = -1
+};
+
+enum tspp_mode {
+	TSPP_MODE_DISABLED,
+	TSPP_MODE_PES,
+	TSPP_MODE_RAW,
+	TSPP_MODE_RAW_NO_SUFFIX
+};
+
+struct tspp_filter {
+	int pid;
+	int mask;
+	enum tspp_mode mode;
+	int priority;	/* 0 - 15 */
+	int decrypt;
+	enum tspp_source source;
+};
+
+struct tspp_select_source {
+	enum tspp_source source;
+};
+
+struct tspp_pid {
+	int pid;
+};
+
+struct tspp_key {
+	enum tspp_key_parity parity;
+	int lsb;
+	int msb;
+};
+
+struct tspp_iv {
+	int data[2];
+};
+
+struct tspp_system_keys {
+	int data[TSPP_NUM_SYSTEM_KEYS];
+};
+
+struct tspp_buffer {
+	int size;
+};
+
+/* defines for IOCTL functions */
+/* read Documentation/ioctl-number.txt */
+/* some random number to avoid coinciding with other ioctl numbers */
+#define TSPP_IOCTL_BASE					0xAA
+#define TSPP_IOCTL_SELECT_SOURCE		\
+	_IOW(TSPP_IOCTL_BASE, 0, struct tspp_select_source)
+#define TSPP_IOCTL_ADD_FILTER			\
+	_IOW(TSPP_IOCTL_BASE, 1, struct tspp_filter)
+#define TSPP_IOCTL_REMOVE_FILTER		\
+	_IOW(TSPP_IOCTL_BASE, 2, struct tspp_pid)
+#define TSPP_IOCTL_SET_KEY				\
+	_IOW(TSPP_IOCTL_BASE, 3, struct tspp_key)
+#define TSPP_IOCTL_SET_IV				\
+	_IOW(TSPP_IOCTL_BASE, 4, struct tspp_iv)
+#define TSPP_IOCTL_SET_SYSTEM_KEYS	\
+	_IOW(TSPP_IOCTL_BASE, 5, struct tspp_system_keys)
+#define TSPP_IOCTL_BUFFER_SIZE		\
+	_IOW(TSPP_IOCTL_BASE, 6, struct tspp_buffer)
+#define TSPP_IOCTL_LOOPBACK			\
+	_IOW(TSPP_IOCTL_BASE, 0xFF, int)
+
+
+#endif /* _TSPP_H_ */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 68fc67c..eb2c543 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -132,6 +132,19 @@
 };
 
 /**
+ * SPS Pipes direction.
+ *
+ * USB_TO_PEER_PERIPHERAL	USB (as Producer) to other
+ *                          peer peripheral.
+ * PEER_PERIPHERAL_TO_USB	Other Peripheral to
+ *                          USB (as consumer).
+ */
+enum usb_bam_pipe_dir {
+	USB_TO_PEER_PERIPHERAL,
+	PEER_PERIPHERAL_TO_USB,
+};
+
+/**
  * struct msm_otg_platform_data - platform device data
  *              for msm_otg driver.
  * @phy_init_seq: PHY configuration sequence. val, reg pairs
@@ -258,4 +271,21 @@
 	unsigned hub_reset;
 };
 
+struct usb_bam_pipe_connect {
+	u32 src_phy_addr;
+	int src_pipe_index;
+	u32 dst_phy_addr;
+	int dst_pipe_index;
+	u32 data_fifo_base_offset;
+	u32 data_fifo_size;
+	u32 desc_fifo_base_offset;
+	u32 desc_fifo_size;
+};
+
+struct msm_usb_bam_platform_data {
+	struct usb_bam_pipe_connect *connections;
+	unsigned long usb_bam_phy_base;
+	unsigned long usb_bam_phy_size;
+	int usb_bam_num_pipes;
+};
 #endif
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index 3b37f85..02c0b95 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -16,6 +16,15 @@
 
 #include <linux/device.h>
 
+enum wcnss_opcode {
+	WCNSS_WLAN_SWITCH_OFF = 0,
+	WCNSS_WLAN_SWITCH_ON,
+};
+
+struct wcnss_wlan_config {
+	int		use_48mhz_xo;
+};
+
 #define WCNSS_WLAN_IRQ_INVALID -1
 
 struct device *wcnss_wlan_get_device(void);
@@ -26,6 +35,11 @@
 				const struct dev_pm_ops *pm_ops);
 void wcnss_wlan_unregister_pm_ops(struct device *dev,
 				const struct dev_pm_ops *pm_ops);
+struct platform_device *wcnss_get_platform_device(void);
+struct wcnss_wlan_config *wcnss_get_wlan_config(void);
+int wcnss_wlan_power(struct device *dev,
+				struct wcnss_wlan_config *cfg,
+				enum wcnss_opcode opcode);
 
 #define wcnss_wlan_get_drvdata(dev) dev_get_drvdata(dev)
 #define wcnss_wlan_set_drvdata(dev, data) dev_set_drvdata((dev), (data))
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 4d5d697..a8b04df 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -159,6 +159,12 @@
 #define MSM_CAM_IOCTL_PICT_PP_DIVERT_DONE \
 	_IOR(MSM_CAM_IOCTL_MAGIC, 47, struct msm_pp_frame *)
 
+#define MSM_CAM_IOCTL_SENSOR_V4l2_S_CTRL \
+	_IOR(MSM_CAM_IOCTL_MAGIC, 48, struct v4l2_control)
+
+#define MSM_CAM_IOCTL_SENSOR_V4l2_QUERY_CTRL \
+	_IOR(MSM_CAM_IOCTL_MAGIC, 49, struct v4l2_queryctrl)
+
 struct msm_mctl_pp_cmd {
 	int32_t  id;
 	uint16_t length;
@@ -821,6 +827,73 @@
 #define CAMERA_EXPOSURE_COMPENSATION_LV3			-6
 #define CAMERA_EXPOSURE_COMPENSATION_LV4			-12
 
+enum msm_v4l2_saturation_level {
+	MSM_V4L2_SATURATION_L0,
+	MSM_V4L2_SATURATION_L1,
+	MSM_V4L2_SATURATION_L2,
+	MSM_V4L2_SATURATION_L3,
+	MSM_V4L2_SATURATION_L4,
+	MSM_V4L2_SATURATION_L5,
+	MSM_V4L2_SATURATION_L6,
+	MSM_V4L2_SATURATION_L7,
+	MSM_V4L2_SATURATION_L8,
+	MSM_V4L2_SATURATION_L9,
+	MSM_V4L2_SATURATION_L10,
+};
+
+enum msm_v4l2_exposure_level {
+	MSM_V4L2_EXPOSURE_N2,
+	MSM_V4L2_EXPOSURE_N1,
+	MSM_V4L2_EXPOSURE_D,
+	MSM_V4L2_EXPOSURE_P1,
+	MSM_V4L2_EXPOSURE_P2,
+};
+
+enum msm_v4l2_sharpness_level {
+	MSM_V4L2_SHARPNESS_L0,
+	MSM_V4L2_SHARPNESS_L1,
+	MSM_V4L2_SHARPNESS_L2,
+	MSM_V4L2_SHARPNESS_L3,
+	MSM_V4L2_SHARPNESS_L4,
+	MSM_V4L2_SHARPNESS_L5,
+	MSM_V4L2_SHARPNESS_L6,
+};
+
+enum msm_v4l2_expo_metering_mode {
+	MSM_V4L2_EXP_FRAME_AVERAGE,
+	MSM_V4L2_EXP_CENTER_WEIGHTED,
+	MSM_V4L2_EXP_SPOT_METERING,
+};
+
+enum msm_v4l2_iso_mode {
+	MSM_V4L2_ISO_AUTO = 0,
+	MSM_V4L2_ISO_DEBLUR,
+	MSM_V4L2_ISO_100,
+	MSM_V4L2_ISO_200,
+	MSM_V4L2_ISO_400,
+	MSM_V4L2_ISO_800,
+	MSM_V4L2_ISO_1600,
+};
+
+enum msm_v4l2_wb_mode {
+	MSM_V4L2_WB_MIN_MINUS_1,
+	MSM_V4L2_WB_AUTO = 1,
+	MSM_V4L2_WB_CUSTOM,
+	MSM_V4L2_WB_INCANDESCENT,
+	MSM_V4L2_WB_FLUORESCENT,
+	MSM_V4L2_WB_DAYLIGHT,
+	MSM_V4L2_WB_CLOUDY_DAYLIGHT,
+	MSM_V4L2_WB_TWILIGHT,
+	MSM_V4L2_WB_SHADE,
+	MSM_V4L2_WB_OFF,
+};
+
+enum msm_v4l2_power_line_frequency {
+	MSM_V4L2_POWER_LINE_OFF,
+	MSM_V4L2_POWER_LINE_60HZ,
+	MSM_V4L2_POWER_LINE_50HZ,
+	MSM_V4L2_POWER_LINE_AUTO,
+};
 
 struct sensor_pict_fps {
 	uint16_t prevfps;
diff --git a/include/media/tavarua.h b/include/media/tavarua.h
index d40829e..b7380bc 100644
--- a/include/media/tavarua.h
+++ b/include/media/tavarua.h
@@ -147,15 +147,26 @@
 	V4L2_CID_PRIVATE_TAVARUA_AF_JUMP,
 	V4L2_CID_PRIVATE_TAVARUA_RSSI_DELTA,
 	V4L2_CID_PRIVATE_TAVARUA_HLSI,
+
 	/*
 	* Here we have IOCTl's that are specific to IRIS
-	* (V4L2_CID_PRIVATE_BASE + 0x1E to V4L2_CID_PRIVATE_BASE + 0x27)
+	* (V4L2_CID_PRIVATE_BASE + 0x1E to V4L2_CID_PRIVATE_BASE + 0x28)
 	*/
-	V4L2_CID_PRIVATE_TAVARUA_SET_NOTCH_FILTER =
-		V4L2_CID_PRIVATE_BASE + 0x28, /* IRIS specific command */
-	V4L2_CID_PRIVATE_TAVARUA_SET_AUDIO_PATH,
-	V4L2_CID_PRIVATE_TAVARUA_DO_CALIBRATION, /* IRIS specific command */
-	V4L2_CID_PRIVATE_TAVARUA_SRCH_ALGORITHM,
+	V4L2_CID_PRIVATE_SOFT_MUTE, /* 0x800001E*/
+	V4L2_CID_PRIVATE_RIVA_ACCS_ADDR,
+	V4L2_CID_PRIVATE_RIVA_ACCS_LEN,
+	V4L2_CID_PRIVATE_RIVA_PEEK,
+	V4L2_CID_PRIVATE_RIVA_POKE,
+	V4L2_CID_PRIVATE_SSBI_ACCS_ADDR,
+	V4L2_CID_PRIVATE_SSBI_PEEK,
+	V4L2_CID_PRIVATE_SSBI_POKE,
+	V4L2_CID_PRIVATE_TX_TONE,
+	V4L2_CID_PRIVATE_RDS_GRP_COUNTERS,
+	V4L2_CID_PRIVATE_SET_NOTCH_FILTER, /* 0x8000028 */
+
+	V4L2_CID_PRIVATE_TAVARUA_SET_AUDIO_PATH, /* 0x8000029 */
+	V4L2_CID_PRIVATE_TAVARUA_DO_CALIBRATION, /* 0x800002A : IRIS command */
+	V4L2_CID_PRIVATE_TAVARUA_SRCH_ALGORITHM, /* 0x800002B */
 
 	V4L2_CID_PRIVATE_TAVARUA_ON_CHANNEL_THRESHOLD =
 		V4L2_CTRL_CLASS_USER + 0x92B,
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 2adc6b5..fe1f47a 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -26,7 +26,7 @@
 int irq_set_chip(unsigned int irq, struct irq_chip *chip)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
 
 	if (!desc)
 		return -EINVAL;
@@ -54,7 +54,7 @@
 int irq_set_irq_type(unsigned int irq, unsigned int type)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
 	int ret = 0;
 
 	if (!desc)
@@ -78,7 +78,7 @@
 int irq_set_handler_data(unsigned int irq, void *data)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
 
 	if (!desc)
 		return -EINVAL;
@@ -98,7 +98,7 @@
 int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
 
 	if (!desc)
 		return -EINVAL;
@@ -119,7 +119,7 @@
 int irq_set_chip_data(unsigned int irq, void *data)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
 
 	if (!desc)
 		return -EINVAL;
@@ -204,6 +204,24 @@
 	}
 }
 
+void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu)
+{
+	if (desc->irq_data.chip->irq_enable)
+		desc->irq_data.chip->irq_enable(&desc->irq_data);
+	else
+		desc->irq_data.chip->irq_unmask(&desc->irq_data);
+	cpumask_set_cpu(cpu, desc->percpu_enabled);
+}
+
+void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu)
+{
+	if (desc->irq_data.chip->irq_disable)
+		desc->irq_data.chip->irq_disable(&desc->irq_data);
+	else
+		desc->irq_data.chip->irq_mask(&desc->irq_data);
+	cpumask_clear_cpu(cpu, desc->percpu_enabled);
+}
+
 static inline void mask_ack_irq(struct irq_desc *desc)
 {
 	if (desc->irq_data.chip->irq_mask_ack)
@@ -553,12 +571,44 @@
 		chip->irq_eoi(&desc->irq_data);
 }
 
+/**
+ * handle_percpu_devid_irq - Per CPU local irq handler with per cpu dev ids
+ * @irq:	the interrupt number
+ * @desc:	the interrupt description structure for this irq
+ *
+ * Per CPU interrupts on SMP machines without locking requirements. Same as
+ * handle_percpu_irq() above but with the following extras:
+ *
+ * action->percpu_dev_id is a pointer to percpu variables which
+ * contain the real device id for the cpu on which this handler is
+ * called
+ */
+void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct irqaction *action = desc->action;
+	void *dev_id = __this_cpu_ptr(action->percpu_dev_id);
+	irqreturn_t res;
+
+	kstat_incr_irqs_this_cpu(irq, desc);
+
+	if (chip->irq_ack)
+		chip->irq_ack(&desc->irq_data);
+
+	trace_irq_handler_entry(irq, action);
+	res = action->handler(irq, dev_id);
+	trace_irq_handler_exit(irq, action, res);
+
+	if (chip->irq_eoi)
+		chip->irq_eoi(&desc->irq_data);
+}
+
 void
 __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
 		  const char *name)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0);
 
 	if (!desc)
 		return;
@@ -602,7 +652,7 @@
 void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
 
 	if (!desc)
 		return;
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 6546431..a73dd6c 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -71,6 +71,8 @@
 extern void irq_shutdown(struct irq_desc *desc);
 extern void irq_enable(struct irq_desc *desc);
 extern void irq_disable(struct irq_desc *desc);
+extern void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu);
+extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu);
 extern void mask_irq(struct irq_desc *desc);
 extern void unmask_irq(struct irq_desc *desc);
 
@@ -114,14 +116,21 @@
 		desc->irq_data.chip->irq_bus_sync_unlock(&desc->irq_data);
 }
 
+#define _IRQ_DESC_CHECK		(1 << 0)
+#define _IRQ_DESC_PERCPU	(1 << 1)
+
+#define IRQ_GET_DESC_CHECK_GLOBAL	(_IRQ_DESC_CHECK)
+#define IRQ_GET_DESC_CHECK_PERCPU	(_IRQ_DESC_CHECK | _IRQ_DESC_PERCPU)
+
 struct irq_desc *
-__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus);
+__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus,
+		    unsigned int check);
 void __irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags, bool bus);
 
 static inline struct irq_desc *
-irq_get_desc_buslock(unsigned int irq, unsigned long *flags)
+irq_get_desc_buslock(unsigned int irq, unsigned long *flags, unsigned int check)
 {
-	return __irq_get_desc_lock(irq, flags, true);
+	return __irq_get_desc_lock(irq, flags, true, check);
 }
 
 static inline void
@@ -131,9 +140,9 @@
 }
 
 static inline struct irq_desc *
-irq_get_desc_lock(unsigned int irq, unsigned long *flags)
+irq_get_desc_lock(unsigned int irq, unsigned long *flags, unsigned int check)
 {
-	return __irq_get_desc_lock(irq, flags, false);
+	return __irq_get_desc_lock(irq, flags, false, check);
 }
 
 static inline void
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 4c60a50..028e377 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -70,7 +70,8 @@
 static inline int desc_node(struct irq_desc *desc) { return 0; }
 #endif
 
-static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node)
+static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node,
+		struct module *owner)
 {
 	int cpu;
 
@@ -86,6 +87,7 @@
 	desc->irq_count = 0;
 	desc->irqs_unhandled = 0;
 	desc->name = NULL;
+	desc->owner = owner;
 	for_each_possible_cpu(cpu)
 		*per_cpu_ptr(desc->kstat_irqs, cpu) = 0;
 	desc_smp_init(desc, node);
@@ -128,7 +130,7 @@
 static inline void free_masks(struct irq_desc *desc) { }
 #endif
 
-static struct irq_desc *alloc_desc(int irq, int node)
+static struct irq_desc *alloc_desc(int irq, int node, struct module *owner)
 {
 	struct irq_desc *desc;
 	gfp_t gfp = GFP_KERNEL;
@@ -147,7 +149,7 @@
 	raw_spin_lock_init(&desc->lock);
 	lockdep_set_class(&desc->lock, &irq_desc_lock_class);
 
-	desc_set_defaults(irq, desc, node);
+	desc_set_defaults(irq, desc, node, owner);
 
 	return desc;
 
@@ -173,13 +175,14 @@
 	kfree(desc);
 }
 
-static int alloc_descs(unsigned int start, unsigned int cnt, int node)
+static int alloc_descs(unsigned int start, unsigned int cnt, int node,
+		       struct module *owner)
 {
 	struct irq_desc *desc;
 	int i;
 
 	for (i = 0; i < cnt; i++) {
-		desc = alloc_desc(start + i, node);
+		desc = alloc_desc(start + i, node, owner);
 		if (!desc)
 			goto err;
 		mutex_lock(&sparse_irq_lock);
@@ -227,7 +230,7 @@
 		nr_irqs = initcnt;
 
 	for (i = 0; i < initcnt; i++) {
-		desc = alloc_desc(i, node);
+		desc = alloc_desc(i, node, NULL);
 		set_bit(i, allocated_irqs);
 		irq_insert_desc(i, desc);
 	}
@@ -261,7 +264,7 @@
 		alloc_masks(&desc[i], GFP_KERNEL, node);
 		raw_spin_lock_init(&desc[i].lock);
 		lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
-		desc_set_defaults(i, &desc[i], node);
+		desc_set_defaults(i, &desc[i], node, NULL);
 	}
 	return arch_early_irq_init();
 }
@@ -276,8 +279,16 @@
 	dynamic_irq_cleanup(irq);
 }
 
-static inline int alloc_descs(unsigned int start, unsigned int cnt, int node)
+static inline int alloc_descs(unsigned int start, unsigned int cnt, int node,
+			      struct module *owner)
 {
+	u32 i;
+
+	for (i = 0; i < cnt; i++) {
+		struct irq_desc *desc = irq_to_desc(start + i);
+
+		desc->owner = owner;
+	}
 	return start;
 }
 
@@ -337,7 +348,8 @@
  * Returns the first irq number or error code
  */
 int __ref
-irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node)
+__irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
+		  struct module *owner)
 {
 	int start, ret;
 
@@ -366,13 +378,13 @@
 
 	bitmap_set(allocated_irqs, start, cnt);
 	mutex_unlock(&sparse_irq_lock);
-	return alloc_descs(start, cnt, node);
+	return alloc_descs(start, cnt, node, owner);
 
 err:
 	mutex_unlock(&sparse_irq_lock);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(irq_alloc_descs);
+EXPORT_SYMBOL_GPL(__irq_alloc_descs);
 
 /**
  * irq_reserve_irqs - mark irqs allocated
@@ -411,11 +423,22 @@
 }
 
 struct irq_desc *
-__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus)
+__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus,
+		    unsigned int check)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 
 	if (desc) {
+		if (check & _IRQ_DESC_CHECK) {
+			if ((check & _IRQ_DESC_PERCPU) &&
+			    !irq_settings_is_per_cpu_devid(desc))
+				return NULL;
+
+			if (!(check & _IRQ_DESC_PERCPU) &&
+			    irq_settings_is_per_cpu_devid(desc))
+				return NULL;
+		}
+
 		if (bus)
 			chip_bus_lock(desc);
 		raw_spin_lock_irqsave(&desc->lock, *flags);
@@ -430,6 +453,25 @@
 		chip_bus_sync_unlock(desc);
 }
 
+int irq_set_percpu_devid(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	if (!desc)
+		return -EINVAL;
+
+	if (desc->percpu_enabled)
+		return -EINVAL;
+
+	desc->percpu_enabled = kzalloc(sizeof(*desc->percpu_enabled), GFP_KERNEL);
+
+	if (!desc->percpu_enabled)
+		return -ENOMEM;
+
+	irq_set_percpu_devid_flags(irq);
+	return 0;
+}
+
 /**
  * dynamic_irq_cleanup - cleanup a dynamically allocated irq
  * @irq:	irq number to initialize
@@ -440,7 +482,7 @@
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
-	desc_set_defaults(irq, desc, desc_node(desc));
+	desc_set_defaults(irq, desc, desc_node(desc), NULL);
 	raw_spin_unlock_irqrestore(&desc->lock, flags);
 }
 
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index b495711..1db1dc6 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -195,7 +195,7 @@
 int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
 
 	if (!desc)
 		return -EINVAL;
@@ -356,7 +356,7 @@
 static int __disable_irq_nosync(unsigned int irq)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
 
 	if (!desc)
 		return -EINVAL;
@@ -448,7 +448,7 @@
 void enable_irq(unsigned int irq)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
 
 	if (!desc)
 		return;
@@ -488,7 +488,7 @@
 int irq_set_irq_wake(unsigned int irq, unsigned int on)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
 	int ret = 0;
 
 	if (!desc)
@@ -555,7 +555,7 @@
 int can_request_irq(unsigned int irq, unsigned long irqflags)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
 	int canrequest = 0;
 
 	if (!desc)
@@ -909,6 +909,8 @@
 
 	if (desc->irq_data.chip == &no_irq_chip)
 		return -ENOSYS;
+	if (!try_module_get(desc->owner))
+		return -ENODEV;
 	/*
 	 * Some drivers like serial.c use request_irq() heavily,
 	 * so we have to be careful not to interfere with a
@@ -932,8 +934,10 @@
 	 */
 	nested = irq_settings_is_nested_thread(desc);
 	if (nested) {
-		if (!new->thread_fn)
-			return -EINVAL;
+		if (!new->thread_fn) {
+			ret = -EINVAL;
+			goto out_mput;
+		}
 		/*
 		 * Replace the primary handler which was provided from
 		 * the driver for non nested interrupt handling by the
@@ -955,8 +959,10 @@
 
 		t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
 				   new->name);
-		if (IS_ERR(t))
-			return PTR_ERR(t);
+		if (IS_ERR(t)) {
+			ret = PTR_ERR(t);
+			goto out_mput;
+		}
 		/*
 		 * We keep the reference to the task struct even if
 		 * the thread dies to avoid that the interrupt code
@@ -1121,6 +1127,8 @@
 			kthread_stop(t);
 		put_task_struct(t);
 	}
+out_mput:
+	module_put(desc->owner);
 	return ret;
 }
 
@@ -1136,6 +1144,8 @@
 	int retval;
 	struct irq_desc *desc = irq_to_desc(irq);
 
+	if (WARN_ON(irq_settings_is_per_cpu_devid(desc)))
+		return -EINVAL;
 	chip_bus_lock(desc);
 	retval = __setup_irq(irq, desc, act);
 	chip_bus_sync_unlock(desc);
@@ -1144,7 +1154,7 @@
 }
 EXPORT_SYMBOL_GPL(setup_irq);
 
- /*
+/*
  * Internal function to unregister an irqaction - used to free
  * regular and special interrupts that are part of the architecture.
  */
@@ -1236,6 +1246,7 @@
 		put_task_struct(action->thread);
 	}
 
+	module_put(desc->owner);
 	return action;
 }
 
@@ -1248,7 +1259,10 @@
  */
 void remove_irq(unsigned int irq, struct irqaction *act)
 {
-	__free_irq(irq, act->dev_id);
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	if (desc && !WARN_ON(irq_settings_is_per_cpu_devid(desc)))
+	    __free_irq(irq, act->dev_id);
 }
 EXPORT_SYMBOL_GPL(remove_irq);
 
@@ -1270,7 +1284,7 @@
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 
-	if (!desc)
+	if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
 		return;
 
 #ifdef CONFIG_SMP
@@ -1348,7 +1362,8 @@
 	if (!desc)
 		return -EINVAL;
 
-	if (!irq_settings_can_request(desc))
+	if (!irq_settings_can_request(desc) ||
+	    WARN_ON(irq_settings_is_per_cpu_devid(desc)))
 		return -EINVAL;
 
 	if (!handler) {
@@ -1446,3 +1461,194 @@
 	}
 }
 EXPORT_SYMBOL_GPL(irq_set_pending);
+
+void enable_percpu_irq(unsigned int irq, unsigned int type)
+{
+	unsigned int cpu = smp_processor_id();
+	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_PERCPU);
+
+	if (!desc)
+		return;
+
+	type &= IRQ_TYPE_SENSE_MASK;
+	if (type != IRQ_TYPE_NONE) {
+		int ret;
+
+		ret = __irq_set_trigger(desc, irq, type);
+
+		if (ret) {
+			WARN(1, "failed to set type for IRQ%d\n", irq);
+			goto out;
+		}
+	}
+
+	irq_percpu_enable(desc, cpu);
+out:
+	irq_put_desc_unlock(desc, flags);
+}
+
+void disable_percpu_irq(unsigned int irq)
+{
+	unsigned int cpu = smp_processor_id();
+	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_PERCPU);
+
+	if (!desc)
+		return;
+
+	irq_percpu_disable(desc, cpu);
+	irq_put_desc_unlock(desc, flags);
+}
+
+/*
+ * Internal function to unregister a percpu irqaction.
+ */
+static struct irqaction *__free_percpu_irq(unsigned int irq, void __percpu *dev_id)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	struct irqaction *action;
+	unsigned long flags;
+
+	WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq);
+
+	if (!desc)
+		return NULL;
+
+	raw_spin_lock_irqsave(&desc->lock, flags);
+
+	action = desc->action;
+	if (!action || action->percpu_dev_id != dev_id) {
+		WARN(1, "Trying to free already-free IRQ %d\n", irq);
+		goto bad;
+	}
+
+	if (!cpumask_empty(desc->percpu_enabled)) {
+		WARN(1, "percpu IRQ %d still enabled on CPU%d!\n",
+		     irq, cpumask_first(desc->percpu_enabled));
+		goto bad;
+	}
+
+	/* Found it - now remove it from the list of entries: */
+	desc->action = NULL;
+
+	raw_spin_unlock_irqrestore(&desc->lock, flags);
+
+	unregister_handler_proc(irq, action);
+
+	module_put(desc->owner);
+	return action;
+
+bad:
+	raw_spin_unlock_irqrestore(&desc->lock, flags);
+	return NULL;
+}
+
+/**
+ *	remove_percpu_irq - free a per-cpu interrupt
+ *	@irq: Interrupt line to free
+ *	@act: irqaction for the interrupt
+ *
+ * Used to remove interrupts statically setup by the early boot process.
+ */
+void remove_percpu_irq(unsigned int irq, struct irqaction *act)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	if (desc && irq_settings_is_per_cpu_devid(desc))
+	    __free_percpu_irq(irq, act->percpu_dev_id);
+}
+
+/**
+ *	free_percpu_irq - free an interrupt allocated with request_percpu_irq
+ *	@irq: Interrupt line to free
+ *	@dev_id: Device identity to free
+ *
+ *	Remove a percpu interrupt handler. The handler is removed, but
+ *	the interrupt line is not disabled. This must be done on each
+ *	CPU before calling this function. The function does not return
+ *	until any executing interrupts for this IRQ have completed.
+ *
+ *	This function must not be called from interrupt context.
+ */
+void free_percpu_irq(unsigned int irq, void __percpu *dev_id)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	if (!desc || !irq_settings_is_per_cpu_devid(desc))
+		return;
+
+	chip_bus_lock(desc);
+	kfree(__free_percpu_irq(irq, dev_id));
+	chip_bus_sync_unlock(desc);
+}
+
+/**
+ *	setup_percpu_irq - setup a per-cpu interrupt
+ *	@irq: Interrupt line to setup
+ *	@act: irqaction for the interrupt
+ *
+ * Used to statically setup per-cpu interrupts in the early boot process.
+ */
+int setup_percpu_irq(unsigned int irq, struct irqaction *act)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	int retval;
+
+	if (!desc || !irq_settings_is_per_cpu_devid(desc))
+		return -EINVAL;
+	chip_bus_lock(desc);
+	retval = __setup_irq(irq, desc, act);
+	chip_bus_sync_unlock(desc);
+
+	return retval;
+}
+
+/**
+ *	request_percpu_irq - allocate a percpu interrupt line
+ *	@irq: Interrupt line to allocate
+ *	@handler: Function to be called when the IRQ occurs.
+ *	@devname: An ascii name for the claiming device
+ *	@dev_id: A percpu cookie passed back to the handler function
+ *
+ *	This call allocates interrupt resources, but doesn't
+ *	automatically enable the interrupt. It has to be done on each
+ *	CPU using enable_percpu_irq().
+ *
+ *	Dev_id must be globally unique. It is a per-cpu variable, and
+ *	the handler gets called with the interrupted CPU's instance of
+ *	that variable.
+ */
+int request_percpu_irq(unsigned int irq, irq_handler_t handler,
+		       const char *devname, void __percpu *dev_id)
+{
+	struct irqaction *action;
+	struct irq_desc *desc;
+	int retval;
+
+	if (!dev_id)
+		return -EINVAL;
+
+	desc = irq_to_desc(irq);
+	if (!desc || !irq_settings_can_request(desc) ||
+	    !irq_settings_is_per_cpu_devid(desc))
+		return -EINVAL;
+
+	action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
+	if (!action)
+		return -ENOMEM;
+
+	action->handler = handler;
+	action->flags = IRQF_PERCPU;
+	action->name = devname;
+	action->percpu_dev_id = dev_id;
+
+	chip_bus_lock(desc);
+	retval = __setup_irq(irq, desc, action);
+	chip_bus_sync_unlock(desc);
+
+	if (retval)
+		kfree(action);
+
+	return retval;
+}
diff --git a/kernel/irq/settings.h b/kernel/irq/settings.h
index f166783..1162f10 100644
--- a/kernel/irq/settings.h
+++ b/kernel/irq/settings.h
@@ -13,6 +13,7 @@
 	_IRQ_MOVE_PCNTXT	= IRQ_MOVE_PCNTXT,
 	_IRQ_NO_BALANCING	= IRQ_NO_BALANCING,
 	_IRQ_NESTED_THREAD	= IRQ_NESTED_THREAD,
+	_IRQ_PER_CPU_DEVID	= IRQ_PER_CPU_DEVID,
 	_IRQF_MODIFY_MASK	= IRQF_MODIFY_MASK,
 };
 
@@ -24,6 +25,7 @@
 #define IRQ_NOTHREAD		GOT_YOU_MORON
 #define IRQ_NOAUTOEN		GOT_YOU_MORON
 #define IRQ_NESTED_THREAD	GOT_YOU_MORON
+#define IRQ_PER_CPU_DEVID	GOT_YOU_MORON
 #undef IRQF_MODIFY_MASK
 #define IRQF_MODIFY_MASK	GOT_YOU_MORON
 
@@ -39,6 +41,11 @@
 	return desc->status_use_accessors & _IRQ_PER_CPU;
 }
 
+static inline bool irq_settings_is_per_cpu_devid(struct irq_desc *desc)
+{
+	return desc->status_use_accessors & _IRQ_PER_CPU_DEVID;
+}
+
 static inline void irq_settings_set_per_cpu(struct irq_desc *desc)
 {
 	desc->status_use_accessors |= _IRQ_PER_CPU;
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 3573169..9a076d6 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -118,7 +118,7 @@
 
 
 /* Track ASM playback & capture sessions of DAI */
-static int fe_dai_map[MSM_FRONTEND_DAI_MAX][2] = {
+static int fe_dai_map[MSM_FRONTEND_DAI_MM_SIZE][2] = {
 	/* MULTIMEDIA1 */
 	{INVALID_SESSION, INVALID_SESSION},
 	/* MULTIMEDIA2 */
@@ -158,6 +158,12 @@
 	int i, session_type, path_type, port_type;
 	struct route_payload payload;
 
+	if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
+		/* bad ID assigned in machine driver */
+		pr_err("%s: bad MM ID\n", __func__);
+		return;
+	}
+
 	if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
 		session_type = SESSION_TYPE_RX;
 		path_type = ADM_PATH_PLAYBACK;
@@ -200,6 +206,12 @@
 {
 	int i, port_type, session_type;
 
+	if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
+		/* bad ID assigned in machine driver */
+		pr_err("%s: bad MM ID\n", __func__);
+		return;
+	}
+
 	if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
 		port_type = MSM_AFE_PORT_TYPE_RX;
 		session_type = SESSION_TYPE_RX;
@@ -229,6 +241,12 @@
 
 	pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
 
+	if (val > MSM_FRONTEND_DAI_MM_MAX_ID) {
+		/* recheck FE ID in the mixer control defined in this file */
+		pr_err("%s: bad MM ID\n", __func__);
+		return;
+	}
+
 	if (afe_get_port_type(msm_bedais[reg].port_id) ==
 		MSM_AFE_PORT_TYPE_RX) {
 		session_type = SESSION_TYPE_RX;
@@ -518,9 +536,11 @@
 	int eq_idx = ((struct soc_multi_mixer_control *)
 					kcontrol->private_value)->reg;
 
+	ucontrol->value.integer.value[0] = eq_data[eq_idx].enable;
+
 	pr_debug("%s: EQ #%d enable %d\n", __func__,
 		eq_idx, eq_data[eq_idx].enable);
-	return eq_data[eq_idx].enable;
+	return 0;
 }
 
 static int msm_routing_put_eq_enable_mixer(struct snd_kcontrol *kcontrol,
@@ -545,6 +565,8 @@
 	int eq_idx = ((struct soc_multi_mixer_control *)
 					kcontrol->private_value)->reg;
 
+	ucontrol->value.integer.value[0] = eq_data[eq_idx].num_bands;
+
 	pr_debug("%s: EQ #%d bands %d\n", __func__,
 		eq_idx, eq_data[eq_idx].num_bands);
 	return eq_data[eq_idx].num_bands;
@@ -558,7 +580,6 @@
 					kcontrol->private_value)->reg;
 	int value = ucontrol->value.integer.value[0];
 
-
 	pr_debug("%s: EQ #%d bands %d\n", __func__,
 		eq_idx, value);
 	eq_data[eq_idx].num_bands = value;
@@ -573,6 +594,17 @@
 	int band_idx = ((struct soc_multi_mixer_control *)
 					kcontrol->private_value)->shift;
 
+	ucontrol->value.integer.value[0] =
+			eq_data[eq_idx].eq_bands[band_idx].band_idx;
+	ucontrol->value.integer.value[1] =
+			eq_data[eq_idx].eq_bands[band_idx].filter_type;
+	ucontrol->value.integer.value[2] =
+			eq_data[eq_idx].eq_bands[band_idx].center_freq_hz;
+	ucontrol->value.integer.value[3] =
+			eq_data[eq_idx].eq_bands[band_idx].filter_gain;
+	ucontrol->value.integer.value[4] =
+			eq_data[eq_idx].eq_bands[band_idx].q_factor;
+
 	pr_debug("%s: band_idx = %d\n", __func__,
 			eq_data[eq_idx].eq_bands[band_idx].band_idx);
 	pr_debug("%s: filter_type = %d\n", __func__,
@@ -1239,6 +1271,11 @@
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	unsigned int be_id = rtd->dai_link->be_id;
 
+	if (be_id >= MSM_BACKEND_DAI_MAX) {
+		pr_err("%s: unexpected be_id %d\n", __func__, be_id);
+		return -EINVAL;
+	}
+
 	mutex_lock(&routing_lock);
 	msm_bedais[be_id].hw_params = params;
 	mutex_unlock(&routing_lock);
@@ -1264,7 +1301,7 @@
 
 	mutex_lock(&routing_lock);
 
-	for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MAX) {
+	for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_MAX_ID) {
 		if (fe_dai_map[i][session_type] != INVALID_SESSION)
 			adm_close(bedai->port_id);
 	}
@@ -1318,7 +1355,7 @@
 	 */
 	bedai->active = 1;
 
-	for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MAX) {
+	for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_MAX_ID) {
 		if (fe_dai_map[i][session_type] != INVALID_SESSION) {
 			adm_open(bedai->port_id, path_type,
 				params_rate(bedai->hw_params),
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index b7fc82a..b3a8210 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -27,6 +27,12 @@
 #define LPASS_BE_AUXPCM_RX "(Backend) AUX_PCM_RX"
 #define LPASS_BE_AUXPCM_TX "(Backend) AUX_PCM_TX"
 
+/* For multimedia front-ends, asm session is allocated dynamically.
+ * Hence, asm session/multimedia front-end mapping has to be maintained.
+ * Due to this reason, additional multimedia front-end must be placed before
+ * non-multimedia front-ends.
+ */
+
 enum {
 	MSM_FRONTEND_DAI_MULTIMEDIA1 = 0,
 	MSM_FRONTEND_DAI_MULTIMEDIA2,
@@ -39,6 +45,9 @@
 	MSM_FRONTEND_DAI_MAX,
 };
 
+#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA4 + 1)
+#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA4
+
 enum {
 	MSM_BACKEND_DAI_PRI_I2S_RX = 0,
 	MSM_BACKEND_DAI_PRI_I2S_TX,
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 965211d..c899b2a 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -2336,7 +2336,10 @@
 	mutex_lock(&v->lock);
 
 	if (v->voc_state == VOC_RUN) {
-		afe_sidetone(v->dev_tx.port_id, v->dev_rx.port_id, 0, 0);
+		if (v->dev_tx.port_id != RT_PROXY_PORT_001_TX &&
+			v->dev_rx.port_id != RT_PROXY_PORT_001_RX)
+			afe_sidetone(v->dev_tx.port_id, v->dev_rx.port_id,
+					0, 0);
 
 		rtac_remove_voice(voice_get_cvs_handle(v));
 		/* send cmd to dsp to disable vocproc */
@@ -2403,12 +2406,17 @@
 			voice_send_set_slowtalk_enable_cmd(v);
 
 		get_sidetone_cal(&sidetone_cal_data);
-		ret = afe_sidetone(v->dev_tx.port_id, v->dev_rx.port_id,
-						sidetone_cal_data.enable,
-						sidetone_cal_data.gain);
+		if (v->dev_tx.port_id != RT_PROXY_PORT_001_TX &&
+			v->dev_rx.port_id != RT_PROXY_PORT_001_RX) {
+			ret = afe_sidetone(v->dev_tx.port_id,
+					v->dev_rx.port_id,
+					sidetone_cal_data.enable,
+					sidetone_cal_data.gain);
 
-		if (ret < 0)
-			pr_err("%s: AFE command sidetone failed\n", __func__);
+			if (ret < 0)
+				pr_err("%s: AFE command sidetone failed\n",
+					__func__);
+		}
 
 		rtac_add_voice(voice_get_cvs_handle(v),
 			voice_get_cvp_handle(v),
@@ -2683,7 +2691,10 @@
 	mutex_lock(&v->lock);
 
 	if (v->voc_state == VOC_RUN) {
-		afe_sidetone(v->dev_tx.port_id, v->dev_rx.port_id, 0, 0);
+		if (v->dev_tx.port_id != RT_PROXY_PORT_001_TX &&
+			v->dev_rx.port_id != RT_PROXY_PORT_001_RX)
+			afe_sidetone(v->dev_tx.port_id, v->dev_rx.port_id,
+					0, 0);
 		ret = voice_destroy_vocproc(v);
 		if (ret < 0)
 			pr_err("%s:  destroy voice failed\n", __func__);
@@ -2732,12 +2743,15 @@
 			goto fail;
 		}
 		get_sidetone_cal(&sidetone_cal_data);
-		ret = afe_sidetone(v->dev_tx.port_id,
+		if (v->dev_tx.port_id != RT_PROXY_PORT_001_TX &&
+			v->dev_rx.port_id != RT_PROXY_PORT_001_RX) {
+			ret = afe_sidetone(v->dev_tx.port_id,
 					v->dev_rx.port_id,
 					sidetone_cal_data.enable,
 					sidetone_cal_data.gain);
-		if (ret < 0)
-			pr_err("AFE command sidetone failed\n");
+			if (ret < 0)
+				pr_err("AFE command sidetone failed\n");
+		}
 
 		v->voc_state = VOC_RUN;
 	}