Merge "msm: iommu: Enable IO-MMU support for 8660" into msm-3.0
diff --git a/Documentation/devicetree/bindings/spmi/msm-qpnp-gpio.txt b/Documentation/devicetree/bindings/gpio/qpnp-gpio.txt
similarity index 94%
rename from Documentation/devicetree/bindings/spmi/msm-qpnp-gpio.txt
rename to Documentation/devicetree/bindings/gpio/qpnp-gpio.txt
index f07d3c2..dff6a3e 100644
--- a/Documentation/devicetree/bindings/spmi/msm-qpnp-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/qpnp-gpio.txt
@@ -84,10 +84,6 @@
 			QPNP_GPIO_DTEST3	= 6,
 			QPNP_GPIO_DTEST4	= 7
 
-  @inv_int_pol:		Invert polarity before feeding the line to the interrupt
-			module in pmic. This feature will almost be never used
-			since the pm8xxx interrupt block can detect both edges
-			and both levels.
   @master_en:		1 = Enable features within the GPIO block based on
 			configurations.
 			0 = Completely disable the GPIO block and let the pin
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
new file mode 100644
index 0000000..002431a
--- /dev/null
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
@@ -0,0 +1,24 @@
+Qualcomm LPASS QDSP6v5 Peripheral Image Loader
+
+pil-qdsp6v5-lpass is a peripheral image loader (PIL) driver. It is used for
+loading QDSP6v5 (Hexagon) firmware images for Low Power Audio Subsystems
+into memory and preparing the subsystem's processor to execute code. It's
+also responsible for shutting down the processor when it's not needed.
+
+Required properties:
+- compatible:	      Must be "qcom,pil-q6v5-lpass"
+- reg:		      Three pairs of physical base addresses and region sizes
+		      of memory mapped registers. The first region corresponds
+		      to QDSP6SS_PUB, the second corresponds to LPASS_CC, and
+		      the third to LPASS_HALTREQ.
+- qcom,firmware-name: Base name of the firmware image. Ex. "lpass"
+
+Example:
+	qcom,lpass@fe200000 {
+	        compatible = "qcom,pil-q6v5-lpass";
+	        reg = <0xfe200000 0x00100>,
+	              <0xfe000000 0x40000>,
+	              <0xfd485100 0x00010>;
+
+	        qcom,firmware-name = "lpass";
+	};
diff --git a/arch/arm/boot/dts/msmcopper.dtsi b/arch/arm/boot/dts/msmcopper.dtsi
index 284426a..4821290 100644
--- a/arch/arm/boot/dts/msmcopper.dtsi
+++ b/arch/arm/boot/dts/msmcopper.dtsi
@@ -233,7 +233,7 @@
 		qcom,i2c-src-freq = <24000000>;
 	};
 
-	qcom,acpuclk@0xf900000 {
+	qcom,acpuclk@f9000000 {
 		compatible = "qcom,acpuclk-copper";
 	};
 
@@ -243,4 +243,13 @@
 		interrupts = <0 131 0>;
 		qcom,dwc-usb3-msm-dbm-eps = <4>;
 	};
+
+	qcom,lpass@fe200000 {
+		compatible = "qcom,pil-q6v5-lpass";
+		reg = <0xfe200000 0x00100>,
+		      <0xfe000000 0x40000>,
+		      <0xfd485100 0x00010>;
+
+		qcom,firmware-name = "lpass";
+	};
 };
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 667b1ec..1574a54 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -116,6 +116,7 @@
 CONFIG_SLIMBUS_MSM_CTRL=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_QPNP=y
 CONFIG_POWER_SUPPLY=y
 # CONFIG_BATTERY_MSM is not set
 # CONFIG_HWMON is not set
diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h
index d665490..df30306 100644
--- a/arch/arm/include/asm/hardware/cache-l2x0.h
+++ b/arch/arm/include/asm/hardware/cache-l2x0.h
@@ -109,8 +109,8 @@
 #define L2X0_PREFETCH_CTRL_WRAP8_SHIFT		30
 
 #ifndef __ASSEMBLY__
-extern void l2cc_suspend(void);
-extern void l2cc_resume(int collapsed);
+extern void l2x0_suspend(void);
+extern void l2x0_resume(int collapsed);
 extern void l2x0_cache_sync(void);
 extern void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask);
 #if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_OF)
diff --git a/arch/arm/include/asm/mach/mmc.h b/arch/arm/include/asm/mach/mmc.h
index 7a5b21a..dabd390 100644
--- a/arch/arm/include/asm/mach/mmc.h
+++ b/arch/arm/include/asm/mach/mmc.h
@@ -152,7 +152,7 @@
 	bool disable_bam;
 	bool disable_runtime_pm;
 	bool disable_cmd23;
-	u32 swfi_latency;
+	u32 cpu_dma_latency;
 };
 
 #endif
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index de314ea..88ad1a9 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -651,6 +651,26 @@
 	}
 }
 
+static int cpu_has_active_perf(void)
+{
+	int idx;
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+
+	if (!armpmu)
+		return 0;
+
+	for (idx = 0; idx <= armpmu->num_events; ++idx) {
+		struct perf_event *event = cpuc->events[idx];
+
+		if (event)
+			/*Even one event's existence is good enough.*/
+			return 1;
+
+	}
+
+	return 0;
+}
+
 static struct pmu pmu = {
 	.pmu_enable	= armpmu_enable,
 	.pmu_disable	= armpmu_disable,
@@ -676,16 +696,18 @@
 {
 	switch (cmd) {
 	case CPU_PM_ENTER:
-		armpmu_update_counters();
-		perf_pmu_disable(&pmu);
+		if (cpu_has_active_perf()) {
+			armpmu_update_counters();
+			perf_pmu_disable(&pmu);
+		}
 		break;
 
 	case CPU_PM_ENTER_FAILED:
 	case CPU_PM_EXIT:
-		if (armpmu && armpmu->reset)
+		if (cpu_has_active_perf() && armpmu->reset) {
 			armpmu->reset(NULL);
-		perf_pmu_enable(&pmu);
-
+			perf_pmu_enable(&pmu);
+		}
 		break;
 	}
 
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 4ea24a4..ca3e459 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -239,6 +239,7 @@
 	select MSM_GPIOMUX
 	select MULTI_IRQ_HANDLER
 	select MSM_MULTIMEDIA_USE_ION
+	select MSM_PIL
 
 config ARCH_FSM9XXX
 	bool "FSM9XXX"
@@ -1742,7 +1743,6 @@
 config MSM_PIL
 	bool "Peripheral image loading"
 	select FW_LOADER
-	depends on (ARCH_MSM8X60 || ARCH_MSM8960)
 	default n
 	help
 	  Some peripherals need to be loaded into memory before they can be
@@ -1771,6 +1771,13 @@
 	  The QDSP6 is a low power DSP used in audio, modem firmware, and modem
 	  software applications.
 
+config MSM_PIL_LPASS_QDSP6V5
+       tristate "LPASS QDSP6v5 (Hexagon) Boot Support"
+       depends on MSM_PIL
+       help
+         Support for booting and shutting down QDSP6v5 processors (Hexagon)
+	 processors in low power audio subsystems.
+
 config MSM_PIL_RIVA
 	tristate "RIVA (WCNSS) Boot Support"
 	depends on MSM_PIL
@@ -2190,12 +2197,12 @@
 	  For production builds, you should probably say 'N' here.
 
 config MSM_L1_ERR_PANIC
-	bool "Panic on L1 cache / TLB errors"
+	bool "Panic on L1 cache errors"
 	depends on MSM_CACHE_ERP
 	help
-	  To cause the kernel to panic whenever an L1 cache or TLB error is
-	  detected, say 'Y' here. This may be useful as a debugging technique if
-	  general system instability is suspected.
+	  To cause the kernel to panic whenever an L1 cache error is detected, say
+	  'Y' here. This may be useful as a debugging technique if general system
+	  instability is suspected.
 
 	  For production builds, you should probably say 'N' here.
 
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index f14f1ea..84af813 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -67,6 +67,7 @@
 obj-$(CONFIG_MSM_PIL) += scm-pas.o
 obj-$(CONFIG_MSM_PIL_QDSP6V3) += pil-q6v3.o
 obj-$(CONFIG_MSM_PIL_QDSP6V4) += pil-q6v4.o
+obj-$(CONFIG_MSM_PIL_LPASS_QDSP6V5) += pil-q6v5.o pil-q6v5-lpass.o
 obj-$(CONFIG_MSM_PIL_RIVA) += pil-riva.o
 obj-$(CONFIG_MSM_PIL_TZAPPS) += pil-tzapps.o
 obj-$(CONFIG_MSM_PIL_VIDC) += pil-vidc.o
@@ -273,6 +274,7 @@
 obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
 obj-$(CONFIG_ARCH_MSMCOPPER) += board-copper.o board-dt.o board-copper-regulator.o board-copper-gpiomux.o
 obj-$(CONFIG_ARCH_MSMCOPPER) += acpuclock-krait.o acpuclock-copper.o
+obj-$(CONFIG_ARCH_MSMCOPPER) += clock-local2.o
 
 obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire.o board-sapphire-gpio.o
 obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-keypad.o board-sapphire-panel.o
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index 3723da8..2019f9b 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -598,6 +598,11 @@
 	.sensor_type = BAYER_SENSOR,
 };
 
+static struct platform_device msm_camera_server = {
+	.name = "msm_cam_server",
+	.id = 0,
+};
+
 void __init apq8064_init_cam(void)
 {
 	msm_gpiomux_install(apq8064_cam_common_configs,
@@ -609,6 +614,7 @@
 	} else if (machine_is_apq8064_liquid())
 		sensor_board_info_imx074.mount_angle = 180;
 
+	platform_device_register(&msm_camera_server);
 	platform_device_register(&msm8960_device_i2c_mux_gsbi4);
 	platform_device_register(&msm8960_device_csiphy0);
 	platform_device_register(&msm8960_device_csiphy1);
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index de6e0d2..99a3fa1 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -433,33 +433,6 @@
 	.drv = GPIOMUX_DRV_12MA,
 	.pull = GPIOMUX_PULL_NONE,
 };
-
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
-static struct gpiomux_setting hsic_act_cfg = {
-	.func = GPIOMUX_FUNC_1,
-	.drv = GPIOMUX_DRV_8MA,
-	.pull = GPIOMUX_PULL_NONE,
-};
-
-static struct gpiomux_setting hsic_sus_cfg = {
-	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_2MA,
-	.pull = GPIOMUX_PULL_DOWN,
-	.dir = GPIOMUX_OUT_LOW,
-};
-
-static struct gpiomux_setting cyts_resout_sus_cfg = {
-	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_6MA,
-	.pull = GPIOMUX_PULL_UP,
-};
-
-static struct gpiomux_setting cyts_resout_act_cfg = {
-	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_6MA,
-	.pull = GPIOMUX_PULL_UP,
-};
-
 static struct gpiomux_setting cyts_sleep_sus_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_6MA,
@@ -499,15 +472,23 @@
 			[GPIOMUX_SUSPENDED] = &cyts_sleep_sus_cfg,
 		},
 	},
-	{	/* TS RESOUT */
-		.gpio = 7,
-		.settings = {
-			[GPIOMUX_ACTIVE]    = &cyts_resout_act_cfg,
-			[GPIOMUX_SUSPENDED] = &cyts_resout_sus_cfg,
-		},
-	},
 };
 
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+static struct gpiomux_setting hsic_act_cfg = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting hsic_sus_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+	.dir = GPIOMUX_OUT_LOW,
+};
+
+
 static struct msm_gpiomux_config apq8064_hsic_configs[] = {
 	{
 		.gpio = 88,               /*HSIC_STROBE */
@@ -828,6 +809,71 @@
 	},
 };
 
+static struct gpiomux_setting mi2s_act_cfg = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting mi2s_sus_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct msm_gpiomux_config mpq8064_mi2s_configs[] __initdata = {
+	{
+		.gpio	= 27,		/* mi2s ws */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &mi2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+		},
+	},
+	{
+		.gpio	= 28,		/* mi2s sclk */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &mi2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+		},
+	},
+	{
+		.gpio	= 29,		/* mi2s dout3 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &mi2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+		},
+	},
+	{
+		.gpio	= 30,		/* mi2s dout2 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &mi2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+		},
+	},
+
+	{
+		.gpio	= 31,		/* mi2s dout1 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &mi2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+		},
+	},
+	{
+		.gpio	= 32,		/* mi2s dout0 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &mi2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+		},
+	},
+
+	{
+		.gpio	= 33,		/* mi2s mclk */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &mi2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+		},
+	},
+};
 static struct msm_gpiomux_config apq8064_mxt_configs[] __initdata = {
 	{	/* TS INTERRUPT */
 		.gpio = 6,
@@ -900,6 +946,28 @@
 	},
 };
 
+static struct gpiomux_setting ir_suspended_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting ir_active_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct msm_gpiomux_config mpq8064_ir_configs[] __initdata = {
+	{
+		.gpio      = 88,			/* GPIO IR */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ir_suspended_cfg,
+			[GPIOMUX_ACTIVE] = &ir_active_cfg,
+		},
+	},
+};
+
 void __init apq8064_init_gpiomux(void)
 {
 	int rc;
@@ -947,6 +1015,11 @@
 		" as audio is not the primary user"
 		" for these GPIO Pins\n", __func__);
 
+	if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
+		machine_is_mpq8064_dtv())
+		msm_gpiomux_install(mpq8064_mi2s_configs,
+			ARRAY_SIZE(mpq8064_mi2s_configs));
+
 	msm_gpiomux_install(apq8064_ext_regulator_configs,
 			ARRAY_SIZE(apq8064_ext_regulator_configs));
 
@@ -970,4 +1043,8 @@
 
 	msm_gpiomux_install(apq8064_hdmi_configs,
 			ARRAY_SIZE(apq8064_hdmi_configs));
+
+	 if (machine_is_mpq8064_cdp())
+		msm_gpiomux_install(mpq8064_ir_configs,
+				ARRAY_SIZE(mpq8064_ir_configs));
 }
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index f8aa9c0..2cab803 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -195,7 +195,7 @@
 			.bus_freq = 0,
 		},
 	},
-	.init_level = 0,
+	.init_level = 1,
 	.num_levels = 4,
 	.set_grp_async = NULL,
 	.idle_timeout = HZ/10,
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index 275c893..d91408a 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -271,14 +271,11 @@
 			apq8064_sdc3_pdata->disable_cmd23 = true;
 		}
 	}
-	if (apq8064_sdc1_pdata) {
-		apq8064_sdc1_pdata->swfi_latency =
-				apq8064_rpm_get_swfi_latency();
+
+	if (apq8064_sdc1_pdata)
 		apq8064_add_sdcc(1, apq8064_sdc1_pdata);
-	}
+
 	if (apq8064_sdc3_pdata) {
-		apq8064_sdc3_pdata->swfi_latency =
-				apq8064_rpm_get_swfi_latency();
 		if (!machine_is_apq8064_cdp()) {
 			apq8064_sdc3_pdata->wpswitch_gpio = 0;
 			apq8064_sdc3_pdata->wpswitch_polarity = 0;
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 9e3b898..5b0b9c3 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -66,6 +66,7 @@
 #include <mach/msm_xo.h>
 #include <mach/msm_rtb.h>
 #include <sound/cs8427.h>
+#include <media/gpio-ir-recv.h>
 
 #include "msm_watchdog.h"
 #include "board-8064.h"
@@ -76,6 +77,7 @@
 #include "pm.h"
 #include "pm-boot.h"
 #include "devices-msm8x60.h"
+#include "smd_private.h"
 
 #define MSM_PMEM_ADSP_SIZE         0x7800000
 #define MSM_PMEM_AUDIO_SIZE        0x4CF000
@@ -375,7 +377,7 @@
 };
 #endif
 
-static void reserve_ion_memory(void)
+static void __init reserve_ion_memory(void)
 {
 #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
 	apq8064_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_SIZE;
@@ -441,6 +443,12 @@
 		apq8064_reserve_info.bank_size);
 }
 
+static int apq8064_change_memory_power(u64 start, u64 size,
+	int change_type)
+{
+	return soc_change_memory_power(start, size, change_type);
+}
+
 static char prim_panel_name[PANEL_NAME_MAX_LEN];
 static char ext_panel_name[PANEL_NAME_MAX_LEN];
 static int __init prim_display_setup(char *param)
@@ -1122,7 +1130,6 @@
 };
 #endif
 #define CYTTSP_TS_GPIO_IRQ		6
-#define CYTTSP_TS_GPIO_RESOUT		7
 #define CYTTSP_TS_GPIO_SLEEP		33
 
 static ssize_t tma340_vkeys_show(struct kobject *kobj,
@@ -1216,7 +1223,7 @@
 	 */
 	.lp_intrvl = CY_LP_INTRVL_DFLT,
 	.sleep_gpio = CYTTSP_TS_GPIO_SLEEP,
-	.resout_gpio = CYTTSP_TS_GPIO_RESOUT,
+	.resout_gpio = -1,
 	.irq_gpio = CYTTSP_TS_GPIO_IRQ,
 	.regulator_info = cyttsp_regulator_data,
 	.num_regulators = ARRAY_SIZE(cyttsp_regulator_data),
@@ -1602,19 +1609,6 @@
 	},
 };
 
-uint32_t apq8064_rpm_get_swfi_latency(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(msm_rpmrs_levels); i++) {
-		if (msm_rpmrs_levels[i].sleep_mode ==
-			MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)
-			return msm_rpmrs_levels[i].latency_us;
-	}
-
-	return 0;
-}
-
 static struct msm_pm_boot_platform_data msm_pm_boot_pdata __initdata = {
 	.mode = MSM_PM_BOOT_CONFIG_TZ,
 };
@@ -1794,6 +1788,12 @@
 	},
 };
 
+static struct msm_pm_sleep_status_data msm_pm_slp_sts_data = {
+	.base_addr = MSM_ACC0_BASE + 0x08,
+	.cpu_offset = MSM_ACC1_BASE - MSM_ACC0_BASE,
+	.mask = 1UL << 13,
+};
+
 static void __init apq8064_init_buses(void)
 {
 	msm_bus_rpm_set_mt_mask();
@@ -1854,6 +1854,18 @@
 	},
 };
 
+static struct gpio_ir_recv_platform_data gpio_ir_recv_pdata = {
+	.gpio_nr = 88,
+	.active_low = 1,
+};
+
+static struct platform_device gpio_ir_recv_pdev = {
+	.name = "gpio-rc-recv",
+	.dev = {
+		.platform_data = &gpio_ir_recv_pdata,
+	},
+};
+
 static struct platform_device *common_devices[] __initdata = {
 	&apq8064_device_dmov,
 #ifndef CONFIG_MSM_VCAP
@@ -1912,6 +1924,7 @@
 	&apq_cpudai0,
 	&apq_cpudai1,
 	&mpq_cpudai_sec_i2s_rx,
+	&mpq_cpudai_mi2s_tx,
 	&apq_cpudai_hdmi_rx,
 	&apq_cpudai_bt_rx,
 	&apq_cpudai_bt_tx,
@@ -1962,6 +1975,10 @@
 	&msm_tpiu_device,
 	&msm_funnel_device,
 	&apq8064_etm_device,
+	&apq_cpudai_slim_4_rx,
+	&apq_cpudai_slim_4_tx,
+	&msm8960_gemini_device,
+	&apq8064_iommu_domain_device,
 };
 
 static struct platform_device *sim_devices[] __initdata = {
@@ -2052,6 +2069,7 @@
 #ifdef CONFIG_MSM_ROTATOR
 	&msm_rotator_device,
 #endif
+	&gpio_ir_recv_pdev,
 	&mpq8064_device_ext_5v_frc_vreg,
 	&mpq8064_device_ext_1p2_buck_vreg,
 	&mpq8064_device_ext_1p8_buck_vreg,
@@ -2105,7 +2123,7 @@
 };
 
 static struct msm_i2c_platform_data apq8064_i2c_qup_gsbi3_pdata = {
-	.clk_freq = 100000,
+	.clk_freq = 384000,
 	.src_clk_rate = 24000000,
 };
 
@@ -2337,6 +2355,8 @@
 	},
 };
 
+#define SX150X_EXP1_INT_N	PM8921_MPP_IRQ(PM8921_IRQ_BASE, 9)
+
 struct sx150x_platform_data mpq8064_sx150x_pdata[] = {
 	[SX150X_EXP1] = {
 		.gpio_base	= SX150X_EXP1_GPIO_BASE,
@@ -2345,7 +2365,8 @@
 		.io_pulldn_ena	= 0x0,
 		.io_open_drain_ena = 0x0,
 		.io_polarity	= 0,
-		.irq_summary	= -1,
+		.irq_summary	= SX150X_EXP1_INT_N,
+		.irq_base	= SX150X_EXP1_IRQ_BASE,
 	},
 	[SX150X_EXP2] = {
 		.gpio_base	= SX150X_EXP2_GPIO_BASE,
@@ -2534,6 +2555,7 @@
 	acpuclk_init(&acpuclk_8064_soc_data);
 	msm_spm_l2_init(msm_spm_l2_data);
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
+	msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
 	apq8064_epm_adc_init();
 }
 
@@ -2562,6 +2584,8 @@
 
 static void __init apq8064_cdp_init(void)
 {
+	if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
+		pr_err("meminfo_init() failed!\n");
 	apq8064_common_init();
 	if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
 		machine_is_mpq8064_dtv()) {
@@ -2583,6 +2607,8 @@
 
 	if (machine_is_apq8064_mtp())
 		platform_device_register(&mtp_kp_pdev);
+
+	change_memory_power = &apq8064_change_memory_power;
 }
 
 MACHINE_START(APQ8064_SIM, "QCT APQ8064 SIMULATOR")
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index f62a9fb..3729385 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -86,7 +86,6 @@
 void apq8064_init_fb(void);
 void apq8064_allocate_fb_region(void);
 void apq8064_mdp_writeback(struct memtype_reserve *reserve_table);
-uint32_t apq8064_rpm_get_swfi_latency(void);
 void __init apq8064_set_display_params(char *prim_panel, char *ext_panel);
 
 void apq8064_init_gpu(void);
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index 1a7e2e1..e7992f9 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -91,6 +91,11 @@
 		.drv = GPIOMUX_DRV_2MA,
 		.pull = GPIOMUX_PULL_KEEPER,
 	},
+	{
+		.func = GPIOMUX_FUNC_2, /*active 9*/
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_NONE,
+	},
 
 };
 
@@ -113,7 +118,7 @@
 	{
 		.gpio = 4,
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[1],
+			[GPIOMUX_ACTIVE]    = &cam_settings[9],
 			[GPIOMUX_SUSPENDED] = &cam_settings[0],
 		},
 	},
@@ -369,16 +374,17 @@
 };
 
 static struct gpio msm8930_common_cam_gpio[] = {
-	{5, GPIOF_DIR_IN, "CAMIF_MCLK"},
 	{20, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
 	{21, GPIOF_DIR_IN, "CAMIF_I2C_CLK"},
 };
 
 static struct gpio msm8930_front_cam_gpio[] = {
+	{4, GPIOF_DIR_IN, "CAMIF_MCLK"},
 	{76, GPIOF_DIR_OUT, "CAM_RESET"},
 };
 
 static struct gpio msm8930_back_cam_gpio[] = {
+	{5, GPIOF_DIR_IN, "CAMIF_MCLK"},
 	{107, GPIOF_DIR_OUT, "CAM_RESET"},
 	{54, GPIOF_DIR_OUT, "CAM_STBY_N"},
 };
@@ -556,11 +562,17 @@
 	.sensor_type          = BAYER_SENSOR,
 };
 
+static struct platform_device msm_camera_server = {
+	.name = "msm_cam_server",
+	.id = 0,
+};
+
 void __init msm8930_init_cam(void)
 {
 	msm_gpiomux_install(msm8930_cam_common_configs,
 			ARRAY_SIZE(msm8930_cam_common_configs));
 
+	platform_device_register(&msm_camera_server);
 	platform_device_register(&msm8960_device_csiphy0);
 	platform_device_register(&msm8960_device_csiphy1);
 	platform_device_register(&msm8960_device_csid0);
diff --git a/arch/arm/mach-msm/board-8930-gpu.c b/arch/arm/mach-msm/board-8930-gpu.c
index 7c8c64f..5ee480a 100644
--- a/arch/arm/mach-msm/board-8930-gpu.c
+++ b/arch/arm/mach-msm/board-8930-gpu.c
@@ -115,7 +115,7 @@
 static struct kgsl_device_platform_data kgsl_3d0_pdata = {
 	.pwrlevel = {
 		{
-			.gpu_freq = 450000000,
+			.gpu_freq = 400000000,
 			.bus_freq = 3,
 			.io_fraction = 0,
 		},
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index f760e7b..fc89a11 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -148,7 +148,6 @@
 };
 VREG_CONSUMERS(S1) = {
 	REGULATOR_SUPPLY("8038_s1",		NULL),
-	REGULATOR_SUPPLY("HSUSB_VDDCX",		"msm_otg"),
 	REGULATOR_SUPPLY("riva_vddcx",		"wcnss_wlan.0"),
 };
 VREG_CONSUMERS(S2) = {
@@ -192,6 +191,7 @@
 };
 VREG_CONSUMERS(VDD_DIG_CORNER) = {
 	REGULATOR_SUPPLY("vdd_dig_corner",	NULL),
+	REGULATOR_SUPPLY("hsusb_vdd_dig",	"msm_otg"),
 };
 
 #define PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 8bbb596..24e6a79 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -116,7 +116,7 @@
 #endif
 
 #define MSM_PMEM_ADSP_SIZE         0x7800000
-#define MSM_PMEM_AUDIO_SIZE        0x2B4000
+#define MSM_PMEM_AUDIO_SIZE        0x4CF000
 #ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
 #define MSM_PMEM_SIZE 0x4000000 /* 64 Mbytes */
 #else
@@ -125,7 +125,7 @@
 
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-#define MSM_PMEM_KERNEL_EBI1_SIZE  0x280000
+#define MSM_PMEM_KERNEL_EBI1_SIZE  0x65000
 #define MSM_ION_SF_SIZE		MSM_PMEM_SIZE
 #define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
 #define MSM_ION_MM_SIZE		MSM_PMEM_ADSP_SIZE
@@ -202,7 +202,6 @@
 	.id = 2,
 	.dev = { .platform_data = &android_pmem_adsp_pdata },
 };
-#endif
 
 static struct android_pmem_platform_data android_pmem_audio_pdata = {
 	.name = "pmem_audio",
@@ -216,7 +215,8 @@
 	.id = 4,
 	.dev = { .platform_data = &android_pmem_audio_pdata },
 };
-#endif
+#endif /* CONFIG_MSM_MULTIMEDIA_USE_ION */
+#endif /* CONFIG_ANDROID_PMEM */
 
 #define DSP_RAM_BASE_8960 0x8da00000
 #define DSP_RAM_SIZE_8960 0x1800000
@@ -287,15 +287,19 @@
 #ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
 	android_pmem_adsp_pdata.size = pmem_adsp_size;
 	android_pmem_pdata.size = pmem_size;
-#endif
 	android_pmem_audio_pdata.size = MSM_PMEM_AUDIO_SIZE;
-#endif
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
 }
 
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
 static void __init reserve_memory_for(struct android_pmem_platform_data *p)
 {
 	msm8930_reserve_table[p->memory_type].size += p->size;
 }
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
 
 static void __init reserve_pmem_memory(void)
 {
@@ -303,10 +307,10 @@
 #ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
 	reserve_memory_for(&android_pmem_adsp_pdata);
 	reserve_memory_for(&android_pmem_pdata);
-#endif
 	reserve_memory_for(&android_pmem_audio_pdata);
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
 	msm8930_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
-#endif
+#endif /*CONFIG_ANDROID_PMEM*/
 }
 
 static int msm8930_paddr_to_memtype(unsigned int paddr)
@@ -419,7 +423,7 @@
 };
 #endif
 
-static void reserve_ion_memory(void)
+static void __init reserve_ion_memory(void)
 {
 #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
 	msm8930_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE;
@@ -1747,9 +1751,9 @@
 #ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
 	&android_pmem_device,
 	&android_pmem_adsp_device,
-#endif
 	&android_pmem_audio_device,
-#endif
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
 	&msm_device_bam_dmux,
 	&msm_fm_platform_init,
 
@@ -1787,6 +1791,7 @@
 	&msm_bus_8930_sys_fpb,
 	&msm_bus_8930_cpss_fpb,
 	&msm8960_device_cache_erp,
+	&msm8930_iommu_domain_device,
 };
 
 static struct platform_device *cdp_devices[] __initdata = {
@@ -1938,6 +1943,12 @@
 	.mode = MSM_PM_BOOT_CONFIG_TZ,
 };
 
+static struct msm_pm_sleep_status_data msm_pm_slp_sts_data = {
+	.base_addr = MSM_ACC0_BASE + 0x08,
+	.cpu_offset = MSM_ACC1_BASE - MSM_ACC0_BASE,
+	.mask = 1UL << 13,
+};
+
 #ifdef CONFIG_I2C
 #define I2C_SURF 1
 #define I2C_FFA  (1 << 1)
@@ -2097,6 +2108,7 @@
 		ARRAY_SIZE(msm_slim_devices));
 	change_memory_power = &msm8930_change_memory_power;
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
+	msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
 
 	if (PLATFORM_IS_CHARM25())
 		platform_add_devices(mdm_devices, ARRAY_SIZE(mdm_devices));
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index 0d1c72d..b60519b 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -681,6 +681,11 @@
 	return rc;
 }
 
+static struct platform_device msm_camera_server = {
+	.name = "msm_cam_server",
+	.id = 0,
+};
+
 void __init msm8960_init_cam(void)
 {
 	msm_gpiomux_install(msm8960_cam_common_configs,
@@ -709,6 +714,7 @@
 			msm_camera_8960_ext_power_ctrl;
 	}
 
+	platform_device_register(&msm_camera_server);
 	platform_device_register(&msm8960_device_csiphy0);
 	platform_device_register(&msm8960_device_csiphy1);
 	platform_device_register(&msm8960_device_csiphy2);
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
index 9bf80ed..8b5c693 100644
--- a/arch/arm/mach-msm/board-8960-gpiomux.c
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -256,6 +256,7 @@
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
+#if defined(CONFIG_FB_MSM_HDMI_MHL_8334) || defined(CONFIG_FB_MSM_HDMI_MHL_9244)
 static struct gpiomux_setting hdmi_active_3_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_2MA,
@@ -270,6 +271,7 @@
 	.dir = GPIOMUX_OUT_HIGH,
 };
 #endif
+#endif
 
 #if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
 static struct msm_gpiomux_config msm8960_ethernet_configs[] = {
@@ -690,6 +692,7 @@
 			[GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
 		},
 	},
+#ifdef CONFIG_FB_MSM_HDMI_MHL_9244
 		{
 		.gpio = 15,
 		.settings = {
@@ -704,6 +707,23 @@
 			[GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
 		},
 	},
+#endif
+#ifdef CONFIG_FB_MSM_HDMI_MHL_8334
+		{
+		.gpio = 4,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &hdmi_active_3_cfg,
+			[GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+		},
+	},
+	{
+		.gpio = 15,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &hdmi_active_4_cfg,
+			[GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+		},
+	},
+#endif /* CONFIG_FB_MSM_HDMI_MHL */
 };
 #endif
 
diff --git a/arch/arm/mach-msm/board-8960-storage.c b/arch/arm/mach-msm/board-8960-storage.c
index cd53f83..f39a691 100644
--- a/arch/arm/mach-msm/board-8960-storage.c
+++ b/arch/arm/mach-msm/board-8960-storage.c
@@ -266,12 +266,10 @@
 void __init msm8960_init_mmc(void)
 {
 #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
-	msm8960_sdc1_data.swfi_latency = msm_rpm_get_swfi_latency();
 	/* SDC1 : eMMC card connected */
 	msm_add_sdcc(1, &msm8960_sdc1_data);
 #endif
 #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
-	msm8960_sdc3_data.swfi_latency = msm_rpm_get_swfi_latency();
 	/* SDC3: External card slot */
 	msm_add_sdcc(3, &msm8960_sdc3_data);
 #endif
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 6ed174c..6328ab3 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -110,6 +110,9 @@
 #define KS8851_IRQ_GPIO		90
 #define HAP_SHIFT_LVL_OE_GPIO	47
 
+#define MHL_GPIO_INT            4
+#define MHL_GPIO_RESET          15
+
 #if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
 
 struct sx150x_platform_data msm8960_sx150x_data[] = {
@@ -707,7 +710,7 @@
 
 #endif
 
-static void reserve_cache_dump_memory(void)
+static void __init reserve_cache_dump_memory(void)
 {
 #ifdef CONFIG_MSM_CACHE_DUMP
 	unsigned int spare;
@@ -2273,11 +2276,76 @@
 	},
 };
 
+#ifdef CONFIG_FB_MSM_HDMI_MHL_8334
+static void mhl_sii_reset_gpio(int on)
+{
+	gpio_set_value(MHL_GPIO_RESET, on);
+	return;
+}
+
+/*
+ * Request for GPIO allocations
+ * Set appropriate GPIO directions
+ */
+static int mhl_sii_gpio_setup(int on)
+{
+	int ret;
+
+	if (on) {
+		ret = gpio_request(MHL_GPIO_RESET, "W_RST#");
+		if (ret < 0) {
+			pr_err("GPIO RESET request failed: %d\n", ret);
+			return -EBUSY;
+		}
+		ret = gpio_direction_output(MHL_GPIO_RESET, 1);
+		if (ret < 0) {
+			pr_err("SET GPIO RESET direction failed: %d\n", ret);
+			gpio_free(MHL_GPIO_RESET);
+			return -EBUSY;
+		}
+		ret = gpio_request(MHL_GPIO_INT, "W_INT");
+		if (ret < 0) {
+			pr_err("GPIO INT request failed: %d\n", ret);
+			gpio_free(MHL_GPIO_RESET);
+			return -EBUSY;
+		}
+		ret = gpio_direction_input(MHL_GPIO_INT);
+		if (ret < 0) {
+			pr_err("SET GPIO INTR direction failed: %d\n", ret);
+			gpio_free(MHL_GPIO_RESET);
+			gpio_free(MHL_GPIO_INT);
+			return -EBUSY;
+		}
+	} else {
+		gpio_free(MHL_GPIO_RESET);
+		gpio_free(MHL_GPIO_INT);
+	}
+
+	return 0;
+}
+
+static struct msm_mhl_platform_data mhl_platform_data = {
+	.irq = MSM_GPIO_TO_INT(4),
+	.gpio_setup = mhl_sii_gpio_setup,
+	.reset_pin = mhl_sii_reset_gpio,
+};
+#endif
+
 static struct i2c_board_info sii_device_info[] __initdata = {
 	{
+#ifdef CONFIG_FB_MSM_HDMI_MHL_8334
+		/*
+		 * keeps SI 8334 as the default
+		 * MHL TX
+		 */
+		I2C_BOARD_INFO("sii8334", 0x39),
+		.platform_data = &mhl_platform_data,
+#endif
+#ifdef CONFIG_FB_MSM_HDMI_MHL_9244
 		I2C_BOARD_INFO("Sil-9244", 0x39),
-		.flags = I2C_CLIENT_WAKE,
 		.irq = MSM_GPIO_TO_INT(15),
+#endif /* CONFIG_MSM_HDMI_MHL */
+		.flags = I2C_CLIENT_WAKE,
 	},
 };
 
@@ -2427,9 +2495,7 @@
 }
 
 static struct msm_serial_hs_platform_data msm_uart_dm9_pdata = {
-	.inject_rx_on_wakeup = 1,
-	.rx_to_inject = 0xFD,
-	.gpio_config = configure_uart_gpios,
+	.gpio_config	= configure_uart_gpios,
 };
 #else
 static struct msm_serial_hs_platform_data msm_uart_dm9_pdata;
@@ -2521,6 +2587,7 @@
 #ifdef CONFIG_MSM_CACHE_DUMP
 	&msm_cache_dump_device,
 #endif
+	&msm8960_iommu_domain_device,
 };
 
 static struct platform_device *sim_devices[] __initdata = {
@@ -2756,19 +2823,6 @@
 	.mode = MSM_PM_BOOT_CONFIG_TZ,
 };
 
-uint32_t msm_rpm_get_swfi_latency(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(msm_rpmrs_levels); i++) {
-		if (msm_rpmrs_levels[i].sleep_mode ==
-			MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)
-			return msm_rpmrs_levels[i].latency_us;
-	}
-
-	return 0;
-}
-
 #ifdef CONFIG_I2C
 #define I2C_SURF 1
 #define I2C_FFA  (1 << 1)
@@ -2902,7 +2956,7 @@
 		ARRAY_SIZE(mxt_device_info),
 	},
 	{
-		I2C_FFA | I2C_LIQUID,
+		I2C_SURF | I2C_FFA | I2C_LIQUID,
 		MSM_8960_GSBI10_QUP_I2C_BUS_ID,
 		sii_device_info,
 		ARRAY_SIZE(sii_device_info),
@@ -3100,8 +3154,10 @@
 		platform_device_register(&msm8960_device_uart_gsbi5);
 
 	/* For 8960 Fusion 2.2 Primary IPC */
-	if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
+	if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
+		msm_uart_dm9_pdata.wakeup_irq = gpio_to_irq(94); /* GSBI9(2) */
 		msm_device_uart_dm9.dev.platform_data = &msm_uart_dm9_pdata;
+	}
 
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
 	msm8960_pm8921_gpio_mpp_init();
diff --git a/arch/arm/mach-msm/board-8960.h b/arch/arm/mach-msm/board-8960.h
index dea957c..3824cfd 100644
--- a/arch/arm/mach-msm/board-8960.h
+++ b/arch/arm/mach-msm/board-8960.h
@@ -84,7 +84,6 @@
 void msm8960_set_display_params(char *prim_panel, char *ext_panel);
 void msm8960_pm8921_gpio_mpp_init(void);
 void msm8960_mdp_writeback(struct memtype_reserve *reserve_table);
-uint32_t msm_rpm_get_swfi_latency(void);
 #define PLATFORM_IS_CHARM25() \
 	(machine_is_msm8960_cdp() && \
 		(socinfo_get_platform_subtype() == 1) \
diff --git a/arch/arm/mach-msm/board-9615-gpiomux.c b/arch/arm/mach-msm/board-9615-gpiomux.c
index c600d53..0e18918 100644
--- a/arch/arm/mach-msm/board-9615-gpiomux.c
+++ b/arch/arm/mach-msm/board-9615-gpiomux.c
@@ -105,20 +105,6 @@
 };
 #endif
 
-static struct gpiomux_setting wlan_active_config = {
-	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_2MA,
-	.pull = GPIOMUX_PULL_NONE,
-	.dir = GPIOMUX_OUT_LOW,
-};
-
-static struct gpiomux_setting wlan_suspend_config = {
-	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_2MA,
-	.pull = GPIOMUX_PULL_NONE,
-	.dir = GPIOMUX_IN,
-};
-
 static struct msm_gpiomux_config msm9615_audio_codec_configs[] __initdata = {
 	{
 		.gpio = 24,
@@ -320,24 +306,6 @@
 };
 #endif
 
-static struct msm_gpiomux_config msm9615_wlan_configs[] __initdata = {
-	{
-		.gpio	= 2,	/* WLAN_PM_ENABLE */
-		.settings = {
-			[GPIOMUX_ACTIVE] = &wlan_active_config,
-			[GPIOMUX_SUSPENDED] = &wlan_suspend_config,
-		},
-	},
-	{
-		.gpio	= 21,	/* WLAN_RESET_N */
-		.settings = {
-			[GPIOMUX_ACTIVE] = &wlan_active_config,
-			[GPIOMUX_SUSPENDED] = &wlan_suspend_config,
-		},
-	},
-};
-
-
 int __init msm9615_init_gpiomux(void)
 {
 	int rc;
@@ -364,9 +332,6 @@
 	msm_gpiomux_install(msm9615_audio_codec_configs,
 			ARRAY_SIZE(msm9615_audio_codec_configs));
 
-	msm_gpiomux_install(msm9615_wlan_configs,
-			ARRAY_SIZE(msm9615_wlan_configs));
-
 #ifdef CONFIG_FB_MSM_EBI2
 	msm_gpiomux_install(msm9615_ebi2_lcdc_configs,
 			ARRAY_SIZE(msm9615_ebi2_lcdc_configs));
diff --git a/arch/arm/mach-msm/board-9615-storage.c b/arch/arm/mach-msm/board-9615-storage.c
index 6bf7c69..7580cc3 100644
--- a/arch/arm/mach-msm/board-9615-storage.c
+++ b/arch/arm/mach-msm/board-9615-storage.c
@@ -214,19 +214,13 @@
 
 void __init msm9615_init_mmc(void)
 {
-	if (msm9615_sdc1_pdata) {
-		msm9615_sdc1_pdata->swfi_latency =
-			msm9615_rpm_get_swfi_latency();
+	if (msm9615_sdc1_pdata)
 		/* SDC1: External card slot for SD/MMC cards */
 		msm_add_sdcc(1, msm9615_sdc1_pdata);
-	}
 
-	if (msm9615_sdc2_pdata) {
-		msm9615_sdc2_pdata->swfi_latency =
-			msm9615_rpm_get_swfi_latency();
+	if (msm9615_sdc2_pdata)
 		/* SDC2: External card slot used for WLAN */
 		msm_add_sdcc(2, msm9615_sdc2_pdata);
-	}
 }
 #else
 void __init msm9615_init_mmc(void)
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 6c6a5c2..3389dea 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -107,7 +107,7 @@
 	.dev = { .platform_data = &ion_pdata },
 };
 
-static void reserve_ion_memory(void)
+static void __init reserve_ion_memory(void)
 {
 	msm9615_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE;
 }
@@ -132,10 +132,16 @@
 		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
 	{"vph_pwr", CHANNEL_VPH_PWR, CHAN_PATH_SCALING2, AMUX_RSV1,
 		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
-	{"batt_therm", CHANNEL_BATT_THERM, CHAN_PATH_SCALING1, AMUX_RSV2,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_BATT_THERM},
-	{"batt_id", CHANNEL_BATT_ID, CHAN_PATH_SCALING1, AMUX_RSV2,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+	/* AMUX8 is used to read either Batt_id/Batt_therm.
+	 * Current configuration is to support Batt_id. If clients
+	 * want to read the Batt_therm, the scaling function needs to be
+	 * updated to use ADC_SCALE_BATT_THERM instead of ADC_SCALE_DEFAULT.
+	 * E.g.
+	 * {"batt_therm", CHANNEL_BATT_ID_THERM, CHAN_PATH_SCALING1,
+	 * AMUX_RSV2, ADC_DECIMATION_TYPE2, ADC_SCALE_BATT_THERM},
+	 */
+	{"batt_id", CHANNEL_BATT_ID_THERM, CHAN_PATH_SCALING1,
+		AMUX_RSV2, ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
 	{"pmic_therm", CHANNEL_DIE_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
 		ADC_DECIMATION_TYPE2, ADC_SCALE_PMIC_THERM},
 	{"625mv", CHANNEL_625MV, CHAN_PATH_SCALING1, AMUX_RSV1,
diff --git a/arch/arm/mach-msm/board-9615.h b/arch/arm/mach-msm/board-9615.h
index 239453f..7dd003f 100644
--- a/arch/arm/mach-msm/board-9615.h
+++ b/arch/arm/mach-msm/board-9615.h
@@ -36,7 +36,6 @@
 #define GPIO_VREG_ID_EXT_2P95V		0
 
 extern struct gpio_regulator_platform_data msm_gpio_regulator_pdata[];
-uint32_t msm9615_rpm_get_swfi_latency(void);
 
 int msm9615_init_gpiomux(void);
 void msm9615_init_mmc(void);
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index 3500448..ccfc770 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -183,7 +183,7 @@
 	.dev = { .platform_data = &ion_pdata },
 };
 
-static void reserve_ion_memory(void)
+static void __init reserve_ion_memory(void)
 {
 	msm_copper_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_SIZE;
 	msm_copper_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_FW_SIZE;
@@ -225,7 +225,12 @@
 	},
 	{
 		.name	= "wcnss_smsm_in",
-		.start	= 32 + 144,		/* RicaAppsWlanSmsmIrq  */
+		.start	= 32 + 144,		/* RivaAppsWlanSmsmIrq  */
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "rpm_smd_in",
+		.start	= 32 + 168,		/* rpm_to_kpss_ipc_irq4  */
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -300,11 +305,43 @@
 		.smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
 		.smsm_int.out_offset = 0x8,
 	},
+	{
+		.irq_config_id = SMD_RPM,
+		.subsys_name = NULL, /* do not use PIL to load RPM */
+		.edge = SMD_APPS_RPM,
+
+		.smd_int.irq_name = "rpm_smd_in",
+		.smd_int.flags = IRQF_TRIGGER_RISING,
+		.smd_int.irq_id = -1,
+		.smd_int.device_name = "smd_dev",
+		.smd_int.dev_id = 0,
+		.smd_int.out_bit_pos = 1 << 0,
+		.smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smd_int.out_offset = 0x8,
+
+		.smsm_int.irq_name = NULL, /* RPM does not support SMSM */
+		.smsm_int.flags = 0,
+		.smsm_int.irq_id = 0,
+		.smsm_int.device_name = NULL,
+		.smsm_int.dev_id = 0,
+		.smsm_int.out_bit_pos = 0,
+		.smsm_int.out_base = NULL,
+		.smsm_int.out_offset = 0,
+	},
+};
+
+static struct smd_smem_regions aux_smem_areas[] = {
+	{
+		.phys_addr = (void *)(0xfc428000),
+		.size = 0x4000,
+	},
 };
 
 static struct smd_platform smd_platform_data = {
 	.num_ss_configs = ARRAY_SIZE(smd_config_list),
 	.smd_ss_configs = smd_config_list,
+	.num_smem_areas = ARRAY_SIZE(aux_smem_areas),
+	.smd_smem_areas = aux_smem_areas,
 };
 
 struct platform_device msm_device_smd_copper = {
@@ -380,6 +417,7 @@
 }
 
 static struct clk_lookup msm_clocks_dummy[] = {
+	CLK_DUMMY("xo",		XO_CLK,		NULL,	OFF),
 	CLK_DUMMY("core_clk",	BLSP2_UART_CLK,	"msm_serial_hsl.0",	OFF),
 	CLK_DUMMY("iface_clk",	BLSP2_UART_CLK,	"msm_serial_hsl.0",	OFF),
 	CLK_DUMMY("core_clk",	SDC1_CLK,	NULL,			OFF),
@@ -414,6 +452,12 @@
 			"spi_qsd.1", NULL),
 	OF_DEV_AUXDATA("qcom,spmi-pmic-arb", 0xFC4C0000, \
 			"spmi-pmic-arb.0", NULL),
+	OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF980B000, \
+			"msm_sdcc.1", NULL),
+	OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF984B000, \
+			"msm_sdcc.3", NULL),
+	OF_DEV_AUXDATA("qcom,pil-q6v5-lpass",   0xFE200000, \
+			"pil-q6v5-lpass", NULL),
 	{}
 };
 
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index f7333b9..9d01d90 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -276,6 +276,11 @@
 };
 #endif
 
+static struct platform_device msm_camera_server = {
+	.name = "msm_cam_server",
+	.id = 0,
+};
+
 static void __init msm7x27a_init_cam(void)
 {
 	if (!(machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()
@@ -291,6 +296,7 @@
 		sensor_board_info_ov5647.cam_vreg = NULL;
 		sensor_board_info_ov5647.num_vreg = 0;
 	}
+	platform_device_register(&msm_camera_server);
 	if (machine_is_msm8625_surf() || machine_is_msm8625_evb()) {
 		platform_device_register(&msm8625_device_csic0);
 		platform_device_register(&msm8625_device_csic1);
diff --git a/arch/arm/mach-msm/board-msm7627a-io.c b/arch/arm/mach-msm/board-msm7627a-io.c
index 8a2f53a..e622dfe 100644
--- a/arch/arm/mach-msm/board-msm7627a-io.c
+++ b/arch/arm/mach-msm/board-msm7627a-io.c
@@ -394,7 +394,7 @@
 #endif
 
 static struct regulator_bulk_data regs_atmel[] = {
-	{ .supply = "ldo2",  .min_uV = 2850000, .max_uV = 2850000 },
+	{ .supply = "ldo12", .min_uV = 2700000, .max_uV = 3300000 },
 	{ .supply = "smps3", .min_uV = 1800000, .max_uV = 1800000 },
 };
 
@@ -579,7 +579,7 @@
 	},
 };
 
-static void ft5x06_touchpad_setup(void)
+static void __init ft5x06_touchpad_setup(void)
 {
 	int rc;
 
diff --git a/arch/arm/mach-msm/board-msm7627a-storage.c b/arch/arm/mach-msm/board-msm7627a-storage.c
index 11d9a21..946e109 100644
--- a/arch/arm/mach-msm/board-msm7627a-storage.c
+++ b/arch/arm/mach-msm/board-msm7627a-storage.c
@@ -374,8 +374,6 @@
 	if (!(machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7())) {
 		if (mmc_regulator_init(3, "emmc", 3000000))
 			return;
-		sdc3_plat_data.swfi_latency = msm7627a_power_collapse_latency(
-			MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
 		msm_add_sdcc(3, &sdc3_plat_data);
 	}
 #endif
@@ -385,8 +383,6 @@
 	if (mmc_regulator_init(1, "mmc", 2850000))
 		return;
 	sdc1_plat_data.status_irq = MSM_GPIO_TO_INT(gpio_sdc1_hw_det);
-	sdc1_plat_data.swfi_latency = msm7627a_power_collapse_latency(
-			MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
 	msm_add_sdcc(1, &sdc1_plat_data);
 #endif
 	/* SDIO WLAN slot */
diff --git a/arch/arm/mach-msm/board-msm7627a-wlan.c b/arch/arm/mach-msm/board-msm7627a-wlan.c
index b72ecd4..5c2f801 100644
--- a/arch/arm/mach-msm/board-msm7627a-wlan.c
+++ b/arch/arm/mach-msm/board-msm7627a-wlan.c
@@ -285,7 +285,9 @@
 gpio_fail:
 	gpio_free(gpio_wlan_sys_rest_en);
 qrd_gpio_fail:
-	gpio_free(GPIO_WLAN_3V3_EN);
+	/* GPIO_WLAN_3V3_EN is only required for the QRD7627a */
+	if (machine_is_msm7627a_qrd1())
+		gpio_free(GPIO_WLAN_3V3_EN);
 reg_disable:
 	wlan_switch_regulators(0);
 out:
@@ -322,6 +324,7 @@
 		}
 		gpio_set_value(gpio_wlan_sys_rest_en, 0);
 	} else {
+		gpio_request(gpio_wlan_sys_rest_en, "WLAN_DEEP_SLEEP_N");
 		rc = setup_wlan_gpio(on);
 		if (rc) {
 			pr_err("%s: wlan_set_gpio = %d\n", __func__, rc);
@@ -359,7 +362,9 @@
 gpio_fail:
 	gpio_free(gpio_wlan_sys_rest_en);
 qrd_gpio_fail:
-	gpio_free(GPIO_WLAN_3V3_EN);
+	/* GPIO_WLAN_3V3_EN is only required for the QRD7627a */
+	if (machine_is_msm7627a_qrd1())
+		gpio_free(GPIO_WLAN_3V3_EN);
 reg_disable:
 	wlan_switch_regulators(0);
 	pr_info("WLAN power-down failed\n");
diff --git a/arch/arm/mach-msm/board-msm7627a.h b/arch/arm/mach-msm/board-msm7627a.h
index 68e333f..413a28c 100644
--- a/arch/arm/mach-msm/board-msm7627a.h
+++ b/arch/arm/mach-msm/board-msm7627a.h
@@ -103,7 +103,6 @@
 #endif
 
 void __init msm7627a_camera_init(void);
-u32 msm7627a_power_collapse_latency(enum msm_pm_sleep_mode);
 
 void __init msm7627a_add_io_devices(void);
 void __init qrd7627a_add_io_devices(void);
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index c3650fa..2ed5897 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -360,26 +360,6 @@
 	},
 };
 
-u32 msm7627a_power_collapse_latency(enum msm_pm_sleep_mode mode)
-{
-	switch (mode) {
-	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
-		return msm7x27a_pm_data
-		[MSM_PM_SLEEP_MODE_POWER_COLLAPSE].latency;
-	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN:
-		return msm7x27a_pm_data
-		[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN].latency;
-	case MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT:
-		return msm7x27a_pm_data
-		[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
-	case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
-		return msm7x27a_pm_data
-		[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT].latency;
-	default:
-		return 0;
-	}
-}
-
 static struct msm_pm_boot_platform_data msm_pm_boot_pdata __initdata = {
 	.mode = MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS,
 	.p_addr = 0,
@@ -587,8 +567,8 @@
 	(DEC4_FORMAT),
 
 	/* Concurrency 6 */
-	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
 	0, 0, 0,
 
 	/* Concurrency 7 */
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 3973bd1..7fa4968 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -993,8 +993,14 @@
 	.camera_type = BACK_CAMERA_2D,
 };
 
+static struct platform_device msm_camera_server = {
+	.name = "msm_cam_server",
+	.id = 0,
+};
+
 void __init msm7x30_init_cam(void)
 {
+	platform_device_register(&msm_camera_server);
 	platform_device_register(&msm_device_csic0);
 	platform_device_register(&msm_device_vfe);
 	platform_device_register(&msm_device_vpe);
@@ -3173,26 +3179,6 @@
 	},
 };
 
-u32 msm7x30_power_collapse_latency(enum msm_pm_sleep_mode mode)
-{
-	switch (mode) {
-	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
-		return msm_pm_data
-		[MSM_PM_SLEEP_MODE_POWER_COLLAPSE].latency;
-	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN:
-		return msm_pm_data
-		[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN].latency;
-	case MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT:
-		return msm_pm_data
-		[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
-	case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
-		return msm_pm_data
-		[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT].latency;
-	default:
-	return 0;
-	}
-}
-
 static struct msm_pm_boot_platform_data msm_pm_boot_pdata __initdata = {
 	.mode = MSM_PM_BOOT_CONFIG_RESET_VECTOR_VIRT,
 	.v_addr = (uint32_t *)PAGE_OFFSET,
@@ -6401,8 +6387,6 @@
 #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
 	if (mmc_regulator_init(1, "s3", 1800000))
 		goto out1;
-	msm7x30_sdc1_data.swfi_latency = msm7x30_power_collapse_latency(
-		MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
 
 	if (machine_is_msm7x30_fluid()) {
 		msm7x30_sdc1_data.ocr_mask =  MMC_VDD_27_28 | MMC_VDD_28_29;
@@ -6418,8 +6402,6 @@
 #ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
 	if (mmc_regulator_init(2, "s3", 1800000))
 		goto out2;
-	msm7x30_sdc2_data.swfi_latency = msm7x30_power_collapse_latency(
-		MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
 
 	if (machine_is_msm8x55_svlte_surf())
 		msm7x30_sdc2_data.msmsdcc_fmax =  24576000;
@@ -6435,8 +6417,6 @@
 #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
 	if (mmc_regulator_init(3, "s3", 1800000))
 		goto out3;
-	msm7x30_sdc3_data.swfi_latency = msm7x30_power_collapse_latency(
-		MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
 
 	msm_sdcc_setup_gpio(3, 1);
 	msm_add_sdcc(3, &msm7x30_sdc3_data);
@@ -6445,8 +6425,6 @@
 #ifdef CONFIG_MMC_MSM_SDC4_SUPPORT
 	if (mmc_regulator_init(4, "mmc", 2850000))
 		return;
-	msm7x30_sdc4_data.swfi_latency = msm7x30_power_collapse_latency(
-		MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
 
 	msm_add_sdcc(4, &msm7x30_sdc4_data);
 #endif
diff --git a/arch/arm/mach-msm/board-msm8x60-camera.c b/arch/arm/mach-msm/board-msm8x60-camera.c
index c12dce6..743ca4d 100644
--- a/arch/arm/mach-msm/board-msm8x60-camera.c
+++ b/arch/arm/mach-msm/board-msm8x60-camera.c
@@ -413,14 +413,14 @@
 
 
 static struct i2c_board_info imx074_actuator_i2c_info = {
-	I2C_BOARD_INFO("imx074_act", 0x11),
+	I2C_BOARD_INFO("msm_actuator", 0x11),
 };
 
 static struct msm_actuator_info imx074_actuator_info = {
 	.board_info     = &imx074_actuator_i2c_info,
+	.cam_name   = MSM_ACTUATOR_MAIN_CAM_0,
 	.bus_id         = MSM_GSBI4_QUP_I2C_BUS_ID,
-	.vcm_pwd        = 0,
-	.vcm_enable     = 1,
+	.vcm_enable     = 0,
 };
 
 static struct msm_camera_sensor_flash_data flash_imx074 = {
@@ -431,7 +431,7 @@
 };
 
 static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
-	.mount_angle	= 0,
+	.mount_angle	= 180,
 	.cam_vreg = msm_8x60_back_cam_vreg,
 	.num_vreg = ARRAY_SIZE(msm_8x60_back_cam_vreg),
 	.gpio_conf = &msm_8x60_back_cam_gpio_conf,
@@ -448,8 +448,14 @@
 	.actuator_info = &imx074_actuator_info
 };
 
+static struct platform_device msm_camera_server = {
+	.name = "msm_cam_server",
+	.id = 0,
+};
+
 void __init msm8x60_init_cam(void)
 {
+	platform_device_register(&msm_camera_server);
 	platform_device_register(&msm_device_csic0);
 	platform_device_register(&msm_device_csic1);
 	platform_device_register(&msm_device_vfe);
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index da362a0..5fc17df 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -5409,7 +5409,7 @@
 	},
 };
 
-static void reserve_ion_memory(void)
+static void __init reserve_ion_memory(void)
 {
 #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
 	unsigned int i;
@@ -7275,7 +7275,7 @@
 };
 #endif /* CONFIG_I2C */
 
-static void fixup_i2c_configs(void)
+static void __init fixup_i2c_configs(void)
 {
 #ifdef CONFIG_I2C
 #if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
@@ -7293,7 +7293,7 @@
 #endif
 }
 
-static void register_i2c_devices(void)
+static void __init register_i2c_devices(void)
 {
 #ifdef CONFIG_I2C
 	u8 mach_mask = 0;
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 3e8dd8f..86bf205 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -510,8 +510,8 @@
 	(DEC4_FORMAT),
 
 	/* Concurrency 6 */
-	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
 	0, 0, 0,
 
 	/* Concurrency 7 */
@@ -806,7 +806,7 @@
 				msm_num_footswitch_devices);
 }
 
-static void add_platform_devices(void)
+static void __init add_platform_devices(void)
 {
 	if (machine_is_msm8625_evb() || machine_is_msm8625_qrd7()) {
 		platform_add_devices(msm8625_evb_devices,
diff --git a/arch/arm/mach-msm/cache_erp.c b/arch/arm/mach-msm/cache_erp.c
index 1eb229a..97225ac 100644
--- a/arch/arm/mach-msm/cache_erp.c
+++ b/arch/arm/mach-msm/cache_erp.c
@@ -17,7 +17,11 @@
 #include <linux/errno.h>
 #include <linux/proc_fs.h>
 #include <linux/cpu.h>
+#include <linux/io.h>
 #include <mach/msm-krait-l2-accessors.h>
+#include <mach/msm_iomap.h>
+#include <asm/cputype.h>
+#include "acpuclock.h"
 
 #define CESR_DCTPE		BIT(0)
 #define CESR_DCDPE		BIT(1)
@@ -28,6 +32,9 @@
 #define CESR_TLBMH		BIT(16)
 #define CESR_I_MASK		0x000000CC
 
+/* Print a message for everything but TLB MH events */
+#define CESR_PRINT_MASK		0x000000FF
+
 #define L2ESR_IND_ADDR		0x204
 #define L2ESYNR0_IND_ADDR	0x208
 #define L2ESYNR1_IND_ADDR	0x209
@@ -190,9 +197,26 @@
 	struct msm_l1_err_stats *l1_stats = dev_id;
 	unsigned int cesr = read_cesr();
 	unsigned int i_cesynr, d_cesynr;
+	unsigned int cpu = smp_processor_id();
+	int print_regs = cesr & CESR_PRINT_MASK;
 
-	pr_alert("L1 Error detected on CPU %d!\n", smp_processor_id());
-	pr_alert("\tCESR    = 0x%08x\n", cesr);
+	void *const saw_bases[] = {
+		MSM_SAW0_BASE,
+		MSM_SAW1_BASE,
+		MSM_SAW2_BASE,
+		MSM_SAW3_BASE,
+	};
+
+	if (print_regs) {
+		pr_alert("L1 / TLB Error detected on CPU %d!\n", cpu);
+		pr_alert("\tCESR      = 0x%08x\n", cesr);
+		pr_alert("\tCPU speed = %lu\n", acpuclk_get_rate(cpu));
+		pr_alert("\tMIDR      = 0x%08x\n", read_cpuid_id());
+		pr_alert("\tPTE fuses = 0x%08x\n",
+					readl_relaxed(MSM_QFPROM_BASE + 0xC0));
+		pr_alert("\tPMIC_VREG = 0x%08x\n",
+					readl_relaxed(saw_bases[cpu] + 0x14));
+	}
 
 	if (cesr & CESR_DCTPE) {
 		pr_alert("D-cache tag parity error\n");
@@ -225,7 +249,7 @@
 	}
 
 	if (cesr & CESR_TLBMH) {
-		pr_alert("TLB multi-hit error\n");
+		asm ("mcr p15, 0, r0, c8, c7, 0");
 		l1_stats->tlbmh++;
 	}
 
@@ -250,7 +274,8 @@
 	/* Clear the interrupt bits we processed */
 	write_cesr(cesr);
 
-	ERP_L1_ERR("L1 cache / TLB error detected");
+	if (print_regs)
+		ERP_L1_ERR("L1 cache error detected");
 
 	return IRQ_HANDLED;
 }
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index 5951734..5ba3577 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -157,8 +157,6 @@
 		.ns_val = N8(nmsb, nlsb, m, n) | SPDIV(SRC_SEL_##s, div), \
 	}
 
-static struct clk_ops clk_ops_rcg_7x30;
-
 enum vdd_dig_levels {
 	VDD_DIG_NONE,
 	VDD_DIG_LOW,
@@ -324,8 +322,6 @@
 	},
 };
 
-static struct clk_ops clk_ops_branch;
-
 static struct clk_freq_tbl clk_tbl_axi[] = {
 	F_RAW(1, &lpxo_clk.c, 0, 0, 0, NULL),
 	F_END,
@@ -344,7 +340,7 @@
 	.set_rate = set_rate_nop,
 	.c = {
 		.dbg_name = "glbl_root_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 1),
 		CLK_INIT(glbl_root_clk.c),
 	},
@@ -1011,7 +1007,7 @@
 	.set_rate = set_rate_mnd,
 	.c = {
 		.dbg_name = "csi0_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 384000000),
 		CLK_INIT(csi0_clk.c),
 	},
@@ -1036,7 +1032,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "i2c_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 19200000),
 		CLK_INIT(i2c_clk.c),
 	},
@@ -1056,7 +1052,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "i2c_2_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 19200000),
 		CLK_INIT(i2c_2_clk.c),
 	},
@@ -1076,7 +1072,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "qup_i2c_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 19200000),
 		CLK_INIT(qup_i2c_clk.c),
 	},
@@ -1096,7 +1092,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "uart1_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 19200000),
 		CLK_INIT(uart1_clk.c),
 	},
@@ -1116,7 +1112,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "uart2_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 19200000),
 		CLK_INIT(uart2_clk.c),
 	},
@@ -1156,7 +1152,7 @@
 	.set_rate = set_rate_mnd,
 	.c = {
 		.dbg_name = "uart1dm_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 64000000),
 		CLK_INIT(uart1dm_clk.c),
 	},
@@ -1180,7 +1176,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "uart2dm_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 64000000),
 		CLK_INIT(uart2dm_clk.c),
 	},
@@ -1214,7 +1210,7 @@
 	.c = {
 		.dbg_name = "emdh_clk",
 		.flags = CLKFLAG_MIN | CLKFLAG_MAX,
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 445500000),
 		CLK_INIT(emdh_clk.c),
 		.depends = &axi_li_adsp_a_clk.c,
@@ -1236,7 +1232,7 @@
 	.c = {
 		.dbg_name = "pmdh_clk",
 		.flags = CLKFLAG_MIN | CLKFLAG_MAX,
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 445500000),
 		CLK_INIT(pmdh_clk.c),
 		.depends = &axi_li_adsp_a_clk.c,
@@ -1281,7 +1277,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "grp_2d_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(NOMINAL, 192000000, HIGH, 245760000),
 		CLK_INIT(grp_2d_clk.c),
 		.depends = &axi_grp_2d_clk.c,
@@ -1301,7 +1297,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "grp_3d_src_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(NOMINAL, 192000000, HIGH, 245760000),
 		CLK_INIT(grp_3d_src_clk.c),
 		.depends = &axi_li_grp_clk.c,
@@ -1370,7 +1366,7 @@
 	.set_rate = set_rate_mnd,
 	.c = {
 		.dbg_name = "sdc1_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 49152000),
 		CLK_INIT(sdc1_clk.c),
 	},
@@ -1394,7 +1390,7 @@
 	.set_rate = set_rate_mnd,
 	.c = {
 		.dbg_name = "sdc3_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 49152000),
 		CLK_INIT(sdc3_clk.c),
 	},
@@ -1430,7 +1426,7 @@
 	.set_rate = set_rate_mnd,
 	.c = {
 		.dbg_name = "sdc2_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 49152000),
 		CLK_INIT(sdc2_clk.c),
 	},
@@ -1454,7 +1450,7 @@
 	.set_rate = set_rate_mnd,
 	.c = {
 		.dbg_name = "sdc4_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 49152000),
 		CLK_INIT(sdc4_clk.c),
 	},
@@ -1489,7 +1485,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "mdp_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(NOMINAL, 153600000, HIGH, 192000000),
 		CLK_INIT(mdp_clk.c),
 		.depends = &axi_mdp_clk.c,
@@ -1524,7 +1520,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "mdp_lcdc_pclk_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 73728000),
 		CLK_INIT(mdp_lcdc_pclk_clk.c),
 	},
@@ -1567,7 +1563,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "mdp_vsync_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 24576000),
 		CLK_INIT(mdp_vsync_clk.c),
 	},
@@ -1598,7 +1594,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "mi2s_codec_rx_m_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 12288000),
 		CLK_INIT(mi2s_codec_rx_m_clk.c),
 	},
@@ -1638,7 +1634,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "mi2s_codec_tx_m_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 12288000),
 		CLK_INIT(mi2s_codec_tx_m_clk.c),
 	},
@@ -1684,7 +1680,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "mi2s_m_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 12288000),
 		CLK_INIT(mi2s_m_clk.c),
 	},
@@ -1745,7 +1741,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "sdac_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 1536000),
 		CLK_INIT(sdac_clk.c),
 	},
@@ -1789,7 +1785,7 @@
 	.set_rate = set_rate_mnd,
 	.c = {
 		.dbg_name = "tv_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 74250000),
 		CLK_INIT(tv_clk.c),
 	},
@@ -1881,7 +1877,7 @@
 	.set_rate = set_rate_mnd,
 	.c = {
 		.dbg_name = "usb_hs_src_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 60000000),
 		CLK_INIT(usb_hs_src_clk.c),
 		.depends = &axi_li_adsp_a_clk.c,
@@ -2018,7 +2014,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "jpeg_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(NOMINAL, 153600000, HIGH, 192000000),
 		CLK_INIT(jpeg_clk.c),
 		.depends = &axi_li_jpeg_clk.c,
@@ -2043,7 +2039,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "vfe_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(NOMINAL, 153600000, HIGH, 192000000),
 		CLK_INIT(vfe_clk.c),
 		.depends = &axi_li_vfe_clk.c,
@@ -2128,7 +2124,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "cam_m_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 64000000),
 		CLK_INIT(cam_m_clk.c),
 	},
@@ -2163,7 +2159,7 @@
 	.set_rate = set_rate_mnd,
 	.c = {
 		.dbg_name = "vpe_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 153600000),
 		CLK_INIT(vpe_clk.c),
 		.depends = &axi_vpe_clk.c,
@@ -2200,7 +2196,7 @@
 	.set_rate = set_rate_mnd,
 	.c = {
 		.dbg_name = "mfc_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 170667000),
 		CLK_INIT(mfc_clk.c),
 		.depends = &axi_mfc_clk.c,
@@ -2249,7 +2245,7 @@
 	.set_rate = set_rate_mnd,
 	.c = {
 		.dbg_name = "spi_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 26331429),
 		CLK_INIT(spi_clk.c),
 	},
@@ -2278,7 +2274,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "lpa_codec_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 4),
 		CLK_INIT(lpa_codec_clk.c),
 	},
@@ -2304,7 +2300,7 @@
 	.set_rate = set_rate_nop,
 	.c = {
 		.dbg_name = "mdc_clk",
-		.ops = &clk_ops_rcg_7x30,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 1),
 		CLK_INIT(mdc_clk.c),
 	},
@@ -2800,8 +2796,8 @@
 	OWN(APPS1,  6, "iface_clk",	grp_2d_p_clk,	"kgsl-2d0.0"),
 	OWN(APPS1,  6, "iface_clk",	grp_2d_p_clk,	"footswitch-pcom.0"),
 	OWN(APPS1, 31, "hdmi_clk",	hdmi_clk,	"dtv.0"),
-	OWN(APPS1,  0, "jpeg_clk",	jpeg_clk,	NULL),
-	OWN(APPS1,  0, "jpeg_pclk",	jpeg_p_clk,	NULL),
+	OWN(APPS1,  0, "jpeg_clk",	jpeg_clk,	"msm_gemini.0"),
+	OWN(APPS1,  0, "jpeg_pclk",	jpeg_p_clk,	"msm_gemini.0"),
 	OWN(APPS1, 23, "lpa_codec_clk", lpa_codec_clk,	NULL),
 	OWN(APPS1, 23, "lpa_core_clk",	lpa_core_clk,	NULL),
 	OWN(APPS1, 23, "lpa_pclk",	lpa_p_clk,	NULL),
@@ -2975,6 +2971,10 @@
 	int i;
 	uint32_t val;
 
+	clk_ops_branch.reset = soc_branch_clk_reset;
+	clk_ops_rcg.reset = msm7x30_clk_reset;
+	clk_ops_rcg.set_flags = soc_clk_set_flags;
+
 	cache_ownership();
 	print_ownership();
 	set_clock_ownership();
@@ -3015,29 +3015,3 @@
 	.pre_init = msm7x30_clock_pre_init,
 	.post_init = msm7x30_clock_post_init,
 };
-
-/*
- * Clock operation handler registration
- */
-static struct clk_ops clk_ops_rcg_7x30 = {
-	.enable = rcg_clk_enable,
-	.disable = rcg_clk_disable,
-	.auto_off = rcg_clk_disable,
-	.set_rate = rcg_clk_set_rate,
-	.list_rate = rcg_clk_list_rate,
-	.is_enabled = rcg_clk_is_enabled,
-	.round_rate = rcg_clk_round_rate,
-	.reset = msm7x30_clk_reset,
-	.set_flags = soc_clk_set_flags,
-	.get_parent = rcg_clk_get_parent,
-};
-
-static struct clk_ops clk_ops_branch = {
-	.enable = branch_clk_enable,
-	.disable = branch_clk_disable,
-	.auto_off = branch_clk_disable,
-	.is_enabled = branch_clk_is_enabled,
-	.reset = soc_branch_clk_reset,
-	.set_flags = soc_clk_set_flags,
-	.get_parent = branch_clk_get_parent,
-};
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index aa25103..0997e8bd 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -556,41 +556,6 @@
 	},
 };
 
-static struct clk_ops clk_ops_rcg_8960 = {
-	.enable = rcg_clk_enable,
-	.disable = rcg_clk_disable,
-	.enable_hwcg = rcg_clk_enable_hwcg,
-	.disable_hwcg = rcg_clk_disable_hwcg,
-	.in_hwcg_mode = rcg_clk_in_hwcg_mode,
-	.auto_off = rcg_clk_disable,
-	.handoff = rcg_clk_handoff,
-	.set_rate = rcg_clk_set_rate,
-	.list_rate = rcg_clk_list_rate,
-	.is_enabled = rcg_clk_is_enabled,
-	.round_rate = rcg_clk_round_rate,
-	.reset = rcg_clk_reset,
-	.get_parent = rcg_clk_get_parent,
-	.set_flags = rcg_clk_set_flags,
-};
-
-static struct clk_ops clk_ops_branch = {
-	.enable = branch_clk_enable,
-	.disable = branch_clk_disable,
-	.enable_hwcg = branch_clk_enable_hwcg,
-	.disable_hwcg = branch_clk_disable_hwcg,
-	.in_hwcg_mode = branch_clk_in_hwcg_mode,
-	.auto_off = branch_clk_disable,
-	.is_enabled = branch_clk_is_enabled,
-	.reset = branch_clk_reset,
-	.get_parent = branch_clk_get_parent,
-	.handoff = branch_clk_handoff,
-	.set_flags = branch_clk_set_flags,
-};
-
-static struct clk_ops clk_ops_reset = {
-	.reset = branch_clk_reset,
-};
-
 /* AXI Interfaces */
 static struct branch_clk gmem_axi_clk = {
 	.b = {
@@ -1238,7 +1203,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_8960, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000), \
 			CLK_INIT(i##_clk.c), \
 		}, \
@@ -1288,7 +1253,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_8960, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 64000000), \
 			CLK_INIT(i##_clk.c), \
 		}, \
@@ -1352,7 +1317,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_8960, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP2(LOW, 24000000, NOMINAL, 52000000), \
 			CLK_INIT(i##_clk.c), \
 		}, \
@@ -1420,7 +1385,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "pdm_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 27000000),
 		CLK_INIT(pdm_clk.c),
 	},
@@ -1465,7 +1430,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "prng_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 65000000),
 		CLK_INIT(prng_clk.c),
 	},
@@ -1491,7 +1456,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #name, \
-			.ops = &clk_ops_rcg_8960, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP2(LOW, fmax_low, NOMINAL, fmax_nom), \
 			CLK_INIT(name.c), \
 		}, \
@@ -1554,7 +1519,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "tsif_ref_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 27000000, NOMINAL, 54000000),
 		CLK_INIT(tsif_ref_clk.c),
 	},
@@ -1586,7 +1551,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "tssc_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 27000000),
 		CLK_INIT(tssc_clk.c),
 	},
@@ -1612,7 +1577,7 @@
 	.current_freq = &rcg_dummy_freq, \
 	.c = { \
 		.dbg_name = #name, \
-		.ops = &clk_ops_rcg_8960, \
+		.ops = &clk_ops_rcg, \
 		VDD_DIG_FMAX_MAP1(NOMINAL, 64000000), \
 		CLK_INIT(name.c), \
 	}, \
@@ -1658,7 +1623,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "usb_hsic_xcvr_fs_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 60000000),
 		CLK_INIT(usb_hsic_xcvr_fs_clk.c),
 	},
@@ -1702,7 +1667,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "usb_hsic_hsic_src_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 480000000),
 		CLK_INIT(usb_hsic_hsic_src_clk.c),
 	},
@@ -1745,7 +1710,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "usb_hsic_hsio_cal_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 10000000),
 		CLK_INIT(usb_hsic_hsio_cal_clk.c),
 	},
@@ -1779,7 +1744,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_8960, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP1(NOMINAL, fmax_nom), \
 			CLK_INIT(i##_clk.c), \
 		}, \
@@ -1913,7 +1878,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "ce3_src_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
 		CLK_INIT(ce3_src_clk.c),
 	},
@@ -2504,7 +2469,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #name, \
-			.ops = &clk_ops_rcg_8960, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP2(LOW, 64000000, NOMINAL, 128000000), \
 			CLK_INIT(name.c), \
 		}, \
@@ -2569,7 +2534,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "csi0_src_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
 		CLK_INIT(csi0_src_clk.c),
 	},
@@ -2625,7 +2590,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "csi1_src_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
 		CLK_INIT(csi1_src_clk.c),
 	},
@@ -2681,7 +2646,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "csi2_src_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
 		CLK_INIT(csi2_src_clk.c),
 	},
@@ -3011,7 +2976,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "csiphy_timer_src_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
 		CLK_INIT(csiphy_timer_src_clk.c),
 	},
@@ -3099,7 +3064,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "dsi1_byte_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		CLK_INIT(dsi1_byte_clk.c),
 	},
 };
@@ -3123,7 +3088,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "dsi2_byte_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		CLK_INIT(dsi2_byte_clk.c),
 	},
 };
@@ -3144,7 +3109,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "dsi1_esc_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		CLK_INIT(dsi1_esc_clk.c),
 	},
 };
@@ -3164,7 +3129,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "dsi2_esc_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		CLK_INIT(dsi2_esc_clk.c),
 	},
 };
@@ -3231,7 +3196,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "gfx2d0_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP3(LOW,  100000000, NOMINAL, 200000000,
 				  HIGH, 228571000),
 		CLK_INIT(gfx2d0_clk.c),
@@ -3275,7 +3240,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "gfx2d1_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP3(LOW,  100000000, NOMINAL, 200000000,
 				  HIGH, 228571000),
 		CLK_INIT(gfx2d1_clk.c),
@@ -3403,7 +3368,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "gfx3d_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP3(LOW,  128000000, NOMINAL, 300000000,
 				  HIGH, 400000000),
 		CLK_INIT(gfx3d_clk.c),
@@ -3465,7 +3430,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "vcap_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		.depends = &vcap_axi_clk.c,
 		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
 		CLK_INIT(vcap_clk.c),
@@ -3540,7 +3505,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "ijpeg_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP3(LOW, 110000000, NOMINAL, 266667000,
 				  HIGH, 320000000),
 		CLK_INIT(ijpeg_clk.c),
@@ -3583,7 +3548,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "jpegd_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 96000000, NOMINAL, 200000000),
 		CLK_INIT(jpegd_clk.c),
 		.depends = &jpegd_axi_clk.c,
@@ -3660,7 +3625,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "mdp_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 96000000, NOMINAL, 200000000),
 		CLK_INIT(mdp_clk.c),
 		.depends = &mdp_axi_clk.c,
@@ -3711,7 +3676,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "mdp_vsync_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 27000000),
 		CLK_INIT(mdp_vsync_clk.c),
 	},
@@ -3772,7 +3737,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "rot_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 96000000, NOMINAL, 200000000),
 		CLK_INIT(rot_clk.c),
 		.depends = &rot_axi_clk.c,
@@ -3883,7 +3848,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "tv_src_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 27030000, NOMINAL, 149000000),
 		CLK_INIT(tv_src_clk.c),
 	},
@@ -4075,7 +4040,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "vcodec_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP3(LOW,  100000000, NOMINAL, 200000000,
 				  HIGH, 228571000),
 		CLK_INIT(vcodec_clk.c),
@@ -4121,7 +4086,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "vpe_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 76800000, NOMINAL, 160000000),
 		CLK_INIT(vpe_clk.c),
 		.depends = &vpe_axi_clk.c,
@@ -4187,7 +4152,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "vfe_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP3(LOW, 110000000, NOMINAL, 266667000,
 				  HIGH, 320000000),
 		CLK_INIT(vfe_clk.c),
@@ -4259,7 +4224,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_8960, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP1(LOW, 24576000), \
 			CLK_INIT(i##_clk.c), \
 		}, \
@@ -4285,7 +4250,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_8960, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP1(LOW, 24576000), \
 			CLK_INIT(i##_clk.c), \
 		}, \
@@ -4361,7 +4326,7 @@
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
 	}
 static struct clk_freq_tbl clk_tbl_pcm[] = {
-	F_PCM(       0, gnd,  1, 0,   0),
+	{ .ns_val = BIT(10) /* external input */ },
 	F_PCM(  512000, pll4, 4, 1, 192),
 	F_PCM(  768000, pll4, 4, 1, 128),
 	F_PCM( 1024000, pll4, 4, 1,  96),
@@ -4389,14 +4354,14 @@
 	.ns_reg = LCC_PCM_NS_REG,
 	.md_reg = LCC_PCM_MD_REG,
 	.root_en_mask = BIT(9),
-	.ns_mask = (BM(31, 16) | BM(6, 0)),
+	.ns_mask = BM(31, 16) | BIT(10) | BM(6, 0),
 	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_pcm,
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "pcm_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 24576000),
 		CLK_INIT(pcm_clk.c),
 	},
@@ -4422,7 +4387,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "audio_slimbus_clk",
-		.ops = &clk_ops_rcg_8960,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 24576000),
 		CLK_INIT(audio_slimbus_clk.c),
 	},
@@ -5047,8 +5012,8 @@
 	CLK_LOOKUP("vcap_npl_clk",      vcap_npl_clk.c,         ""),
 	CLK_LOOKUP("vcap_npl_clk",      vcap_npl_clk.c,         "msm_vcap.0"),
 	CLK_LOOKUP("bus_clk",		ijpeg_axi_clk.c, "footswitch-8x60.3"),
-	CLK_LOOKUP("mem_clk",		imem_axi_clk.c,		""),
-	CLK_LOOKUP("ijpeg_clk",         ijpeg_clk.c,            ""),
+	CLK_LOOKUP("imem_clk",		imem_axi_clk.c,		"msm_gemini.0"),
+	CLK_LOOKUP("ijpeg_clk",         ijpeg_clk.c,    "msm_gemini.0"),
 	CLK_LOOKUP("core_clk",		ijpeg_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("core_clk",		jpegd_clk.c,		""),
 	CLK_LOOKUP("core_clk",		mdp_clk.c,		"mdp.0"),
@@ -5093,7 +5058,7 @@
 	CLK_LOOKUP("iface_clk",		gfx3d_p_clk.c,	"footswitch-8x60.2"),
 	CLK_LOOKUP("master_iface_clk",	hdmi_m_p_clk.c,		"hdmi_msm.1"),
 	CLK_LOOKUP("slave_iface_clk",	hdmi_s_p_clk.c,		"hdmi_msm.1"),
-	CLK_LOOKUP("ijpeg_pclk",	ijpeg_p_clk.c,		""),
+	CLK_LOOKUP("ijpeg_pclk",	ijpeg_p_clk.c,		"msm_gemini.0"),
 	CLK_LOOKUP("iface_clk",		ijpeg_p_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("iface_clk",		jpegd_p_clk.c,		""),
 	CLK_LOOKUP("mem_iface_clk",	imem_p_clk.c,	"kgsl-3d0.0"),
@@ -5111,6 +5076,8 @@
 
 	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,		"msm-dai-q6.6"),
 	CLK_LOOKUP("osr_clk",		mi2s_osr_clk.c,		"msm-dai-q6.6"),
+	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,		"msm-dai-q6.7"),
+	CLK_LOOKUP("osr_clk",		mi2s_osr_clk.c,		"msm-dai-q6.7"),
 	CLK_LOOKUP("bit_clk",		codec_i2s_mic_bit_clk.c,
 			   "msm-dai-q6.1"),
 	CLK_LOOKUP("osr_clk",		codec_i2s_mic_osr_clk.c,
@@ -5175,6 +5142,11 @@
 	CLK_LOOKUP("core_clk",		gfx3d_axi_clk_8064.c,	"msm_iommu.10"),
 	CLK_LOOKUP("core_clk",		vcap_axi_clk.c,		"msm_iommu.11"),
 
+	CLK_LOOKUP("mdp_iommu_clk", mdp_axi_clk.c,	"msm_vidc.0"),
+	CLK_LOOKUP("rot_iommu_clk",	rot_axi_clk.c,	"msm_vidc.0"),
+	CLK_LOOKUP("vcodec_iommu0_clk", vcodec_axi_a_clk.c, "msm_vidc.0"),
+	CLK_LOOKUP("vcodec_iommu1_clk", vcodec_axi_b_clk.c, "msm_vidc.0"),
+	CLK_LOOKUP("smmu_iface_clk", smmu_p_clk.c,	"msm_vidc.0"),
 	CLK_LOOKUP("core_clk",		vcodec_axi_clk.c,  "pil_vidc"),
 	CLK_LOOKUP("smmu_iface_clk",	smmu_p_clk.c,  "pil_vidc"),
 
@@ -5349,8 +5321,8 @@
 	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	"footswitch-8x60.2"),
 	CLK_LOOKUP("bus_clk",		ijpeg_axi_clk.c, "footswitch-8x60.3"),
-	CLK_LOOKUP("imem_clk",		imem_axi_clk.c,		NULL),
-	CLK_LOOKUP("ijpeg_clk",         ijpeg_clk.c,            NULL),
+	CLK_LOOKUP("imem_clk",		imem_axi_clk.c,		"msm_gemini.0"),
+	CLK_LOOKUP("ijpeg_clk",     ijpeg_clk.c,    "msm_gemini.0"),
 	CLK_LOOKUP("core_clk",		ijpeg_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("core_clk",		jpegd_clk.c,		""),
 	CLK_LOOKUP("core_clk",		mdp_clk.c,		"mdp.0"),
@@ -5402,7 +5374,7 @@
 	CLK_LOOKUP("iface_clk",		gfx3d_p_clk.c,	"footswitch-8x60.2"),
 	CLK_LOOKUP("master_iface_clk",	hdmi_m_p_clk.c,	"hdmi_msm.1"),
 	CLK_LOOKUP("slave_iface_clk",	hdmi_s_p_clk.c,	"hdmi_msm.1"),
-	CLK_LOOKUP("ijpeg_pclk",	ijpeg_p_clk.c,		NULL),
+	CLK_LOOKUP("ijpeg_pclk",	ijpeg_p_clk.c,		"msm_gemini.0"),
 	CLK_LOOKUP("iface_clk",		ijpeg_p_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("iface_clk",		jpegd_p_clk.c,		""),
 	CLK_LOOKUP("mem_iface_clk",	imem_p_clk.c,	"kgsl-3d0.0"),
@@ -5420,6 +5392,8 @@
 	CLK_LOOKUP("iface_clk",		vpe_p_clk.c,	"footswitch-8x60.9"),
 	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,		"msm-dai-q6.6"),
 	CLK_LOOKUP("osr_clk",		mi2s_osr_clk.c,		"msm-dai-q6.6"),
+	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,		"msm-dai-q6.7"),
+	CLK_LOOKUP("osr_clk",		mi2s_osr_clk.c,		"msm-dai-q6.7"),
 	CLK_LOOKUP("bit_clk",		codec_i2s_mic_bit_clk.c,
 			   "msm-dai-q6.1"),
 	CLK_LOOKUP("osr_clk",		codec_i2s_mic_osr_clk.c,
@@ -5600,7 +5574,7 @@
 	CLK_LOOKUP("core_clk",		pmic_ssbi2_clk.c,	""),
 	CLK_LOOKUP("mem_clk",		rpm_msg_ram_p_clk.c,	""),
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-001a"),
-	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-006c"),
+	CLK_LOOKUP("cam_clk",		cam1_clk.c,	"4-006c"),
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-0048"),
 	CLK_LOOKUP("cam_clk",		cam2_clk.c,		NULL),
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-0020"),
@@ -5638,8 +5612,8 @@
 	CLK_LOOKUP("bus_clk",
 			    gfx3d_axi_clk_8930.c, "footswitch-8x60.2"),
 	CLK_LOOKUP("bus_clk",		ijpeg_axi_clk.c, "footswitch-8x60.3"),
-	CLK_LOOKUP("imem_clk",		imem_axi_clk.c,		NULL),
-	CLK_LOOKUP("ijpeg_clk",         ijpeg_clk.c,            NULL),
+	CLK_LOOKUP("imem_clk",		imem_axi_clk.c,		"msm_gemini.0"),
+	CLK_LOOKUP("ijpeg_clk",         ijpeg_clk.c,    "msm_gemini.0"),
 	CLK_LOOKUP("core_clk",		ijpeg_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("core_clk",		mdp_clk.c,		"mdp.0"),
 	CLK_LOOKUP("core_clk",		mdp_clk.c,	"footswitch-8x60.4"),
@@ -5682,7 +5656,7 @@
 	CLK_LOOKUP("iface_clk",		gfx3d_p_clk.c,	"footswitch-8x60.2"),
 	CLK_LOOKUP("master_iface_clk",	hdmi_m_p_clk.c,	"hdmi_msm.1"),
 	CLK_LOOKUP("slave_iface_clk",	hdmi_s_p_clk.c,	"hdmi_msm.1"),
-	CLK_LOOKUP("ijpeg_pclk",	ijpeg_p_clk.c,		NULL),
+	CLK_LOOKUP("ijpeg_pclk",	ijpeg_p_clk.c,		"msm_gemini.0"),
 	CLK_LOOKUP("iface_clk",		ijpeg_p_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("mem_iface_clk",	imem_p_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("iface_clk",		mdp_p_clk.c,		"mdp.0"),
@@ -6088,10 +6062,10 @@
 	 * The halt status bits for these clocks may be incorrect at boot.
 	 * Toggle these clocks on and off to refresh them.
 	 */
-	rcg_clk_enable(&pdm_clk.c);
-	rcg_clk_disable(&pdm_clk.c);
-	rcg_clk_enable(&tssc_clk.c);
-	rcg_clk_disable(&tssc_clk.c);
+	clk_prepare_enable(&pdm_clk.c);
+	clk_disable_unprepare(&pdm_clk.c);
+	clk_prepare_enable(&tssc_clk.c);
+	clk_disable_unprepare(&tssc_clk.c);
 	clk_prepare_enable(&usb_hsic_hsic_clk.c);
 	clk_disable_unprepare(&usb_hsic_hsic_clk.c);
 
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 53dbebe..26ccaa3 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -431,34 +431,6 @@
 	writel_relaxed(pll_mode, MM_PLL2_MODE_REG);
 }
 
-static struct clk_ops clk_ops_rcg_8x60 = {
-	.enable = rcg_clk_enable,
-	.disable = rcg_clk_disable,
-	.auto_off = rcg_clk_disable,
-	.handoff = rcg_clk_handoff,
-	.set_rate = rcg_clk_set_rate,
-	.list_rate = rcg_clk_list_rate,
-	.is_enabled = rcg_clk_is_enabled,
-	.round_rate = rcg_clk_round_rate,
-	.reset = rcg_clk_reset,
-	.get_parent = rcg_clk_get_parent,
-	.set_flags = rcg_clk_set_flags,
-};
-
-static struct clk_ops clk_ops_branch = {
-	.enable = branch_clk_enable,
-	.disable = branch_clk_disable,
-	.auto_off = branch_clk_disable,
-	.is_enabled = branch_clk_is_enabled,
-	.reset = branch_clk_reset,
-	.get_parent = branch_clk_get_parent,
-	.set_flags = branch_clk_set_flags,
-};
-
-static struct clk_ops clk_ops_reset = {
-	.reset = branch_clk_reset,
-};
-
 /*
  * Clock Descriptions
  */
@@ -965,7 +937,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_8x60, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP1(LOW, 27000000), \
 			CLK_INIT(i##_clk.c), \
 		}, \
@@ -1010,7 +982,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_8x60, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 64000000), \
 			CLK_INIT(i##_clk.c), \
 		}, \
@@ -1074,7 +1046,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_8x60, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP2(LOW, 24000000, NOMINAL, 52000000), \
 			CLK_INIT(i##_clk.c), \
 		}, \
@@ -1142,7 +1114,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "pdm_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 27000000),
 		CLK_INIT(pdm_clk.c),
 	},
@@ -1185,7 +1157,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "prng_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 65000000),
 		CLK_INIT(prng_clk.c),
 	},
@@ -1211,7 +1183,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_8x60, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000), \
 			CLK_INIT(i##_clk.c), \
 		}, \
@@ -1271,7 +1243,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "tsif_ref_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		CLK_INIT(tsif_ref_clk.c),
 	},
 };
@@ -1302,7 +1274,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "tssc_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 27000000),
 		CLK_INIT(tssc_clk.c),
 	},
@@ -1340,7 +1312,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "usb_hs1_xcvr_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 60000000),
 		CLK_INIT(usb_hs1_xcvr_clk.c),
 	},
@@ -1374,7 +1346,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_8x60, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP1(NOMINAL, 60000000), \
 			CLK_INIT(i##_clk.c), \
 		}, \
@@ -2001,7 +1973,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "cam_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 64000000, NOMINAL, 128000000),
 		CLK_INIT(cam_clk.c),
 	},
@@ -2033,7 +2005,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "csi_src_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 192000000, NOMINAL, 384000000),
 		CLK_INIT(csi_src_clk.c),
 	},
@@ -2107,7 +2079,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "dsi_byte_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		CLK_INIT(dsi_byte_clk.c),
 	},
 };
@@ -2188,7 +2160,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "gfx2d0_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP3(LOW,  100000000, NOMINAL, 200000000,
 				  HIGH, 228571000),
 		CLK_INIT(gfx2d0_clk.c),
@@ -2232,7 +2204,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "gfx2d1_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP3(LOW,  100000000, NOMINAL, 200000000,
 				  HIGH, 228571000),
 		CLK_INIT(gfx2d1_clk.c),
@@ -2303,7 +2275,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "gfx3d_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP3(LOW,   96000000, NOMINAL, 200000000,
 				  HIGH, 320000000),
 		CLK_INIT(gfx3d_clk.c),
@@ -2355,7 +2327,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "ijpeg_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 110000000, NOMINAL, 228571000),
 		CLK_INIT(ijpeg_clk.c),
 		.depends = &ijpeg_axi_clk.c,
@@ -2397,7 +2369,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "jpegd_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 96000000, NOMINAL, 200000000),
 		CLK_INIT(jpegd_clk.c),
 		.depends = &jpegd_axi_clk.c,
@@ -2468,7 +2440,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "mdp_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP3(LOW,   85330000, NOMINAL, 200000000,
 				  HIGH, 228571000),
 		CLK_INIT(mdp_clk.c),
@@ -2503,7 +2475,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "mdp_vsync_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 27000000),
 		CLK_INIT(mdp_vsync_clk.c),
 	},
@@ -2555,7 +2527,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "pixel_mdp_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 85333000, NOMINAL, 170000000),
 		CLK_INIT(pixel_mdp_clk.c),
 	},
@@ -2630,7 +2602,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "rot_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 80000000, NOMINAL, 160000000),
 		CLK_INIT(rot_clk.c),
 		.depends = &rot_axi_clk.c,
@@ -2682,7 +2654,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "tv_src_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 27030000, NOMINAL, 149000000),
 		CLK_INIT(tv_src_clk.c),
 	},
@@ -2813,7 +2785,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "vcodec_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP3(LOW,  100000000, NOMINAL, 200000000,
 				  HIGH, 228571000),
 		CLK_INIT(vcodec_clk.c),
@@ -2860,7 +2832,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "vpe_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP3(LOW,   76800000, NOMINAL, 160000000,
 				  HIGH, 200000000),
 		CLK_INIT(vpe_clk.c),
@@ -2919,7 +2891,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "vfe_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP3(LOW,  110000000, NOMINAL, 228570000,
 				  HIGH, 266667000),
 		CLK_INIT(vfe_clk.c),
@@ -3007,7 +2979,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_8x60, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP1(LOW, 24576000), \
 			CLK_INIT(i##_clk.c), \
 		}, \
@@ -3064,7 +3036,7 @@
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
 	}
 static struct clk_freq_tbl clk_tbl_pcm[] = {
-	F_PCM(       0, gnd,  1, 0,   0),
+	{ .ns_val = BIT(10) /* external input */ },
 	F_PCM(  512000, pll4, 4, 1, 264),
 	F_PCM(  768000, pll4, 4, 1, 176),
 	F_PCM( 1024000, pll4, 4, 1, 132),
@@ -3092,14 +3064,14 @@
 	.ns_reg = LCC_PCM_NS_REG,
 	.md_reg = LCC_PCM_MD_REG,
 	.root_en_mask = BIT(9),
-	.ns_mask = (BM(31, 16) | BM(6, 0)),
+	.ns_mask = BM(31, 16) | BIT(10) | BM(6, 0),
 	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_pcm,
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "pcm_clk",
-		.ops = &clk_ops_rcg_8x60,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 24580000),
 		CLK_INIT(pcm_clk.c),
 	},
@@ -3613,7 +3585,7 @@
 	CLK_LOOKUP("core_clk",		gfx2d1_clk.c,	"footswitch-8x60.1"),
 	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	"footswitch-8x60.2"),
-	CLK_LOOKUP("ijpeg_clk",		ijpeg_clk.c,		NULL),
+	CLK_LOOKUP("ijpeg_clk",		ijpeg_clk.c,		"msm_gemini.0"),
 	CLK_LOOKUP("core_clk",		ijpeg_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("core_clk",		jpegd_clk.c,		NULL),
 	CLK_LOOKUP("core_clk",		mdp_clk.c,		"mdp.0"),
@@ -3666,7 +3638,7 @@
 	CLK_LOOKUP("iface_clk",		gfx3d_p_clk.c,	"footswitch-8x60.2"),
 	CLK_LOOKUP("master_iface_clk",	hdmi_m_p_clk.c,	"hdmi_msm.1"),
 	CLK_LOOKUP("slave_iface_clk",	hdmi_s_p_clk.c,	"hdmi_msm.1"),
-	CLK_LOOKUP("ijpeg_pclk",	ijpeg_p_clk.c,		NULL),
+	CLK_LOOKUP("ijpeg_pclk",	ijpeg_p_clk.c,		"msm_gemini.0"),
 	CLK_LOOKUP("iface_clk",		ijpeg_p_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("iface_clk",		jpegd_p_clk.c,		NULL),
 	CLK_LOOKUP("mem_iface_clk",	imem_p_clk.c,	"kgsl-3d0.0"),
@@ -3843,10 +3815,10 @@
 
 	/* The halt status bits for PDM and TSSC may be incorrect at boot.
 	 * Toggle these clocks on and off to refresh them. */
-	rcg_clk_enable(&pdm_clk.c);
-	rcg_clk_disable(&pdm_clk.c);
-	rcg_clk_enable(&tssc_clk.c);
-	rcg_clk_disable(&tssc_clk.c);
+	clk_prepare_enable(&pdm_clk.c);
+	clk_disable_unprepare(&pdm_clk.c);
+	clk_prepare_enable(&tssc_clk.c);
+	clk_disable_unprepare(&tssc_clk.c);
 }
 
 static int __init msm8660_clock_late_init(void)
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index b145278..12d37ae 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -153,6 +153,7 @@
 /* MUX source input identifiers. */
 #define cxo_to_bb_mux		0
 #define pll8_to_bb_mux		3
+#define pll8_acpu_to_bb_mux	3
 #define pll14_to_bb_mux		4
 #define gnd_to_bb_mux		6
 #define cxo_to_xo_mux		0
@@ -365,35 +366,6 @@
 	},
 };
 
-static struct clk_ops clk_ops_rcg_9615 = {
-	.enable = rcg_clk_enable,
-	.disable = rcg_clk_disable,
-	.auto_off = rcg_clk_disable,
-	.enable_hwcg = rcg_clk_enable_hwcg,
-	.disable_hwcg = rcg_clk_disable_hwcg,
-	.in_hwcg_mode = rcg_clk_in_hwcg_mode,
-	.handoff = rcg_clk_handoff,
-	.set_rate = rcg_clk_set_rate,
-	.list_rate = rcg_clk_list_rate,
-	.is_enabled = rcg_clk_is_enabled,
-	.round_rate = rcg_clk_round_rate,
-	.reset = rcg_clk_reset,
-	.get_parent = rcg_clk_get_parent,
-};
-
-static struct clk_ops clk_ops_branch = {
-	.enable = branch_clk_enable,
-	.disable = branch_clk_disable,
-	.auto_off = branch_clk_disable,
-	.enable_hwcg = branch_clk_enable_hwcg,
-	.disable_hwcg = branch_clk_disable_hwcg,
-	.in_hwcg_mode = branch_clk_in_hwcg_mode,
-	.handoff = branch_clk_handoff,
-	.is_enabled = branch_clk_is_enabled,
-	.reset = branch_clk_reset,
-	.get_parent = branch_clk_get_parent,
-};
-
 /*
  * Peripheral Clocks
  */
@@ -415,7 +387,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_9615, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP1(LOW, 27000000), \
 			CLK_INIT(i##_clk.c), \
 		}, \
@@ -458,7 +430,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_9615, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 64000000), \
 			CLK_INIT(i##_clk.c), \
 		}, \
@@ -514,7 +486,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_9615, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP2(LOW, 24000000, NOMINAL, 52000000), \
 			CLK_INIT(i##_clk.c), \
 		}, \
@@ -574,7 +546,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "pdm_clk",
-		.ops = &clk_ops_rcg_9615,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 19200000),
 		CLK_INIT(pdm_clk.c),
 	},
@@ -619,7 +591,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "prng_clk",
-		.ops = &clk_ops_rcg_9615,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 65000000),
 		CLK_INIT(prng_clk.c),
 	},
@@ -645,7 +617,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #name, \
-			.ops = &clk_ops_rcg_9615, \
+			.ops = &clk_ops_rcg, \
 			VDD_DIG_FMAX_MAP2(LOW, 26000000, NOMINAL, 52000000), \
 			CLK_INIT(name.c), \
 		}, \
@@ -689,8 +661,8 @@
 };
 
 static struct clk_freq_tbl clk_tbl_usb_hsic_sys[] = {
-	F_USB(       0, gnd,  1, 0, 0),
-	F_USB(64000000, pll8, 1, 1, 6),
+	F_USB(       0,       gnd, 1, 0, 0),
+	F_USB(64000000, pll8_acpu, 1, 1, 6),
 	F_END
 };
 
@@ -713,7 +685,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "usb_hs1_xcvr_clk",
-		.ops = &clk_ops_rcg_9615,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 60000000),
 		CLK_INIT(usb_hs1_xcvr_clk.c),
 	},
@@ -738,7 +710,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "usb_hs1_sys_clk",
-		.ops = &clk_ops_rcg_9615,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(NOMINAL, 60000000),
 		CLK_INIT(usb_hs1_sys_clk.c),
 	},
@@ -763,7 +735,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "usb_hsic_xcvr_clk",
-		.ops = &clk_ops_rcg_9615,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 60000000),
 		CLK_INIT(usb_hsic_xcvr_clk.c),
 	},
@@ -788,7 +760,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "usb_hsic_sys_clk",
-		.ops = &clk_ops_rcg_9615,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 64000000),
 		CLK_INIT(usb_hsic_sys_clk.c),
 	},
@@ -817,7 +789,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "usb_hsic_clk",
-		.ops = &clk_ops_rcg_9615,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 480000000),
 		CLK_INIT(usb_hsic_clk.c),
 	},
@@ -1154,7 +1126,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_9615, \
+			.ops = &clk_ops_rcg, \
 			CLK_INIT(i##_clk.c), \
 		}, \
 	}
@@ -1179,7 +1151,7 @@
 		.current_freq = &rcg_dummy_freq, \
 		.c = { \
 			.dbg_name = #i "_clk", \
-			.ops = &clk_ops_rcg_9615, \
+			.ops = &clk_ops_rcg, \
 			CLK_INIT(i##_clk.c), \
 		}, \
 	}
@@ -1254,7 +1226,7 @@
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
 	}
 static struct clk_freq_tbl clk_tbl_pcm[] = {
-	F_PCM(       0, gnd,  1, 0,   0),
+	{ .ns_val = BIT(10) /* external input */ },
 	F_PCM(  512000, pll4, 4, 1, 192),
 	F_PCM(  768000, pll4, 4, 1, 128),
 	F_PCM( 1024000, pll4, 4, 1,  96),
@@ -1282,14 +1254,14 @@
 	.ns_reg = LCC_PCM_NS_REG,
 	.md_reg = LCC_PCM_MD_REG,
 	.root_en_mask = BIT(9),
-	.ns_mask = (BM(31, 16) | BM(6, 0)),
+	.ns_mask = BM(31, 16) | BIT(10) | BM(6, 0),
 	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_pcm,
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "pcm_clk",
-		.ops = &clk_ops_rcg_9615,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 24576000),
 		CLK_INIT(pcm_clk.c),
 	},
@@ -1315,7 +1287,7 @@
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "audio_slimbus_clk",
-		.ops = &clk_ops_rcg_9615,
+		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP1(LOW, 24576000),
 		CLK_INIT(audio_slimbus_clk.c),
 	},
@@ -1857,8 +1829,8 @@
 	 * The halt status bits for PDM may be incorrect at boot.
 	 * Toggle these clocks on and off to refresh them.
 	*/
-	rcg_clk_enable(&pdm_clk.c);
-	rcg_clk_disable(&pdm_clk.c);
+	clk_prepare_enable(&pdm_clk.c);
+	clk_disable_unprepare(&pdm_clk.c);
 }
 
 static int __init msm9615_clock_late_init(void)
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index d414e44..e1b3381 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -268,7 +268,7 @@
 	return invert ? !status_bit : status_bit;
 }
 
-int branch_in_hwcg_mode(const struct branch *b)
+static int branch_in_hwcg_mode(const struct branch *b)
 {
 	if (!b->hwcg_mask)
 		return 0;
@@ -420,7 +420,7 @@
 }
 
 /* Enable a rate-settable clock. */
-int rcg_clk_enable(struct clk *c)
+static int rcg_clk_enable(struct clk *c)
 {
 	unsigned long flags;
 	struct rcg_clk *clk = to_rcg_clk(c);
@@ -434,7 +434,7 @@
 }
 
 /* Disable a rate-settable clock. */
-void rcg_clk_disable(struct clk *c)
+static void rcg_clk_disable(struct clk *c)
 {
 	unsigned long flags;
 	struct rcg_clk *clk = to_rcg_clk(c);
@@ -450,7 +450,7 @@
  */
 
 /* Set a clock to an exact rate. */
-int rcg_clk_set_rate(struct clk *c, unsigned long rate)
+static int rcg_clk_set_rate(struct clk *c, unsigned long rate)
 {
 	struct rcg_clk *clk = to_rcg_clk(c);
 	struct clk_freq_tbl *nf, *cf;
@@ -527,13 +527,13 @@
 }
 
 /* Check if a clock is currently enabled. */
-int rcg_clk_is_enabled(struct clk *clk)
+static int rcg_clk_is_enabled(struct clk *clk)
 {
 	return to_rcg_clk(clk)->enabled;
 }
 
 /* Return a supported rate that's at least the specified rate. */
-long rcg_clk_round_rate(struct clk *c, unsigned long rate)
+static long rcg_clk_round_rate(struct clk *c, unsigned long rate)
 {
 	struct rcg_clk *clk = to_rcg_clk(c);
 	struct clk_freq_tbl *f;
@@ -546,7 +546,7 @@
 }
 
 /* Return the nth supported frequency for a given clock. */
-int rcg_clk_list_rate(struct clk *c, unsigned n)
+static int rcg_clk_list_rate(struct clk *c, unsigned n)
 {
 	struct rcg_clk *clk = to_rcg_clk(c);
 
@@ -556,7 +556,7 @@
 	return (clk->freq_tbl + n)->freq_hz;
 }
 
-struct clk *rcg_clk_get_parent(struct clk *clk)
+static struct clk *rcg_clk_get_parent(struct clk *clk)
 {
 	return to_rcg_clk(clk)->current_freq->src_clk;
 }
@@ -575,13 +575,13 @@
 	return HANDOFF_DISABLED_CLK;
 }
 
-enum handoff branch_clk_handoff(struct clk *c)
+static enum handoff branch_clk_handoff(struct clk *c)
 {
 	struct branch_clk *clk = to_branch_clk(c);
 	return branch_handoff(&clk->b, &clk->c);
 }
 
-enum handoff rcg_clk_handoff(struct clk *c)
+static enum handoff rcg_clk_handoff(struct clk *c)
 {
 	struct rcg_clk *clk = to_rcg_clk(c);
 	uint32_t ctl_val, ns_val, md_val, ns_mask;
@@ -641,7 +641,7 @@
 struct clk_ops clk_ops_measure = {
 };
 
-int branch_clk_enable(struct clk *clk)
+static int branch_clk_enable(struct clk *clk)
 {
 	unsigned long flags;
 	struct branch_clk *branch = to_branch_clk(clk);
@@ -654,7 +654,7 @@
 	return 0;
 }
 
-void branch_clk_disable(struct clk *clk)
+static void branch_clk_disable(struct clk *clk)
 {
 	unsigned long flags;
 	struct branch_clk *branch = to_branch_clk(clk);
@@ -665,13 +665,13 @@
 	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
 }
 
-struct clk *branch_clk_get_parent(struct clk *clk)
+static struct clk *branch_clk_get_parent(struct clk *clk)
 {
 	struct branch_clk *branch = to_branch_clk(clk);
 	return branch->parent;
 }
 
-int branch_clk_is_enabled(struct clk *clk)
+static int branch_clk_is_enabled(struct clk *clk)
 {
 	struct branch_clk *branch = to_branch_clk(clk);
 	return branch->enabled;
@@ -701,13 +701,13 @@
 	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
 }
 
-void branch_clk_enable_hwcg(struct clk *clk)
+static void branch_clk_enable_hwcg(struct clk *clk)
 {
 	struct branch_clk *branch = to_branch_clk(clk);
 	branch_enable_hwcg(&branch->b);
 }
 
-void branch_clk_disable_hwcg(struct clk *clk)
+static void branch_clk_disable_hwcg(struct clk *clk)
 {
 	struct branch_clk *branch = to_branch_clk(clk);
 	branch_disable_hwcg(&branch->b);
@@ -740,36 +740,36 @@
 	return ret;
 }
 
-int branch_clk_set_flags(struct clk *clk, unsigned flags)
+static int branch_clk_set_flags(struct clk *clk, unsigned flags)
 {
 	return branch_set_flags(&to_branch_clk(clk)->b, flags);
 }
 
-int branch_clk_in_hwcg_mode(struct clk *c)
+static int branch_clk_in_hwcg_mode(struct clk *c)
 {
 	struct branch_clk *clk = to_branch_clk(c);
 	return branch_in_hwcg_mode(&clk->b);
 }
 
-void rcg_clk_enable_hwcg(struct clk *clk)
+static void rcg_clk_enable_hwcg(struct clk *clk)
 {
 	struct rcg_clk *rcg = to_rcg_clk(clk);
 	branch_enable_hwcg(&rcg->b);
 }
 
-void rcg_clk_disable_hwcg(struct clk *clk)
+static void rcg_clk_disable_hwcg(struct clk *clk)
 {
 	struct rcg_clk *rcg = to_rcg_clk(clk);
 	branch_disable_hwcg(&rcg->b);
 }
 
-int rcg_clk_in_hwcg_mode(struct clk *c)
+static int rcg_clk_in_hwcg_mode(struct clk *c)
 {
 	struct rcg_clk *clk = to_rcg_clk(c);
 	return branch_in_hwcg_mode(&clk->b);
 }
 
-int rcg_clk_set_flags(struct clk *clk, unsigned flags)
+static int rcg_clk_set_flags(struct clk *clk, unsigned flags)
 {
 	return branch_set_flags(&to_rcg_clk(clk)->b, flags);
 }
@@ -811,16 +811,51 @@
 	return ret;
 }
 
-int branch_clk_reset(struct clk *clk, enum clk_reset_action action)
+static int branch_clk_reset(struct clk *clk, enum clk_reset_action action)
 {
 	return branch_reset(&to_branch_clk(clk)->b, action);
 }
 
-int rcg_clk_reset(struct clk *clk, enum clk_reset_action action)
+struct clk_ops clk_ops_branch = {
+	.enable = branch_clk_enable,
+	.disable = branch_clk_disable,
+	.enable_hwcg = branch_clk_enable_hwcg,
+	.disable_hwcg = branch_clk_disable_hwcg,
+	.in_hwcg_mode = branch_clk_in_hwcg_mode,
+	.auto_off = branch_clk_disable,
+	.is_enabled = branch_clk_is_enabled,
+	.reset = branch_clk_reset,
+	.get_parent = branch_clk_get_parent,
+	.handoff = branch_clk_handoff,
+	.set_flags = branch_clk_set_flags,
+};
+
+struct clk_ops clk_ops_reset = {
+	.reset = branch_clk_reset,
+};
+
+static int rcg_clk_reset(struct clk *clk, enum clk_reset_action action)
 {
 	return branch_reset(&to_rcg_clk(clk)->b, action);
 }
 
+struct clk_ops clk_ops_rcg = {
+	.enable = rcg_clk_enable,
+	.disable = rcg_clk_disable,
+	.enable_hwcg = rcg_clk_enable_hwcg,
+	.disable_hwcg = rcg_clk_disable_hwcg,
+	.in_hwcg_mode = rcg_clk_in_hwcg_mode,
+	.auto_off = rcg_clk_disable,
+	.handoff = rcg_clk_handoff,
+	.set_rate = rcg_clk_set_rate,
+	.list_rate = rcg_clk_list_rate,
+	.is_enabled = rcg_clk_is_enabled,
+	.round_rate = rcg_clk_round_rate,
+	.reset = rcg_clk_reset,
+	.get_parent = rcg_clk_get_parent,
+	.set_flags = rcg_clk_set_flags,
+};
+
 static int cdiv_clk_enable(struct clk *c)
 {
 	unsigned long flags;
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 0419ede..a419d69 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -73,16 +73,6 @@
 		* !!(n))
 
 /*
- * Halt/Status Checking Mode Macros
- */
-#define HALT		0	/* Bit pol: 1 = halted */
-#define NOCHECK		1	/* No bit to check, do nothing */
-#define HALT_VOTED	2	/* Bit pol: 1 = halted; delay on disable */
-#define ENABLE		3	/* Bit pol: 1 = running */
-#define ENABLE_VOTED	4	/* Bit pol: 1 = running; delay on disable */
-#define DELAY		5	/* No bit to check, just delay */
-
-/*
  * Clock Definition Macros
  */
 #define DEFINE_CLK_MEASURE(name) \
@@ -162,12 +152,13 @@
 	const u32 retain_mask;
 };
 
+extern struct clk_ops clk_ops_branch;
+extern struct clk_ops clk_ops_reset;
+
 int branch_reset(struct branch *b, enum clk_reset_action action);
 void __branch_clk_enable_reg(const struct branch *clk, const char *name);
 u32 __branch_clk_disable_reg(const struct branch *clk, const char *name);
-enum handoff branch_clk_handoff(struct clk *c);
 enum handoff branch_handoff(struct branch *clk, struct clk *c);
-int branch_clk_set_flags(struct clk *clk, unsigned flags);
 
 /*
  * Generic clock-definition struct and macros
@@ -197,21 +188,9 @@
 	return container_of(clk, struct rcg_clk, c);
 }
 
-extern struct clk_freq_tbl rcg_dummy_freq;
+extern struct clk_ops clk_ops_rcg;
 
-int rcg_clk_enable(struct clk *clk);
-void rcg_clk_disable(struct clk *clk);
-int rcg_clk_set_rate(struct clk *clk, unsigned long rate);
-int rcg_clk_list_rate(struct clk *clk, unsigned n);
-int rcg_clk_is_enabled(struct clk *clk);
-long rcg_clk_round_rate(struct clk *clk, unsigned long rate);
-struct clk *rcg_clk_get_parent(struct clk *c);
-enum handoff rcg_clk_handoff(struct clk *c);
-int rcg_clk_reset(struct clk *clk, enum clk_reset_action action);
-void rcg_clk_enable_hwcg(struct clk *clk);
-void rcg_clk_disable_hwcg(struct clk *clk);
-int rcg_clk_in_hwcg_mode(struct clk *c);
-int rcg_clk_set_flags(struct clk *clk, unsigned flags);
+extern struct clk_freq_tbl rcg_dummy_freq;
 
 /**
  * struct cdiv_clk - integer divider clock with external source selection
@@ -271,15 +250,6 @@
 	return container_of(clk, struct branch_clk, c);
 }
 
-int branch_clk_enable(struct clk *clk);
-void branch_clk_disable(struct clk *clk);
-struct clk *branch_clk_get_parent(struct clk *clk);
-int branch_clk_is_enabled(struct clk *clk);
-int branch_clk_reset(struct clk *c, enum clk_reset_action action);
-void branch_clk_enable_hwcg(struct clk *clk);
-void branch_clk_disable_hwcg(struct clk *clk);
-int branch_clk_in_hwcg_mode(struct clk *c);
-
 /**
  * struct measure_clk - for rate measurement debug use
  * @sample_ticks: sample period in reference clock ticks
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
new file mode 100644
index 0000000..55282b6
--- /dev/null
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -0,0 +1,591 @@
+/* Copyright (c) 2012, 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.
+ *
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <mach/clk.h>
+
+#include "clock.h"
+#include "clock-local2.h"
+
+/*
+ * When enabling/disabling a clock, check the halt bit up to this number
+ * number of times (with a 1 us delay in between) before continuing.
+ */
+#define HALT_CHECK_MAX_LOOPS	200
+/* For clock without halt checking, wait this long after enables/disables. */
+#define HALT_CHECK_DELAY_US	10
+
+/*
+ * When updating an RCG configuration, check the update bit up to this number
+ * number of times (with a 1 us delay in between) before continuing.
+ */
+#define UPDATE_CHECK_MAX_LOOPS	200
+
+DEFINE_SPINLOCK(local_clock_reg_lock);
+struct clk_freq_tbl rcg_dummy_freq = F_END;
+
+#define CMD_RCGR_REG(x) (*(x)->base + (x)->cmd_rcgr_reg)
+#define CFG_RCGR_REG(x) (*(x)->base + (x)->cmd_rcgr_reg + 0x4)
+#define M_REG(x)	(*(x)->base + (x)->cmd_rcgr_reg + 0x8)
+#define N_REG(x)	(*(x)->base + (x)->cmd_rcgr_reg + 0xC)
+#define D_REG(x)	(*(x)->base + (x)->cmd_rcgr_reg + 0x10)
+#define CBCR_REG(x)	(*(x)->base + (x)->cbcr_reg)
+#define BCR_REG(x)	(*(x)->base + (x)->bcr_reg)
+#define VOTE_REG(x)	(*(x)->base + (x)->vote_reg)
+
+/*
+ * Important clock bit positions and masks
+ */
+#define CMD_RCGR_ROOT_ENABLE_BIT	BIT(1)
+#define CBCR_BRANCH_ENABLE_BIT		BIT(0)
+#define CBCR_BRANCH_OFF_BIT		BIT(31)
+#define CMD_RCGR_CONFIG_UPDATE_BIT	BIT(0)
+#define CMD_RCGR_ROOT_STATUS_BIT	BIT(31)
+#define BCR_BLK_ARES_BIT		BIT(0)
+#define CBCR_HW_CTL_BIT			BIT(1)
+#define CFG_RCGR_DIV_MASK		BM(4, 0)
+#define CFG_RCGR_SRC_SEL_MASK		BM(10, 8)
+#define MND_MODE_MASK			BM(13, 12)
+#define MND_DUAL_EDGE_MODE_BVAL		BVAL(13, 12, 0x2)
+#define CMD_RCGR_CONFIG_DIRTY_MASK	BM(7, 4)
+#define CBCR_BRANCH_CDIV_MASK		BM(24, 16)
+#define CBCR_BRANCH_CDIV_MASKED(val)	BVAL(24, 16, (val));
+
+enum branch_state {
+	BRANCH_ON,
+	BRANCH_OFF,
+};
+
+/*
+ * RCG functions
+ */
+
+/*
+ * Update an RCG with a new configuration. This may include a new M, N, or D
+ * value, source selection or pre-divider value.
+ *
+ */
+static void rcg_update_config(struct rcg_clk *rcg)
+{
+	u32 cmd_rcgr_regval, count;
+
+	cmd_rcgr_regval = readl_relaxed(CMD_RCGR_REG(rcg));
+	cmd_rcgr_regval |= CMD_RCGR_CONFIG_UPDATE_BIT;
+	writel_relaxed(cmd_rcgr_regval, CMD_RCGR_REG(rcg));
+
+	/* Wait for update to take effect */
+	for (count = UPDATE_CHECK_MAX_LOOPS; count > 0; count--) {
+		if (!(readl_relaxed(CMD_RCGR_REG(rcg)) &
+				CMD_RCGR_CONFIG_UPDATE_BIT))
+			return;
+		udelay(1);
+	}
+
+	WARN(count == 0, "%s: rcg didn't update its configuration.",
+		rcg->c.dbg_name);
+}
+
+/* RCG set rate function for clocks with Half Integer Dividers. */
+void set_rate_hid(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
+{
+	u32 cfg_regval;
+
+	cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg));
+	cfg_regval &= ~(CFG_RCGR_DIV_MASK | CFG_RCGR_SRC_SEL_MASK);
+	cfg_regval |= nf->div_src_val;
+	writel_relaxed(cfg_regval, CFG_RCGR_REG(rcg));
+
+	rcg_update_config(rcg);
+}
+
+/* RCG set rate function for clocks with MND & Half Integer Dividers. */
+void set_rate_mnd(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
+{
+	u32 cfg_regval;
+
+	writel_relaxed(nf->m_val, M_REG(rcg));
+	writel_relaxed(nf->n_val, N_REG(rcg));
+	writel_relaxed(nf->d_val, D_REG(rcg));
+
+	cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg));
+	cfg_regval &= ~(CFG_RCGR_DIV_MASK | CFG_RCGR_SRC_SEL_MASK);
+	cfg_regval |= nf->div_src_val;
+
+	/* Activate or disable the M/N:D divider as necessary */
+	cfg_regval &= ~MND_MODE_MASK;
+	if (nf->n_val != 0)
+		cfg_regval |= MND_DUAL_EDGE_MODE_BVAL;
+	writel_relaxed(cfg_regval, CFG_RCGR_REG(rcg));
+
+	rcg_update_config(rcg);
+}
+
+static int rcg_clk_enable(struct clk *c)
+{
+	struct rcg_clk *rcg = to_rcg_clk(c);
+
+	WARN(rcg->current_freq == &rcg_dummy_freq,
+		"Attempting to enable %s before setting its rate. "
+		"Set the rate first!\n", rcg->c.dbg_name);
+
+	return 0;
+}
+
+static int rcg_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	struct clk_freq_tbl *cf, *nf;
+	struct rcg_clk *rcg = to_rcg_clk(c);
+	int rc = 0;
+	unsigned long flags;
+
+	for (nf = rcg->freq_tbl; nf->freq_hz != FREQ_END
+			&& nf->freq_hz != rate; nf++)
+		;
+
+	if (nf->freq_hz == FREQ_END)
+		return -EINVAL;
+
+	/* Check if frequency is actually changed. */
+	cf = rcg->current_freq;
+	if (nf == cf)
+		return 0;
+
+	if (rcg->c.count) {
+		/* TODO: Modify to use the prepare API */
+		/* Enable source clock dependency for the new freq. */
+		rc = clk_enable(nf->src_clk);
+		if (rc)
+			goto out;
+	}
+
+	BUG_ON(!rcg->set_rate);
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+
+	/* Perform clock-specific frequency switch operations. */
+	rcg->set_rate(rcg, nf);
+
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+	/* Release source requirements of the old freq. */
+	if (rcg->c.count)
+		clk_disable(cf->src_clk);
+
+	rcg->current_freq = nf;
+out:
+	return rc;
+}
+
+/* Return a supported rate that's at least the specified rate. */
+static long rcg_clk_round_rate(struct clk *c, unsigned long rate)
+{
+	struct rcg_clk *rcg = to_rcg_clk(c);
+	struct clk_freq_tbl *f;
+
+	for (f = rcg->freq_tbl; f->freq_hz != FREQ_END; f++)
+		if (f->freq_hz >= rate)
+			return f->freq_hz;
+
+	return -EPERM;
+}
+
+/* Return the nth supported frequency for a given clock. */
+static int rcg_clk_list_rate(struct clk *c, unsigned n)
+{
+	struct rcg_clk *rcg = to_rcg_clk(c);
+
+	if (!rcg->freq_tbl || rcg->freq_tbl->freq_hz == FREQ_END)
+		return -ENXIO;
+
+	return (rcg->freq_tbl + n)->freq_hz;
+}
+
+static struct clk *rcg_clk_get_parent(struct clk *c)
+{
+	return to_rcg_clk(c)->current_freq->src_clk;
+}
+
+static enum handoff _rcg_clk_handoff(struct rcg_clk *rcg, int has_mnd)
+{
+	u32 n_regval = 0, m_regval = 0, d_regval = 0;
+	u32 cfg_regval;
+	struct clk_freq_tbl *freq;
+	u32 cmd_rcgr_regval;
+
+	/* Is the root enabled? */
+	cmd_rcgr_regval = readl_relaxed(CMD_RCGR_REG(rcg));
+	if ((cmd_rcgr_regval & CMD_RCGR_ROOT_STATUS_BIT))
+		return HANDOFF_DISABLED_CLK;
+
+	/* Is there a pending configuration? */
+	if (cmd_rcgr_regval & CMD_RCGR_CONFIG_DIRTY_MASK)
+		return HANDOFF_UNKNOWN_RATE;
+
+	/* Get values of m, n, d, div and src_sel registers. */
+	if (has_mnd) {
+		m_regval = readl_relaxed(M_REG(rcg));
+		n_regval = readl_relaxed(N_REG(rcg));
+		d_regval = readl_relaxed(D_REG(rcg));
+
+		/*
+		 * The n and d values stored in the frequency tables are sign
+		 * extended to 32 bits. The n and d values in the registers are
+		 * sign extended to 8 or 16 bits. Sign extend the values read
+		 * from the registers so that they can be compared to the
+		 * values in the frequency tables.
+		 */
+		n_regval |= (n_regval >> 8) ? BM(31, 16) : BM(31, 8);
+		d_regval |= (d_regval >> 8) ? BM(31, 16) : BM(31, 8);
+	}
+
+	cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg));
+	cfg_regval &= CFG_RCGR_SRC_SEL_MASK | CFG_RCGR_DIV_MASK
+				| MND_MODE_MASK;
+
+	/* If mnd counter is present, check if it's in use. */
+	has_mnd = (has_mnd) &&
+		((cfg_regval & MND_MODE_MASK) == MND_DUAL_EDGE_MODE_BVAL);
+
+	/*
+	 * Clear out the mn counter mode bits since we now want to compare only
+	 * the source mux selection and pre-divider values in the registers.
+	 */
+	cfg_regval &= ~MND_MODE_MASK;
+
+	/* Figure out what rate the rcg is running at */
+	for (freq = rcg->freq_tbl; freq->freq_hz != FREQ_END; freq++) {
+		if (freq->div_src_val != cfg_regval)
+			continue;
+		if (has_mnd) {
+			if (freq->m_val != m_regval)
+				continue;
+			if (freq->n_val != n_regval)
+				continue;
+			if (freq->d_val != d_regval)
+				continue;
+		}
+		pr_info("%s rate=%lu\n", rcg->c.dbg_name, freq->freq_hz);
+		break;
+	}
+
+	/* No known frequency found */
+	if (freq->freq_hz == FREQ_END)
+		return HANDOFF_UNKNOWN_RATE;
+
+	rcg->current_freq = freq;
+	rcg->c.rate = freq->freq_hz;
+
+	return HANDOFF_ENABLED_CLK;
+}
+
+static enum handoff rcg_mnd_clk_handoff(struct clk *c)
+{
+	return _rcg_clk_handoff(to_rcg_clk(c), 1);
+}
+
+static enum handoff rcg_clk_handoff(struct clk *c)
+{
+	return _rcg_clk_handoff(to_rcg_clk(c), 0);
+}
+
+/*
+ * Branch clock functions
+ */
+static void branch_clk_halt_check(u32 halt_check, const char *clk_name,
+				  void __iomem *cbcr_reg,
+				  enum branch_state br_status)
+{
+	char *status_str = (br_status == BRANCH_ON) ? "on" : "off";
+
+	/*
+	 * Use a memory barrier since some halt status registers are
+	 * not within the same 1K segment as the branch/root enable
+	 * registers.  It's also needed in the udelay() case to ensure
+	 * the delay starts after the branch disable.
+	 */
+	mb();
+
+	if (halt_check == DELAY || halt_check == HALT_VOTED) {
+		udelay(HALT_CHECK_DELAY_US);
+	} else if (halt_check == HALT) {
+		int count;
+		for (count = HALT_CHECK_MAX_LOOPS; count > 0; count--) {
+			if (br_status == BRANCH_ON
+				&& !(readl_relaxed(cbcr_reg)
+						& CBCR_BRANCH_OFF_BIT))
+				return;
+			if (br_status == BRANCH_OFF
+				&& (readl_relaxed(cbcr_reg)
+						& CBCR_BRANCH_OFF_BIT))
+				return;
+			udelay(1);
+		}
+		WARN(count == 0, "%s status stuck %s", clk_name, status_str);
+	}
+}
+
+static int branch_clk_enable(struct clk *c)
+{
+	unsigned long flags;
+	u32 cbcr_val;
+	struct branch_clk *branch = to_branch_clk(c);
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	cbcr_val = readl_relaxed(CBCR_REG(branch));
+	cbcr_val |= CBCR_BRANCH_ENABLE_BIT;
+	writel_relaxed(cbcr_val, CBCR_REG(branch));
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+	/* Wait for clock to enable before continuing. */
+	branch_clk_halt_check(branch->halt_check, branch->c.dbg_name,
+				CBCR_REG(branch), BRANCH_ON);
+
+	return 0;
+}
+
+static void branch_clk_disable(struct clk *c)
+{
+	unsigned long flags;
+	struct branch_clk *branch = to_branch_clk(c);
+	u32 reg_val;
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	reg_val = readl_relaxed(CBCR_REG(branch));
+	reg_val &= ~CBCR_BRANCH_ENABLE_BIT;
+	writel_relaxed(reg_val, CBCR_REG(branch));
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+	/* Wait for clock to disable before continuing. */
+	branch_clk_halt_check(branch->halt_check, branch->c.dbg_name,
+				CBCR_REG(branch), BRANCH_OFF);
+}
+
+static int branch_cdiv_set_rate(struct branch_clk *branch, unsigned long rate)
+{
+	unsigned long flags;
+	u32 regval;
+
+	if (rate > branch->max_div)
+		return -EINVAL;
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	regval = readl_relaxed(CBCR_REG(branch));
+	regval &= ~CBCR_BRANCH_CDIV_MASK;
+	regval |= CBCR_BRANCH_CDIV_MASKED(rate);
+	writel_relaxed(regval, CBCR_REG(branch));
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+	return 0;
+}
+
+static int branch_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	struct branch_clk *branch = to_branch_clk(c);
+
+	if (branch->max_div)
+		return branch_cdiv_set_rate(branch, rate);
+
+	if (!branch->has_sibling)
+		return clk_set_rate(branch->parent, rate);
+
+	return -EPERM;
+}
+
+static unsigned long branch_clk_get_rate(struct clk *c)
+{
+	struct branch_clk *branch = to_branch_clk(c);
+
+	if (branch->max_div)
+		return branch->c.rate;
+
+	if (!branch->has_sibling)
+		return clk_get_rate(branch->parent);
+
+	return 0;
+}
+
+static struct clk *branch_clk_get_parent(struct clk *c)
+{
+	return to_branch_clk(c)->parent;
+}
+
+static int branch_clk_list_rate(struct clk *c, unsigned n)
+{
+	struct branch_clk *branch = to_branch_clk(c);
+
+	if (branch->has_sibling == 1)
+		return -ENXIO;
+
+	if (branch->parent)
+		return rcg_clk_list_rate(branch->parent, n);
+	else
+		return 0;
+}
+
+static enum handoff branch_clk_handoff(struct clk *c)
+{
+	struct branch_clk *branch = to_branch_clk(c);
+	u32 cbcr_regval;
+
+	cbcr_regval = readl_relaxed(CBCR_REG(branch));
+	if ((cbcr_regval & CBCR_BRANCH_OFF_BIT))
+		return HANDOFF_DISABLED_CLK;
+	pr_info("%s enabled.\n", branch->c.dbg_name);
+
+	if (branch->parent) {
+		if (branch->parent->ops->handoff)
+			return branch->parent->ops->handoff(branch->parent);
+	}
+
+	return HANDOFF_ENABLED_CLK;
+}
+
+static int __branch_clk_reset(void __iomem *bcr_reg,
+				enum clk_reset_action action)
+{
+	int ret = 0;
+	unsigned long flags;
+	u32 reg_val;
+
+	if (!bcr_reg)
+		return -EPERM;
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	reg_val = readl_relaxed(bcr_reg);
+	switch (action) {
+	case CLK_RESET_ASSERT:
+		reg_val |= BCR_BLK_ARES_BIT;
+		break;
+	case CLK_RESET_DEASSERT:
+		reg_val &= ~BCR_BLK_ARES_BIT;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	writel_relaxed(reg_val, bcr_reg);
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+	/* Make sure write is issued before returning. */
+	mb();
+
+	return ret;
+}
+
+static int branch_clk_reset(struct clk *c, enum clk_reset_action action)
+{
+	struct branch_clk *branch = to_branch_clk(c);
+	return __branch_clk_reset(BCR_REG(branch), action);
+}
+
+/*
+ * Voteable clock functions
+ */
+static int local_vote_clk_reset(struct clk *c, enum clk_reset_action action)
+{
+	struct branch_clk *vclk = to_branch_clk(c);
+	return __branch_clk_reset(BCR_REG(vclk), action);
+}
+
+static int local_vote_clk_enable(struct clk *c)
+{
+	unsigned long flags;
+	u32 ena;
+	struct local_vote_clk *vclk = to_local_vote_clk(c);
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	ena = readl_relaxed(VOTE_REG(vclk));
+	ena |= vclk->en_mask;
+	writel_relaxed(ena, VOTE_REG(vclk));
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+	branch_clk_halt_check(vclk->halt_check, c->dbg_name, CBCR_REG(vclk),
+				BRANCH_ON);
+
+	return 0;
+}
+
+static void local_vote_clk_disable(struct clk *c)
+{
+	unsigned long flags;
+	u32 ena;
+	struct local_vote_clk *vclk = to_local_vote_clk(c);
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	ena = readl_relaxed(VOTE_REG(vclk));
+	ena &= ~vclk->en_mask;
+	writel_relaxed(ena, VOTE_REG(vclk));
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+}
+
+static enum handoff local_vote_clk_handoff(struct clk *c)
+{
+	struct local_vote_clk *vclk = to_local_vote_clk(c);
+	u32 vote_regval;
+
+	/* Is the branch voted on by apps? */
+	vote_regval = readl_relaxed(VOTE_REG(vclk));
+	if (!(vote_regval & vclk->en_mask))
+		return HANDOFF_DISABLED_CLK;
+	pr_info("%s enabled.\n", vclk->c.dbg_name);
+
+	return HANDOFF_ENABLED_CLK;
+}
+
+struct clk_ops clk_ops_rcg = {
+	.enable = rcg_clk_enable,
+	.set_rate = rcg_clk_set_rate,
+	.list_rate = rcg_clk_list_rate,
+	.round_rate = rcg_clk_round_rate,
+	.get_parent = rcg_clk_get_parent,
+	.handoff = rcg_clk_handoff,
+};
+
+struct clk_ops clk_ops_rcg_mnd = {
+	.enable = rcg_clk_enable,
+	.set_rate = rcg_clk_set_rate,
+	.list_rate = rcg_clk_list_rate,
+	.round_rate = rcg_clk_round_rate,
+	.get_parent = rcg_clk_get_parent,
+	.handoff = rcg_mnd_clk_handoff,
+};
+
+struct clk_ops clk_ops_branch = {
+	.enable = branch_clk_enable,
+	.disable = branch_clk_disable,
+	.auto_off = branch_clk_disable,
+	.set_rate = branch_clk_set_rate,
+	.get_rate = branch_clk_get_rate,
+	.list_rate = branch_clk_list_rate,
+	.reset = branch_clk_reset,
+	.get_parent = branch_clk_get_parent,
+	.handoff = branch_clk_handoff,
+};
+
+struct clk_ops clk_ops_vote = {
+	.enable = local_vote_clk_enable,
+	.disable = local_vote_clk_disable,
+	.auto_off = local_vote_clk_disable,
+	.reset = local_vote_clk_reset,
+	.handoff = local_vote_clk_handoff,
+};
diff --git a/arch/arm/mach-msm/clock-local2.h b/arch/arm/mach-msm/clock-local2.h
new file mode 100644
index 0000000..c8d53cb
--- /dev/null
+++ b/arch/arm/mach-msm/clock-local2.h
@@ -0,0 +1,180 @@
+/* Copyright (c) 2012, 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_CLOCK_LOCAL_2_H
+#define __ARCH_ARM_MACH_MSM_CLOCK_LOCAL_2_H
+
+#include <linux/spinlock.h>
+#include "clock.h"
+
+/*
+ * Generic frequency-definition structs and macros
+ */
+
+/**
+ * @freq_hz: output rate
+ * @src_clk: source clock for freq_hz
+ * @m_val: M value corresponding to freq_hz
+ * @n_val: N value corresponding to freq_hz
+ * @d_val: D value corresponding to freq_hz
+ * @div_src_val: Pre divider value and source selection mux index for freq_hz
+ * @sys_vdd: Voltage level required for freq_hz
+ */
+struct clk_freq_tbl {
+	unsigned long	freq_hz;
+	struct clk	*src_clk;
+	const u32	m_val;
+	const u32	n_val;
+	const u32	d_val;
+	const u32	div_src_val;
+	const unsigned	sys_vdd;
+};
+
+#define FREQ_END	(UINT_MAX-1)
+#define F_END { .freq_hz = FREQ_END }
+
+/*
+ * Generic clock-definition struct and macros
+ */
+/**
+ * struct rcg_clk - root clock generator
+ * @cmd_rcgr_reg: command register
+ * @set_rate: function to set frequency
+ * @freq_tbl: frequency table for this RCG
+ * @current_freq: current RCG frequency
+ * @c: generic clock data
+ * @base: pointer to base address of ioremapped registers.
+ */
+struct rcg_clk {
+	const u32 cmd_rcgr_reg;
+
+	void   (*set_rate)(struct rcg_clk *, struct clk_freq_tbl *);
+
+	struct clk_freq_tbl *freq_tbl;
+	struct clk_freq_tbl *current_freq;
+	struct clk	c;
+
+	void *const __iomem *base;
+};
+
+static inline struct rcg_clk *to_rcg_clk(struct clk *clk)
+{
+	return container_of(clk, struct rcg_clk, c);
+}
+
+extern struct clk_freq_tbl rcg_dummy_freq;
+
+/**
+ * struct fixed_clk - fixed rate clock (used for crystal oscillators)
+ * @rate: output rate
+ * @c: clk
+ */
+struct fixed_clk {
+	struct clk c;
+};
+
+/**
+ * struct branch_clk - branch clock
+ * @set_rate: Set the frequency of this branch clock.
+ * @parent: clock source
+ * @c: clk
+ * @cbcr_reg: branch control register
+ * @bcr_reg: block reset register
+ * @has_sibling: true if other branches are derived from this branch's source
+ * @cur_div: current branch divider value
+ * @max_div: maximum branch divider value (if zero, no divider exists)
+ * @halt_check: halt checking type
+ * @base: pointer to base address of ioremapped registers.
+ */
+struct branch_clk {
+	void   (*set_rate)(struct branch_clk *, struct clk_freq_tbl *);
+	struct clk *parent;
+	struct clk c;
+	const u32 cbcr_reg;
+	const u32 bcr_reg;
+	int has_sibling;
+	u32 cur_div;
+	const u32 max_div;
+	const u32 halt_check;
+	void *const __iomem *base;
+};
+
+static inline struct branch_clk *to_branch_clk(struct clk *clk)
+{
+	return container_of(clk, struct branch_clk, c);
+}
+
+/**
+ * struct local_vote_clk - Voteable branch clock
+ * @c: clk
+ * @cbcr_reg: branch control register
+ * @vote_reg: voting register
+ * @en_mask: enable mask
+ * @halt_check: halt checking type
+ * @base: pointer to base address of ioremapped registers.
+ * An on/off switch with a rate derived from the parent.
+ */
+struct local_vote_clk {
+	struct clk c;
+	const u32 cbcr_reg;
+	const u32 vote_reg;
+	const u32 bcr_reg;
+	const u32 en_mask;
+	const u32 halt_check;
+	void *const __iomem *base;
+};
+
+static inline struct local_vote_clk *to_local_vote_clk(struct clk *clk)
+{
+	return container_of(clk, struct local_vote_clk, c);
+}
+
+/**
+ * struct measure_clk - for rate measurement debug use
+ * @sample_ticks: sample period in reference clock ticks
+ * @multiplier: measurement scale-up factor
+ * @divider: measurement scale-down factor
+ * @c: clk
+*/
+struct measure_clk {
+	u64 sample_ticks;
+	u32 multiplier;
+	u32 divider;
+	struct clk c;
+};
+
+extern struct clk_ops clk_ops_measure;
+
+static inline struct measure_clk *to_measure_clk(struct clk *clk)
+{
+	return container_of(clk, struct measure_clk, c);
+}
+
+/*
+ * Generic set-rate implementations
+ */
+void set_rate_mnd(struct rcg_clk *clk, struct clk_freq_tbl *nf);
+void set_rate_hid(struct rcg_clk *clk, struct clk_freq_tbl *nf);
+
+/*
+ * Variables from the clock-local driver
+ */
+extern spinlock_t local_clock_reg_lock;
+
+extern struct clk_ops clk_ops_rcg;
+extern struct clk_ops clk_ops_rcg_mnd;
+extern struct clk_ops clk_ops_branch;
+extern struct clk_ops clk_ops_vote;
+
+#endif /* __ARCH_ARM_MACH_MSM_COPPER_CLOCK_LOCAL_H */
+
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
index e83f17a..5022811 100644
--- a/arch/arm/mach-msm/clock-pll.c
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -45,9 +45,11 @@
 
 static DEFINE_SPINLOCK(pll_reg_lock);
 
+#define ENABLE_WAIT_MAX_LOOPS 200
+
 int pll_vote_clk_enable(struct clk *clk)
 {
-	u32 ena;
+	u32 ena, count;
 	unsigned long flags;
 	struct pll_vote_clk *pll = to_pll_vote_clk(clk);
 
@@ -57,11 +59,22 @@
 	writel_relaxed(ena, PLL_EN_REG(pll));
 	spin_unlock_irqrestore(&pll_reg_lock, flags);
 
-	/* Wait until PLL is enabled */
-	while ((readl_relaxed(PLL_STATUS_REG(pll)) & pll->status_mask) == 0)
-		cpu_relax();
+	/*
+	 * Use a memory barrier since some PLL status registers are
+	 * not within the same 1K segment as the voting registers.
+	 */
+	mb();
 
-	return 0;
+	/* Wait for pll to enable. */
+	for (count = ENABLE_WAIT_MAX_LOOPS; count > 0; count--) {
+		if (readl_relaxed(pll->status_reg) & pll->status_mask)
+			return 0;
+		udelay(1);
+	}
+
+	WARN("PLL %s didn't enable after voting for it!\n", clk->dbg_name);
+
+	return -ETIMEDOUT;
 }
 
 void pll_vote_clk_disable(struct clk *clk)
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index d5a3e8f..7ea464f 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -43,6 +43,16 @@
 #define BM(msb, lsb)	(((((uint32_t)-1) << (31-msb)) >> (31-msb+lsb)) << lsb)
 #define BVAL(msb, lsb, val)	(((val) << lsb) & BM(msb, lsb))
 
+/*
+ * Halt/Status Checking Mode Macros
+ */
+#define HALT		0	/* Bit pol: 1 = halted */
+#define NOCHECK		1	/* No bit to check, do nothing */
+#define HALT_VOTED	2	/* Bit pol: 1 = halted; delay on disable */
+#define ENABLE		3	/* Bit pol: 1 = running */
+#define ENABLE_VOTED	4	/* Bit pol: 1 = running; delay on disable */
+#define DELAY		5	/* No bit to check, just delay */
+
 #define MAX_VDD_LEVELS			4
 
 /**
diff --git a/arch/arm/mach-msm/cpuidle.c b/arch/arm/mach-msm/cpuidle.c
index 4ba3f95..b68fdc1 100644
--- a/arch/arm/mach-msm/cpuidle.c
+++ b/arch/arm/mach-msm/cpuidle.c
@@ -30,28 +30,40 @@
 	{0, 0, "C0", "WFI",
 		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
 
-	{0, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+	{0, 1, "C1", "RETENTION",
+		MSM_PM_SLEEP_MODE_RETENTION},
+
+	{0, 2, "C2", "STANDALONE_POWER_COLLAPSE",
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
 
-	{0, 2, "C2", "POWER_COLLAPSE",
+	{0, 3, "C3", "POWER_COLLAPSE",
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE},
 
 	{1, 0, "C0", "WFI",
 		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
 
-	{1, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+	{1, 1, "C1", "RETENTION",
+		MSM_PM_SLEEP_MODE_RETENTION},
+
+	{1, 2, "C2", "STANDALONE_POWER_COLLAPSE",
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
 
 	{2, 0, "C0", "WFI",
 		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
 
-	{2, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+	{2, 1, "C1", "RETENTION",
+		MSM_PM_SLEEP_MODE_RETENTION},
+
+	{2, 2, "C2", "STANDALONE_POWER_COLLAPSE",
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
 
 	{3, 0, "C0", "WFI",
 		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
 
-	{3, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+	{3, 1, "C1", "RETENTION",
+		MSM_PM_SLEEP_MODE_RETENTION},
+
+	{3, 2, "C2", "STANDALONE_POWER_COLLAPSE",
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
 };
 
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 2dc8751..aaa5bfb 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -40,6 +40,7 @@
 #include "rpm_stats.h"
 #include "rpm_log.h"
 #include <mach/mpm.h>
+#include <mach/iommu_domains.h>
 
 /* Address of GSBI blocks */
 #define MSM_GSBI1_PHYS		0x12440000
@@ -440,6 +441,16 @@
 	.id     = 0x3005,
 };
 
+struct platform_device apq_cpudai_slim_4_rx = {
+	.name   = "msm-dai-q6",
+	.id     = 0x4008,
+};
+
+struct platform_device apq_cpudai_slim_4_tx = {
+	.name   = "msm-dai-q6",
+	.id     = 0x4009,
+};
+
 /*
  * Machine specific data for AUX PCM Interface
  * which the driver will  be unware of.
@@ -471,6 +482,19 @@
 	},
 };
 
+struct msm_mi2s_data mpq_mi2s_tx_data = {
+	.sd_lines = MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 | MSM_MI2S_SD3,
+	.capability = MSM_MI2S_CAP_TX,
+};
+
+struct platform_device mpq_cpudai_mi2s_tx = {
+	.name	= "msm-dai-q6",
+	.id	= 7, /*MI2S_TX */
+	.dev = {
+		.platform_data = &mpq_mi2s_tx_data,
+	},
+};
+
 struct platform_device apq_cpu_fe = {
 	.name	= "msm-dai-fe",
 	.id	= -1,
@@ -2082,8 +2106,8 @@
 	{
 		.src = MSM_BUS_MASTER_VIDEO_CAP,
 		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 1280 * 720 * 3 * 60 / 16,
-		.ib = 1280 * 720 * 3 * 60 / 16 * 1.5,
+		.ab = 1280 * 720 * 3 * 60,
+		.ib = 1280 * 720 * 3 * 60 * 1.5,
 	},
 };
 
@@ -2091,8 +2115,8 @@
 	{
 		.src = MSM_BUS_MASTER_VIDEO_CAP,
 		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 1280 * 720 * 3 * 60 / 16,
-		.ib = 1280 * 720 * 3 * 60 / 16 * 1.5,
+		.ab = 1280 * 720 * 3 * 60,
+		.ib = 1280 * 720 * 3 * 60 * 1.5,
 	},
 };
 
@@ -2100,8 +2124,8 @@
 	{
 		.src = MSM_BUS_MASTER_VIDEO_CAP,
 		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 1920 * 1080 * 3 * 60 / 16,
-		.ib = 1920 * 1080 * 3 * 60 / 16 * 1.5,
+		.ab = 1920 * 1080 * 3 * 60,
+		.ib = 1920 * 1080 * 3 * 60 * 1.5,
 	},
 };
 
@@ -2226,3 +2250,161 @@
 	.num_resources = ARRAY_SIZE(msm_etm_resources),
 	.resource      = msm_etm_resources,
 };
+
+struct msm_iommu_domain_name apq8064_iommu_ctx_names[] = {
+	/* Camera */
+	{
+		.name = "vpe_src",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "vpe_dst",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "vfe_imgwr",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "vfe_misc",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "ijpeg_src",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "ijpeg_dst",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "jpegd_src",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "jpegd_dst",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Rotator */
+	{
+		.name = "rot_src",
+		.domain = ROTATOR_DOMAIN,
+	},
+	/* Rotator */
+	{
+		.name = "rot_dst",
+		.domain = ROTATOR_DOMAIN,
+	},
+	/* Video */
+	{
+		.name = "vcodec_a_mm1",
+		.domain = VIDEO_DOMAIN,
+	},
+	/* Video */
+	{
+		.name = "vcodec_b_mm2",
+		.domain = VIDEO_DOMAIN,
+	},
+	/* Video */
+	{
+		.name = "vcodec_a_stream",
+		.domain = VIDEO_DOMAIN,
+	},
+};
+
+static struct mem_pool apq8064_video_pools[] =  {
+	/*
+	 * Video hardware has the following requirements:
+	 * 1. All video addresses used by the video hardware must be at a higher
+	 *    address than video firmware address.
+	 * 2. Video hardware can only access a range of 256MB from the base of
+	 *    the video firmware.
+	*/
+	[VIDEO_FIRMWARE_POOL] =
+	/* Low addresses, intended for video firmware */
+		{
+			.paddr	= SZ_128K,
+			.size	= SZ_16M - SZ_128K,
+		},
+	[VIDEO_MAIN_POOL] =
+	/* Main video pool */
+		{
+			.paddr	= SZ_16M,
+			.size	= SZ_256M - SZ_16M,
+		},
+	[GEN_POOL] =
+	/* Remaining address space up to 2G */
+		{
+			.paddr	= SZ_256M,
+			.size	= SZ_2G - SZ_256M,
+		},
+};
+
+static struct mem_pool apq8064_camera_pools[] =  {
+	[GEN_POOL] =
+	/* One address space for camera */
+		{
+			.paddr	= SZ_128K,
+			.size	= SZ_2G - SZ_128K,
+		},
+};
+
+static struct mem_pool apq8064_display_pools[] =  {
+	[GEN_POOL] =
+	/* One address space for display */
+		{
+			.paddr	= SZ_128K,
+			.size	= SZ_2G - SZ_128K,
+		},
+};
+
+static struct mem_pool apq8064_rotator_pools[] =  {
+	[GEN_POOL] =
+	/* One address space for rotator */
+		{
+			.paddr	= SZ_128K,
+			.size	= SZ_2G - SZ_128K,
+		},
+};
+
+static struct msm_iommu_domain apq8064_iommu_domains[] = {
+		[VIDEO_DOMAIN] = {
+			.iova_pools = apq8064_video_pools,
+			.npools = ARRAY_SIZE(apq8064_video_pools),
+		},
+		[CAMERA_DOMAIN] = {
+			.iova_pools = apq8064_camera_pools,
+			.npools = ARRAY_SIZE(apq8064_camera_pools),
+		},
+		[DISPLAY_DOMAIN] = {
+			.iova_pools = apq8064_display_pools,
+			.npools = ARRAY_SIZE(apq8064_display_pools),
+		},
+		[ROTATOR_DOMAIN] = {
+			.iova_pools = apq8064_rotator_pools,
+			.npools = ARRAY_SIZE(apq8064_rotator_pools),
+		},
+};
+
+struct iommu_domains_pdata apq8064_iommu_domain_pdata = {
+	.domains = apq8064_iommu_domains,
+	.ndomains = ARRAY_SIZE(apq8064_iommu_domains),
+	.domain_names = apq8064_iommu_ctx_names,
+	.nnames = ARRAY_SIZE(apq8064_iommu_ctx_names),
+	.domain_alloc_flags = 0,
+};
+
+struct platform_device apq8064_iommu_domain_device = {
+	.name = "iommu_domains",
+	.id = -1,
+	.dev = {
+		.platform_data = &apq8064_iommu_domain_pdata,
+	},
+};
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index 85e927e..b7048db 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -22,6 +22,7 @@
 #include <mach/msm_bus_board.h>
 #include <mach/board.h>
 #include <mach/socinfo.h>
+#include <mach/iommu_domains.h>
 
 #include "devices.h"
 #include "rpm_log.h"
@@ -628,3 +629,161 @@
 	}
 	platform_add_devices(vidc_device, ARRAY_SIZE(vidc_device));
 }
+
+struct msm_iommu_domain_name msm8930_iommu_ctx_names[] = {
+	/* Camera */
+	{
+		.name = "vpe_src",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "vpe_dst",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "vfe_imgwr",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "vfe_misc",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "ijpeg_src",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "ijpeg_dst",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "jpegd_src",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "jpegd_dst",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Rotator */
+	{
+		.name = "rot_src",
+		.domain = ROTATOR_DOMAIN,
+	},
+	/* Rotator */
+	{
+		.name = "rot_dst",
+		.domain = ROTATOR_DOMAIN,
+	},
+	/* Video */
+	{
+		.name = "vcodec_a_mm1",
+		.domain = VIDEO_DOMAIN,
+	},
+	/* Video */
+	{
+		.name = "vcodec_b_mm2",
+		.domain = VIDEO_DOMAIN,
+	},
+	/* Video */
+	{
+		.name = "vcodec_a_stream",
+		.domain = VIDEO_DOMAIN,
+	},
+};
+
+static struct mem_pool msm8930_video_pools[] =  {
+	/*
+	 * Video hardware has the following requirements:
+	 * 1. All video addresses used by the video hardware must be at a higher
+	 *    address than video firmware address.
+	 * 2. Video hardware can only access a range of 256MB from the base of
+	 *    the video firmware.
+	*/
+	[VIDEO_FIRMWARE_POOL] =
+	/* Low addresses, intended for video firmware */
+		{
+			.paddr	= SZ_128K,
+			.size	= SZ_16M - SZ_128K,
+		},
+	[VIDEO_MAIN_POOL] =
+	/* Main video pool */
+		{
+			.paddr	= SZ_16M,
+			.size	= SZ_256M - SZ_16M,
+		},
+	[GEN_POOL] =
+	/* Remaining address space up to 2G */
+		{
+			.paddr	= SZ_256M,
+			.size	= SZ_2G - SZ_256M,
+		},
+};
+
+static struct mem_pool msm8930_camera_pools[] =  {
+	[GEN_POOL] =
+	/* One address space for camera */
+		{
+			.paddr	= SZ_128K,
+			.size	= SZ_2G - SZ_128K,
+		},
+};
+
+static struct mem_pool msm8930_display_pools[] =  {
+	[GEN_POOL] =
+	/* One address space for display */
+		{
+			.paddr	= SZ_128K,
+			.size	= SZ_2G - SZ_128K,
+		},
+};
+
+static struct mem_pool msm8930_rotator_pools[] =  {
+	[GEN_POOL] =
+	/* One address space for rotator */
+		{
+			.paddr	= SZ_128K,
+			.size	= SZ_2G - SZ_128K,
+		},
+};
+
+static struct msm_iommu_domain msm8930_iommu_domains[] = {
+		[VIDEO_DOMAIN] = {
+			.iova_pools = msm8930_video_pools,
+			.npools = ARRAY_SIZE(msm8930_video_pools),
+		},
+		[CAMERA_DOMAIN] = {
+			.iova_pools = msm8930_camera_pools,
+			.npools = ARRAY_SIZE(msm8930_camera_pools),
+		},
+		[DISPLAY_DOMAIN] = {
+			.iova_pools = msm8930_display_pools,
+			.npools = ARRAY_SIZE(msm8930_display_pools),
+		},
+		[ROTATOR_DOMAIN] = {
+			.iova_pools = msm8930_rotator_pools,
+			.npools = ARRAY_SIZE(msm8930_rotator_pools),
+		},
+};
+
+struct iommu_domains_pdata msm8930_iommu_domain_pdata = {
+	.domains = msm8930_iommu_domains,
+	.ndomains = ARRAY_SIZE(msm8930_iommu_domains),
+	.domain_names = msm8930_iommu_ctx_names,
+	.nnames = ARRAY_SIZE(msm8930_iommu_ctx_names),
+	.domain_alloc_flags = 0,
+};
+
+struct platform_device msm8930_iommu_domain_device = {
+	.name = "iommu_domains",
+	.id = -1,
+	.dev = {
+		.platform_data = &msm8930_iommu_domain_pdata,
+	},
+};
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 894c13f..8df1d7a 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -47,6 +47,7 @@
 #include "pil-q6v4.h"
 #include "scm-pas.h"
 #include <mach/msm_dcvs.h>
+#include <mach/iommu_domains.h>
 
 #ifdef CONFIG_MSM_MPM
 #include <mach/mpm.h>
@@ -3343,3 +3344,161 @@
 	.num_resources	= ARRAY_SIZE(msm_cache_erp_resources),
 	.resource	= msm_cache_erp_resources,
 };
+
+struct msm_iommu_domain_name msm8960_iommu_ctx_names[] = {
+	/* Camera */
+	{
+		.name = "vpe_src",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "vpe_dst",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "vfe_imgwr",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "vfe_misc",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "ijpeg_src",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "ijpeg_dst",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "jpegd_src",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Camera */
+	{
+		.name = "jpegd_dst",
+		.domain = CAMERA_DOMAIN,
+	},
+	/* Rotator */
+	{
+		.name = "rot_src",
+		.domain = ROTATOR_DOMAIN,
+	},
+	/* Rotator */
+	{
+		.name = "rot_dst",
+		.domain = ROTATOR_DOMAIN,
+	},
+	/* Video */
+	{
+		.name = "vcodec_a_mm1",
+		.domain = VIDEO_DOMAIN,
+	},
+	/* Video */
+	{
+		.name = "vcodec_b_mm2",
+		.domain = VIDEO_DOMAIN,
+	},
+	/* Video */
+	{
+		.name = "vcodec_a_stream",
+		.domain = VIDEO_DOMAIN,
+	},
+};
+
+static struct mem_pool msm8960_video_pools[] =  {
+	/*
+	 * Video hardware has the following requirements:
+	 * 1. All video addresses used by the video hardware must be at a higher
+	 *    address than video firmware address.
+	 * 2. Video hardware can only access a range of 256MB from the base of
+	 *    the video firmware.
+	*/
+	[VIDEO_FIRMWARE_POOL] =
+	/* Low addresses, intended for video firmware */
+		{
+			.paddr	= SZ_128K,
+			.size	= SZ_16M - SZ_128K,
+		},
+	[VIDEO_MAIN_POOL] =
+	/* Main video pool */
+		{
+			.paddr	= SZ_16M,
+			.size	= SZ_256M - SZ_16M,
+		},
+	[GEN_POOL] =
+	/* Remaining address space up to 2G */
+		{
+			.paddr	= SZ_256M,
+			.size	= SZ_2G - SZ_256M,
+		},
+};
+
+static struct mem_pool msm8960_camera_pools[] =  {
+	[GEN_POOL] =
+	/* One address space for camera */
+		{
+			.paddr	= SZ_128K,
+			.size	= SZ_2G - SZ_128K,
+		},
+};
+
+static struct mem_pool msm8960_display_pools[] =  {
+	[GEN_POOL] =
+	/* One address space for display */
+		{
+			.paddr	= SZ_128K,
+			.size	= SZ_2G - SZ_128K,
+		},
+};
+
+static struct mem_pool msm8960_rotator_pools[] =  {
+	[GEN_POOL] =
+	/* One address space for rotator */
+		{
+			.paddr	= SZ_128K,
+			.size	= SZ_2G - SZ_128K,
+		},
+};
+
+static struct msm_iommu_domain msm8960_iommu_domains[] = {
+		[VIDEO_DOMAIN] = {
+			.iova_pools = msm8960_video_pools,
+			.npools = ARRAY_SIZE(msm8960_video_pools),
+		},
+		[CAMERA_DOMAIN] = {
+			.iova_pools = msm8960_camera_pools,
+			.npools = ARRAY_SIZE(msm8960_camera_pools),
+		},
+		[DISPLAY_DOMAIN] = {
+			.iova_pools = msm8960_display_pools,
+			.npools = ARRAY_SIZE(msm8960_display_pools),
+		},
+		[ROTATOR_DOMAIN] = {
+			.iova_pools = msm8960_rotator_pools,
+			.npools = ARRAY_SIZE(msm8960_rotator_pools),
+		},
+};
+
+struct iommu_domains_pdata msm8960_iommu_domain_pdata = {
+	.domains = msm8960_iommu_domains,
+	.ndomains = ARRAY_SIZE(msm8960_iommu_domains),
+	.domain_names = msm8960_iommu_ctx_names,
+	.nnames = ARRAY_SIZE(msm8960_iommu_ctx_names),
+	.domain_alloc_flags = 0,
+};
+
+struct platform_device msm8960_iommu_domain_device = {
+	.name = "iommu_domains",
+	.id = -1,
+	.dev = {
+		.platform_data = &msm8960_iommu_domain_pdata,
+	},
+};
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 60bcdce..34298c5 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -1247,18 +1247,6 @@
 	},
 };
 
-uint32_t __init msm9615_rpm_get_swfi_latency(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(msm_rpmrs_levels); i++) {
-		if (msm_rpmrs_levels[i].sleep_mode ==
-			MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)
-				return msm_rpmrs_levels[i].latency_us;
-	}
-	return 0;
-}
-
 void __init msm9615_device_init(void)
 {
 	msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index 29e8180..9a03afd 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -376,11 +376,13 @@
 static struct msm_iommu_dev gfx2d0_iommu = {
 	.name = "gfx2d0",
 	.ncb = 2,
+	.ttbr_split = 2,
 };
 
 static struct msm_iommu_dev gfx2d1_iommu = {
 	.name = "gfx2d1",
 	.ncb = 2,
+	.ttbr_split = 2,
 };
 
 static struct msm_iommu_dev vcap_iommu = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 48a38f0..5718fe0 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -238,6 +238,7 @@
 extern struct platform_device apq_pcm_routing;
 extern struct platform_device apq_cpudai0;
 extern struct platform_device apq_cpudai1;
+extern struct platform_device mpq_cpudai_mi2s_tx;
 extern struct platform_device apq_cpudai_hdmi_rx;
 extern struct platform_device apq_cpudai_bt_rx;
 extern struct platform_device apq_cpudai_bt_tx;
@@ -262,6 +263,8 @@
 extern struct platform_device apq_cpudai_slimbus_1_rx;
 extern struct platform_device apq_cpudai_slimbus_1_tx;
 extern struct platform_device apq_cpudai_slimbus_2_tx;
+extern struct platform_device apq_cpudai_slim_4_rx;
+extern struct platform_device apq_cpudai_slim_4_tx;
 
 extern struct platform_device *msm_footswitch_devices[];
 extern unsigned msm_num_footswitch_devices;
@@ -370,5 +373,8 @@
 extern struct platform_device msm_device_csic1;
 extern struct platform_device msm_device_vfe;
 extern struct platform_device msm_device_vpe;
-
 extern struct platform_device mpq8064_device_qup_i2c_gsbi5;
+
+extern struct platform_device msm8960_iommu_domain_device;
+extern struct platform_device msm8930_iommu_domain_device;
+extern struct platform_device apq8064_iommu_domain_device;
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index c92c049..bde7713 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.c
@@ -638,6 +638,11 @@
 			fs->clk_data = gfx3d_8064_clks;
 		else
 			fs->clk_data = gfx3d_8660_clks;
+	} else if (pdev->id == FS_VED) {
+		if (cpu_is_apq8064()) {
+			fs->bus_port0 = MSM_BUS_MASTER_VIDEO_ENC;
+			fs->bus_port1 = MSM_BUS_MASTER_VIDEO_DEC;
+		}
 	}
 
 	for (clock = fs->clk_data; clock->name; clock++) {
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 36cdd86..c46c493 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -475,6 +475,12 @@
 	bool (*check_hdcp_hw_support)(void);
 };
 
+struct msm_mhl_platform_data {
+	int irq;
+	int (*gpio_setup)(int on);
+	void (*reset_pin)(int on);
+};
+
 struct msm_i2c_platform_data {
 	int clk_freq;
 	uint32_t rmutex;
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index e6a0175..7857e69 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -365,6 +365,7 @@
 	struct list_head list_frame;
 	struct list_head list_pict;
 	struct list_head list_vpe_frame;
+	struct list_head list_eventdata;
 	enum msm_queue type;
 	void *command;
 	atomic_t on_heap;
@@ -638,8 +639,6 @@
 };
 
 int msm_camio_enable(struct platform_device *dev);
-int msm_camio_jpeg_clk_enable(void);
-int msm_camio_jpeg_clk_disable(void);
 int msm_camio_vpe_clk_enable(uint32_t);
 int msm_camio_vpe_clk_disable(void);
 
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index c17795a..52e70ec 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -13,6 +13,8 @@
 #ifndef _ARCH_IOMMU_DOMAINS_H
 #define _ARCH_IOMMU_DOMAINS_H
 
+#include <linux/memory_alloc.h>
+
 enum {
 	VIDEO_DOMAIN,
 	CAMERA_DOMAIN,
@@ -27,6 +29,32 @@
 	GEN_POOL,
 };
 
+struct msm_iommu_domain_name {
+	char *name;
+	int domain;
+};
+
+struct msm_iommu_domain {
+	/* iommu domain to map in */
+	struct iommu_domain *domain;
+	/* total number of allocations from this domain */
+	atomic_t allocation_cnt;
+	/* number of iova pools */
+	int npools;
+	/*
+	 * array of gen_pools for allocating iovas.
+	 * behavior is undefined if these overlap
+	 */
+	struct mem_pool *iova_pools;
+};
+
+struct iommu_domains_pdata {
+	struct msm_iommu_domain *domains;
+	int ndomains;
+	struct msm_iommu_domain_name *domain_names;
+	int nnames;
+	unsigned int domain_alloc_flags;
+};
 
 #if defined(CONFIG_MSM_IOMMU)
 
@@ -42,10 +70,6 @@
 			unsigned int partition_no,
 			unsigned long size);
 
-extern unsigned long msm_subsystem_get_domain_no(int subsys_id);
-
-extern unsigned long msm_subsystem_get_partition_no(int subsys_id);
-
 extern int msm_use_iommu(void);
 
 extern int msm_iommu_map_extra(struct iommu_domain *domain,
@@ -69,16 +93,6 @@
 			unsigned int partition_no,
 			unsigned long size) { return; }
 
-static inline unsigned long msm_subsystem_get_domain_no(int subsys_id)
-{
-	return 0xFFFFFFFF;
-}
-
-static inline unsigned long msm_subsystem_get_partition_no(int subsys_id)
-{
-	return 0xFFFFFFFF;
-}
-
 static inline int msm_use_iommu(void)
 {
 	return 0;
diff --git a/arch/arm/mach-msm/include/mach/subsystem_restart.h b/arch/arm/mach-msm/include/mach/subsystem_restart.h
index f7becef..51ace96 100644
--- a/arch/arm/mach-msm/include/mach/subsystem_restart.h
+++ b/arch/arm/mach-msm/include/mach/subsystem_restart.h
@@ -22,7 +22,6 @@
 	RESET_SOC = 1,
 	RESET_SUBSYS_COUPLED,
 	RESET_SUBSYS_INDEPENDENT,
-	RESET_SUBSYS_MIXED = 25,
 	RESET_LEVEL_MAX
 };
 
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index 1959f5d..8f4af3b 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -13,6 +13,7 @@
 #include <mach/msm_subsystem_map.h>
 #include <linux/memory_alloc.h>
 #include <linux/iommu.h>
+#include <linux/platform_device.h>
 #include <linux/vmalloc.h>
 #include <asm/sizes.h>
 #include <asm/page.h>
@@ -24,166 +25,12 @@
 /* dummy 4k for overmapping */
 char iommu_dummy[2*PAGE_SIZE-4];
 
-struct msm_iommu_domain {
-	/* iommu domain to map in */
-	struct iommu_domain *domain;
-	/* total number of allocations from this domain */
-	atomic_t allocation_cnt;
-	/* number of iova pools */
-	int npools;
-	/*
-	 * array of gen_pools for allocating iovas.
-	 * behavior is undefined if these overlap
-	 */
-	struct mem_pool *iova_pools;
-
+struct msm_iommu_domain_state {
+	struct msm_iommu_domain *domains;
+	int ndomains;
 };
 
-
-struct {
-	char *name;
-	int  domain;
-} msm_iommu_ctx_names[] = {
-	/* Camera */
-	{
-		.name = "vpe_src",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vpe_dst",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_imgwr",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_misc",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "ijpeg_src",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "ijpeg_dst",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "jpegd_src",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "jpegd_dst",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Rotator */
-	{
-		.name = "rot_src",
-		.domain = ROTATOR_DOMAIN,
-	},
-	/* Rotator */
-	{
-		.name = "rot_dst",
-		.domain = ROTATOR_DOMAIN,
-	},
-	/* Video */
-	{
-		.name = "vcodec_a_mm1",
-		.domain = VIDEO_DOMAIN,
-	},
-	/* Video */
-	{
-		.name = "vcodec_b_mm2",
-		.domain = VIDEO_DOMAIN,
-	},
-	/* Video */
-	{
-		.name = "vcodec_a_stream",
-		.domain = VIDEO_DOMAIN,
-	},
-};
-
-static struct mem_pool video_pools[] =  {
-	/*
-	 * Video hardware has the following requirements:
-	 * 1. All video addresses used by the video hardware must be at a higher
-	 *    address than video firmware address.
-	 * 2. Video hardware can only access a range of 256MB from the base of
-	 *    the video firmware.
-	*/
-	[VIDEO_FIRMWARE_POOL] =
-	/* Low addresses, intended for video firmware */
-		{
-			.paddr	= SZ_128K,
-			.size	= SZ_16M - SZ_128K,
-		},
-	[VIDEO_MAIN_POOL] =
-	/* Main video pool */
-		{
-			.paddr	= SZ_16M,
-			.size	= SZ_256M - SZ_16M,
-		},
-	[GEN_POOL] =
-	/* Remaining address space up to 2G */
-		{
-			.paddr	= SZ_256M,
-			.size	= SZ_2G - SZ_256M,
-		},
-};
-
-static struct mem_pool camera_pools[] =  {
-	[GEN_POOL] =
-	/* One address space for camera */
-		{
-			.paddr	= SZ_128K,
-			.size	= SZ_2G - SZ_128K,
-		},
-};
-
-static struct mem_pool display_pools[] =  {
-	[GEN_POOL] =
-	/* One address space for display */
-		{
-			.paddr	= SZ_128K,
-			.size	= SZ_2G - SZ_128K,
-		},
-};
-
-static struct mem_pool rotator_pools[] =  {
-	[GEN_POOL] =
-	/* One address space for rotator */
-		{
-			.paddr	= SZ_128K,
-			.size	= SZ_2G - SZ_128K,
-		},
-};
-
-static struct msm_iommu_domain msm_iommu_domains[] = {
-		[VIDEO_DOMAIN] = {
-			.iova_pools = video_pools,
-			.npools = ARRAY_SIZE(video_pools),
-		},
-		[CAMERA_DOMAIN] = {
-			.iova_pools = camera_pools,
-			.npools = ARRAY_SIZE(camera_pools),
-		},
-		[DISPLAY_DOMAIN] = {
-			.iova_pools = display_pools,
-			.npools = ARRAY_SIZE(display_pools),
-		},
-		[ROTATOR_DOMAIN] = {
-			.iova_pools = rotator_pools,
-			.npools = ARRAY_SIZE(rotator_pools),
-		},
-};
+static struct msm_iommu_domain_state domain_state;
 
 int msm_iommu_map_extra(struct iommu_domain *domain,
 				unsigned long start_iova,
@@ -221,46 +68,12 @@
 
 struct iommu_domain *msm_get_iommu_domain(int domain_num)
 {
-	if (domain_num >= 0 && domain_num < MAX_DOMAINS)
-		return msm_iommu_domains[domain_num].domain;
+	if (domain_num >= 0 && domain_num < domain_state.ndomains)
+		return domain_state.domains[domain_num].domain;
 	else
 		return NULL;
 }
 
-static unsigned long subsystem_to_domain_tbl[] = {
-	VIDEO_DOMAIN,
-	VIDEO_DOMAIN,
-	CAMERA_DOMAIN,
-	DISPLAY_DOMAIN,
-	ROTATOR_DOMAIN,
-	0xFFFFFFFF
-};
-
-unsigned long msm_subsystem_get_domain_no(int subsys_id)
-{
-	if (subsys_id > INVALID_SUBSYS_ID && subsys_id <= MAX_SUBSYSTEM_ID &&
-	    subsys_id < ARRAY_SIZE(subsystem_to_domain_tbl))
-		return subsystem_to_domain_tbl[subsys_id];
-	else
-		return subsystem_to_domain_tbl[MAX_SUBSYSTEM_ID];
-}
-
-unsigned long msm_subsystem_get_partition_no(int subsys_id)
-{
-	switch (subsys_id) {
-	case MSM_SUBSYSTEM_VIDEO_FWARE:
-		return VIDEO_FIRMWARE_POOL;
-	case MSM_SUBSYSTEM_VIDEO:
-		return VIDEO_MAIN_POOL;
-	case MSM_SUBSYSTEM_CAMERA:
-	case MSM_SUBSYSTEM_DISPLAY:
-	case MSM_SUBSYSTEM_ROTATOR:
-		return GEN_POOL;
-	default:
-		return 0xFFFFFFFF;
-	}
-}
-
 unsigned long msm_allocate_iova_address(unsigned int iommu_domain,
 					unsigned int partition_no,
 					unsigned long size,
@@ -269,13 +82,13 @@
 	struct mem_pool *pool;
 	unsigned long iova;
 
-	if (iommu_domain >= MAX_DOMAINS)
+	if (iommu_domain >= domain_state.ndomains)
 		return 0;
 
-	if (partition_no >= msm_iommu_domains[iommu_domain].npools)
+	if (partition_no >= domain_state.domains[iommu_domain].npools)
 		return 0;
 
-	pool = &msm_iommu_domains[iommu_domain].iova_pools[partition_no];
+	pool = &domain_state.domains[iommu_domain].iova_pools[partition_no];
 
 	if (!pool->gpool)
 		return 0;
@@ -294,18 +107,18 @@
 {
 	struct mem_pool *pool;
 
-	if (iommu_domain >= MAX_DOMAINS) {
+	if (iommu_domain >= domain_state.ndomains) {
 		WARN(1, "Invalid domain %d\n", iommu_domain);
 		return;
 	}
 
-	if (partition_no >= msm_iommu_domains[iommu_domain].npools) {
+	if (partition_no >= domain_state.domains[iommu_domain].npools) {
 		WARN(1, "Invalid partition %d for domain %d\n",
 			partition_no, iommu_domain);
 		return;
 	}
 
-	pool = &msm_iommu_domains[iommu_domain].iova_pools[partition_no];
+	pool = &domain_state.domains[iommu_domain].iova_pools[partition_no];
 
 	if (!pool)
 		return;
@@ -316,20 +129,31 @@
 
 int msm_use_iommu()
 {
-	return iommu_found();
+	/*
+	 * If there are no domains, don't bother trying to use the iommu
+	 */
+	return domain_state.ndomains && iommu_found();
 }
 
-static int __init msm_subsystem_iommu_init(void)
+static int __init iommu_domain_probe(struct platform_device *pdev)
 {
+	struct iommu_domains_pdata *p  = pdev->dev.platform_data;
 	int i, j;
 
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_domains); i++) {
-		msm_iommu_domains[i].domain = iommu_domain_alloc(0);
-		if (!msm_iommu_domains[i].domain)
+	if (!p)
+		return -ENODEV;
+
+	domain_state.domains = p->domains;
+	domain_state.ndomains = p->ndomains;
+
+	for (i = 0; i < domain_state.ndomains; i++) {
+		domain_state.domains[i].domain = iommu_domain_alloc(
+							p->domain_alloc_flags);
+		if (!domain_state.domains[i].domain)
 			continue;
 
-		for (j = 0; j < msm_iommu_domains[i].npools; j++) {
-			struct mem_pool *pool = &msm_iommu_domains[i].
+		for (j = 0; j < domain_state.domains[i].npools; j++) {
+			struct mem_pool *pool = &domain_state.domains[i].
 							iova_pools[j];
 			mutex_init(&pool->pool_mutex);
 			if (pool->size) {
@@ -359,29 +183,41 @@
 		}
 	}
 
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_names); i++) {
+	for (i = 0; i < p->nnames; i++) {
 		int domain_idx;
 		struct device *ctx = msm_iommu_get_ctx(
-						msm_iommu_ctx_names[i].name);
+						p->domain_names[i].name);
 
 		if (!ctx)
 			continue;
 
-		domain_idx = msm_iommu_ctx_names[i].domain;
+		domain_idx = p->domain_names[i].domain;
 
-		if (!msm_iommu_domains[domain_idx].domain)
+		if (!domain_state.domains[domain_idx].domain)
 			continue;
 
-		if (iommu_attach_device(msm_iommu_domains[domain_idx].domain,
+		if (iommu_attach_device(domain_state.domains[domain_idx].domain,
 					ctx)) {
 			WARN(1, "%s: could not attach domain %d to context %s."
 				" iommu programming will not occur.\n",
 				__func__, domain_idx,
-				msm_iommu_ctx_names[i].name);
+				p->domain_names[i].name);
 			continue;
 		}
 	}
 
 	return 0;
 }
+
+static struct platform_driver iommu_domain_driver = {
+	.driver         = {
+		.name = "iommu_domains",
+		.owner = THIS_MODULE
+	},
+};
+
+static int __init msm_subsystem_iommu_init(void)
+{
+	return platform_driver_probe(&iommu_domain_driver, iommu_domain_probe);
+}
 device_initcall(msm_subsystem_iommu_init);
diff --git a/arch/arm/mach-msm/ipc_router.h b/arch/arm/mach-msm/ipc_router.h
index a90be23..462543e 100644
--- a/arch/arm/mach-msm/ipc_router.h
+++ b/arch/arm/mach-msm/ipc_router.h
@@ -138,7 +138,7 @@
 struct msm_ipc_sock {
 	struct sock sk;
 	struct msm_ipc_port *port;
-	void *default_pil;
+	void *modem_pil;
 };
 
 enum write_data_type {
@@ -206,15 +206,4 @@
 int msm_ipc_router_init_sockets(void);
 void msm_ipc_router_exit_sockets(void);
 
-#if defined CONFIG_MSM_IPC_ROUTER_SMD_XPRT
-extern void *msm_ipc_load_default_node(void);
-
-extern void msm_ipc_unload_default_node(void *pil);
-#else
-static inline void *msm_ipc_load_default_node(void)
-{ return NULL; }
-
-static inline void msm_ipc_unload_default_node(void *pil) { }
-#endif
-
 #endif
diff --git a/arch/arm/mach-msm/ipc_router_smd_xprt.c b/arch/arm/mach-msm/ipc_router_smd_xprt.c
index 307b6ae..0cde393 100644
--- a/arch/arm/mach-msm/ipc_router_smd_xprt.c
+++ b/arch/arm/mach-msm/ipc_router_smd_xprt.c
@@ -19,7 +19,6 @@
 #include <linux/types.h>
 
 #include <mach/msm_smd.h>
-#include <mach/peripheral-loader.h>
 
 #include "ipc_router.h"
 #include "smd_private.h"
@@ -443,31 +442,6 @@
 	return 0;
 }
 
-void *msm_ipc_load_default_node(void)
-{
-	void *pil = NULL;
-	const char *peripheral;
-
-	peripheral = smd_edge_to_subsystem(SMD_APPS_MODEM);
-	if (peripheral && !strncmp(peripheral, "modem", 6)) {
-		pil = pil_get(peripheral);
-		if (IS_ERR(pil)) {
-			pr_err("%s: Failed to load %s\n",
-				__func__, peripheral);
-			pil = NULL;
-		}
-	}
-	return pil;
-}
-EXPORT_SYMBOL(msm_ipc_load_default_node);
-
-void msm_ipc_unload_default_node(void *pil)
-{
-	if (pil)
-		pil_put(pil);
-}
-EXPORT_SYMBOL(msm_ipc_unload_default_node);
-
 static struct platform_driver msm_ipc_router_smd_remote_driver[] = {
 	{
 		.probe		= msm_ipc_router_smd_remote_probe,
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index d1ed538..6e8c99e 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -26,15 +26,58 @@
 
 #include <net/sock.h>
 
+#include <mach/peripheral-loader.h>
+#include <mach/socinfo.h>
+
 #include "ipc_router.h"
 
 #define msm_ipc_sk(sk) ((struct msm_ipc_sock *)(sk))
 #define msm_ipc_sk_port(sk) ((struct msm_ipc_port *)(msm_ipc_sk(sk)->port))
+#define MODEM_LOAD_TIMEOUT (10 * HZ)
 
 static int sockets_enabled;
 static struct proto msm_ipc_proto;
 static const struct proto_ops msm_ipc_proto_ops;
 
+static void msm_ipc_router_unload_modem(void *pil)
+{
+	if (pil)
+		pil_put(pil);
+}
+
+static void *msm_ipc_router_load_modem(void)
+{
+	void *pil = NULL;
+	int rc;
+
+	/* Load GNSS for Standalone 8064 but not for Fusion 3 */
+	if (cpu_is_apq8064()) {
+		if (socinfo_get_platform_subtype() == 0x0)
+			pil = pil_get("gss");
+	} else {
+		pil = pil_get("modem");
+	}
+
+	if (IS_ERR(pil) || !pil) {
+		pr_debug("%s: modem load failed\n", __func__);
+		pil = NULL;
+	} else {
+		rc = wait_for_completion_interruptible_timeout(
+						&msm_ipc_remote_router_up,
+						MODEM_LOAD_TIMEOUT);
+		if (!rc)
+			rc = -ETIMEDOUT;
+		if (rc < 0) {
+			pr_err("%s: wait for remote router failed %d\n",
+				__func__, rc);
+			msm_ipc_router_unload_modem(pil);
+			pil = NULL;
+		}
+	}
+
+	return pil;
+}
+
 static struct sk_buff_head *msm_ipc_router_build_msg(unsigned int num_sect,
 					  struct iovec const *msg_sect,
 					  size_t total_len)
@@ -201,9 +244,9 @@
 	sock_init_data(sock, sk);
 	sk->sk_rcvtimeo = DEFAULT_RCV_TIMEO;
 
-	pil = msm_ipc_load_default_node();
+	pil = msm_ipc_router_load_modem();
 	msm_ipc_sk(sk)->port = port_ptr;
-	msm_ipc_sk(sk)->default_pil = pil;
+	msm_ipc_sk(sk)->modem_pil = pil;
 
 	return 0;
 }
@@ -452,12 +495,12 @@
 {
 	struct sock *sk = sock->sk;
 	struct msm_ipc_port *port_ptr = msm_ipc_sk_port(sk);
-	void *pil = msm_ipc_sk(sk)->default_pil;
+	void *pil = msm_ipc_sk(sk)->modem_pil;
 	int ret;
 
 	lock_sock(sk);
 	ret = msm_ipc_router_close_port(port_ptr);
-	msm_ipc_unload_default_node(pil);
+	msm_ipc_router_unload_modem(pil);
 	release_sock(sk);
 	sock_put(sk);
 	sock->sk = NULL;
diff --git a/arch/arm/mach-msm/lpass-8660.c b/arch/arm/mach-msm/lpass-8660.c
index ff08eff..1018360 100644
--- a/arch/arm/mach-msm/lpass-8660.c
+++ b/arch/arm/mach-msm/lpass-8660.c
@@ -79,9 +79,6 @@
 	pil_force_shutdown("q6");
 	disable_irq_nosync(LPASS_Q6SS_WDOG_EXPIRED);
 
-	if (get_restart_level() == RESET_SUBSYS_MIXED)
-		smsm_reset_modem(SMSM_RESET);
-
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/msm_rtb.c b/arch/arm/mach-msm/msm_rtb.c
index 403c13d..9dbf9c1 100644
--- a/arch/arm/mach-msm/msm_rtb.c
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -74,6 +74,17 @@
 module_param_named(filter, msm_rtb.filter, uint, 0644);
 module_param_named(enable, msm_rtb.enabled, int, 0644);
 
+static int msm_rtb_panic_notifier(struct notifier_block *this,
+					unsigned long event, void *ptr)
+{
+	msm_rtb.enabled = 0;
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block msm_rtb_panic_blk = {
+	.notifier_call  = msm_rtb_panic_notifier,
+};
+
 int msm_rtb_event_should_log(enum logk_event_type log_type)
 {
 	return msm_rtb.initialized && msm_rtb.enabled &&
@@ -258,7 +269,8 @@
 	msm_rtb.step_size = 1;
 #endif
 
-
+	atomic_notifier_chain_register(&panic_notifier_list,
+						&msm_rtb_panic_blk);
 	msm_rtb.initialized = 1;
 	return 0;
 }
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
new file mode 100644
index 0000000..60ae4d9
--- /dev/null
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2012, 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/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/err.h>
+#include <linux/of.h>
+
+#include "peripheral-loader.h"
+#include "pil-q6v5.h"
+
+/* Register Offsets */
+#define QDSP6SS_RST_EVB			0x010
+#define LPASS_Q6SS_BCR			0x06000
+#define LPASS_Q6SS_AHB_LFABIF_CBCR	0x22000
+#define LPASS_Q6SS_XO_CBCR		0x26000
+#define AXI_HALTREQ			0x0
+#define AXI_HALTACK			0x4
+#define AXI_IDLE			0x8
+
+#define HALT_ACK_TIMEOUT_US		100000
+
+static void clk_reg_enable(void __iomem *reg)
+{
+	u32 val;
+	val = readl_relaxed(reg);
+	val |= BIT(0);
+	writel_relaxed(val, reg);
+}
+
+static void clk_reg_disable(void __iomem *reg)
+{
+	u32 val;
+	val = readl_relaxed(reg);
+	val &= ~BIT(0);
+	writel_relaxed(val, reg);
+}
+
+static int pil_lpass_shutdown(struct pil_desc *pil)
+{
+	struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+	int ret;
+	u32 status;
+
+	writel_relaxed(1, drv->axi_halt_base + AXI_HALTREQ);
+	ret = readl_poll_timeout(drv->axi_halt_base + AXI_HALTACK,
+		status,	status, 50, HALT_ACK_TIMEOUT_US);
+	if (ret)
+		dev_err(pil->dev, "Port halt timeout\n");
+	else if (!readl_relaxed(drv->axi_halt_base + AXI_IDLE))
+		dev_err(pil->dev, "Port halt failed\n");
+	writel_relaxed(0, drv->axi_halt_base + AXI_HALTREQ);
+
+	/* Make sure Q6 registers are accessible */
+	writel_relaxed(0, drv->clk_base + LPASS_Q6SS_BCR);
+	clk_reg_enable(drv->clk_base + LPASS_Q6SS_AHB_LFABIF_CBCR);
+	mb();
+
+	pil_q6v5_shutdown(pil);
+
+	/* Disable clocks and assert subsystem resets. */
+	clk_reg_disable(drv->clk_base + LPASS_Q6SS_AHB_LFABIF_CBCR);
+	clk_reg_disable(drv->clk_base + LPASS_Q6SS_XO_CBCR);
+	writel_relaxed(1, drv->clk_base + LPASS_Q6SS_BCR);
+
+	return 0;
+}
+
+static int pil_lpass_reset(struct pil_desc *pil)
+{
+	struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+
+	/*
+	 * Bring subsystem out of reset and enable required
+	 * regulators and clocks.
+	 */
+	writel_relaxed(0, drv->clk_base + LPASS_Q6SS_BCR);
+	clk_reg_enable(drv->clk_base + LPASS_Q6SS_XO_CBCR);
+	clk_reg_enable(drv->clk_base + LPASS_Q6SS_AHB_LFABIF_CBCR);
+	mb();
+
+	/* Program Image Address */
+	writel_relaxed(((drv->start_addr >> 4) & 0x0FFFFFF0),
+				drv->reg_base + QDSP6SS_RST_EVB);
+
+	return pil_q6v5_reset(pil);
+}
+
+static struct pil_reset_ops pil_lpass_ops = {
+	.init_image = pil_q6v5_init_image,
+	.proxy_vote = pil_q6v5_make_proxy_votes,
+	.proxy_unvote = pil_q6v5_remove_proxy_votes,
+	.auth_and_reset = pil_lpass_reset,
+	.shutdown = pil_lpass_shutdown,
+};
+
+static int __devinit pil_lpass_driver_probe(struct platform_device *pdev)
+{
+	struct q6v5_data *drv;
+	struct pil_desc *desc;
+	struct resource *res;
+
+	desc = pil_q6v5_init(pdev);
+	drv = platform_get_drvdata(pdev);
+
+	desc->ops = &pil_lpass_ops;
+	desc->owner = THIS_MODULE;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	drv->axi_halt_base = devm_ioremap(&pdev->dev, res->start,
+					  resource_size(res));
+	if (!drv->axi_halt_base)
+		return -ENOMEM;
+
+	drv->pil = msm_pil_register(desc);
+	if (IS_ERR(drv->pil))
+		return PTR_ERR(drv->pil);
+
+	return 0;
+}
+
+static int __devexit pil_lpass_driver_exit(struct platform_device *pdev)
+{
+	struct q6v5_data *drv = platform_get_drvdata(pdev);
+	msm_pil_unregister(drv->pil);
+	return 0;
+}
+
+static struct of_device_id lpass_match_table[] = {
+	{ .compatible = "qcom,pil-q6v5-lpass" },
+	{}
+};
+
+static struct platform_driver pil_lpass_driver = {
+	.probe = pil_lpass_driver_probe,
+	.remove = __devexit_p(pil_lpass_driver_exit),
+	.driver = {
+		.name = "pil-q6v5-lpass",
+		.of_match_table = lpass_match_table,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init pil_lpass_init(void)
+{
+	return platform_driver_register(&pil_lpass_driver);
+}
+module_init(pil_lpass_init);
+
+static void __exit pil_lpass_exit(void)
+{
+	platform_driver_unregister(&pil_lpass_driver);
+}
+module_exit(pil_lpass_exit);
+
+MODULE_DESCRIPTION("Support for booting low-power audio subsystems with QDSP6v5 (Hexagon) processors");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pil-q6v5.c b/arch/arm/mach-msm/pil-q6v5.c
new file mode 100644
index 0000000..cd58a4c
--- /dev/null
+++ b/arch/arm/mach-msm/pil-q6v5.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2012, 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/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/elf.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+
+#include "peripheral-loader.h"
+#include "pil-q6v5.h"
+
+/* Register Offsets */
+#define QDSP6SS_RESET			0x014
+#define QDSP6SS_GFMUX_CTL		0x020
+#define QDSP6SS_PWR_CTL			0x030
+
+/* QDSP6SS_RESET */
+#define Q6SS_CORE_ARES			BIT(1)
+#define Q6SS_ETM_ISDB_ARES		BIT(3)
+#define Q6SS_STOP_CORE			BIT(4)
+
+/* QDSP6SS_GFMUX_CTL */
+#define Q6SS_CLK_ENA			BIT(1)
+
+/* QDSP6SS_PWR_CTL */
+#define Q6SS_L2DATA_SLP_NRET_N		BIT(0)
+#define Q6SS_L2TAG_SLP_NRET_N		BIT(16)
+#define Q6SS_ETB_SLP_NRET_N		BIT(17)
+#define Q6SS_L2DATA_STBY_N		BIT(18)
+#define Q6SS_SLP_RET_N			BIT(19)
+#define Q6SS_CLAMP_IO			BIT(20)
+#define QDSS_BHS_ON			BIT(21)
+
+int pil_q6v5_make_proxy_votes(struct pil_desc *pil)
+{
+	int ret;
+	struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+
+	ret = clk_prepare_enable(drv->xo);
+	if (ret) {
+		dev_err(pil->dev, "Failed to enable XO\n");
+		return ret;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(pil_q6v5_make_proxy_votes);
+
+void pil_q6v5_remove_proxy_votes(struct pil_desc *pil)
+{
+	struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+	clk_disable_unprepare(drv->xo);
+}
+EXPORT_SYMBOL(pil_q6v5_remove_proxy_votes);
+
+int pil_q6v5_init_image(struct pil_desc *pil, const u8 *metadata,
+			       size_t size)
+{
+	const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
+	struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+	drv->start_addr = ehdr->e_entry;
+	return 0;
+}
+EXPORT_SYMBOL(pil_q6v5_init_image);
+
+void pil_q6v5_shutdown(struct pil_desc *pil)
+{
+	u32 val;
+	struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+
+	/* Turn off core clock */
+	val = readl_relaxed(drv->reg_base + QDSP6SS_GFMUX_CTL);
+	val &= ~Q6SS_CLK_ENA;
+	writel_relaxed(val, drv->reg_base + QDSP6SS_GFMUX_CTL);
+
+	/* Clamp IO */
+	val = readl_relaxed(drv->reg_base + QDSP6SS_PWR_CTL);
+	val |= Q6SS_CLAMP_IO;
+	writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
+
+	/* Turn off Q6 memories */
+	val &= ~(Q6SS_L2DATA_SLP_NRET_N | Q6SS_SLP_RET_N |
+		 Q6SS_L2TAG_SLP_NRET_N | Q6SS_ETB_SLP_NRET_N |
+		 Q6SS_L2DATA_STBY_N);
+	writel_relaxed(Q6SS_CLAMP_IO, drv->reg_base + QDSP6SS_PWR_CTL);
+
+	/* Assert Q6 resets */
+	val = readl_relaxed(drv->reg_base + QDSP6SS_RESET);
+	val = (Q6SS_CORE_ARES | Q6SS_ETM_ISDB_ARES);
+	writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
+
+	/* Kill power at block headswitch (affects LPASS only) */
+	val = readl_relaxed(drv->reg_base + QDSP6SS_PWR_CTL);
+	val &= ~QDSS_BHS_ON;
+	writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
+}
+EXPORT_SYMBOL(pil_q6v5_shutdown);
+
+int pil_q6v5_reset(struct pil_desc *pil)
+{
+	struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+	u32 val;
+
+	/* Assert resets, stop core */
+	val = readl_relaxed(drv->reg_base + QDSP6SS_RESET);
+	val |= (Q6SS_CORE_ARES | Q6SS_ETM_ISDB_ARES | Q6SS_STOP_CORE);
+	writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
+
+	/* Enable power block headswitch (only affects LPASS) */
+	val = readl_relaxed(drv->reg_base + QDSP6SS_PWR_CTL);
+	val |= QDSS_BHS_ON;
+	writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
+
+	/* Turn on memories */
+	val = readl_relaxed(drv->reg_base + QDSP6SS_PWR_CTL);
+	val |= Q6SS_L2DATA_SLP_NRET_N | Q6SS_SLP_RET_N |
+	       Q6SS_L2TAG_SLP_NRET_N | Q6SS_ETB_SLP_NRET_N |
+	       Q6SS_L2DATA_STBY_N;
+	writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
+
+	/* Remove IO clamp */
+	val &= ~Q6SS_CLAMP_IO;
+	writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
+
+	/* Bring core out of reset */
+	val = Q6SS_STOP_CORE;
+	writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
+
+	/* Turn on core clock */
+	val = readl_relaxed(drv->reg_base + QDSP6SS_GFMUX_CTL);
+	val |= Q6SS_CLK_ENA;
+	writel_relaxed(val, drv->reg_base + QDSP6SS_GFMUX_CTL);
+
+	/* Start core execution */
+	val = readl_relaxed(drv->reg_base + QDSP6SS_RESET);
+	val &= ~Q6SS_STOP_CORE;
+	writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
+
+	return 0;
+}
+EXPORT_SYMBOL(pil_q6v5_reset);
+
+struct pil_desc __devinit *pil_q6v5_init(struct platform_device *pdev)
+{
+	struct q6v5_data *drv;
+	struct resource *res;
+	struct pil_desc *desc;
+	int ret;
+
+	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+	if (!drv)
+		return ERR_PTR(-ENOMEM);
+	platform_set_drvdata(pdev, drv);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return ERR_PTR(-EINVAL);
+	drv->reg_base = devm_ioremap(&pdev->dev, res->start,
+				     resource_size(res));
+	if (!drv->reg_base)
+		return ERR_PTR(-ENOMEM);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	drv->clk_base = devm_ioremap(&pdev->dev, res->start,
+				     resource_size(res));
+	if (!drv->clk_base)
+		return ERR_PTR(-ENOMEM);
+
+	desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return ERR_PTR(-ENOMEM);
+
+	ret = of_property_read_string(pdev->dev.of_node, "qcom,firmware-name",
+				      &desc->name);
+	if (ret)
+		return ERR_PTR(ret);
+
+	drv->xo = devm_clk_get(&pdev->dev, "xo");
+	if (IS_ERR(drv->xo))
+		return ERR_CAST(drv->xo);
+
+	desc->dev = &pdev->dev;
+
+	return desc;
+}
+EXPORT_SYMBOL(pil_q6v5_init);
diff --git a/arch/arm/mach-msm/pil-q6v5.h b/arch/arm/mach-msm/pil-q6v5.h
new file mode 100644
index 0000000..b17d4e7
--- /dev/null
+++ b/arch/arm/mach-msm/pil-q6v5.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MSM_PIL_Q6V5_H
+#define __MSM_PIL_Q6V5_H
+
+struct regulator;
+struct clk;
+struct pil_device;
+struct pil_desc;
+struct platform_device;
+
+struct q6v5_data {
+	void __iomem *reg_base;
+	void __iomem *clk_base;
+	void __iomem *axi_halt_base;
+	void __iomem *rmb_base;
+	unsigned long start_addr;
+	struct regulator *vreg;
+	bool vreg_enabled;
+	int self_auth;
+	struct clk *xo;
+	struct pil_device *pil;
+};
+
+int pil_q6v5_make_proxy_votes(struct pil_desc *pil);
+void pil_q6v5_remove_proxy_votes(struct pil_desc *pil);
+int pil_q6v5_init_image(struct pil_desc *pil, const u8 *metadata,
+			size_t size);
+void pil_q6v5_shutdown(struct pil_desc *pil);
+int pil_q6v5_reset(struct pil_desc *pil);
+struct pil_desc *pil_q6v5_init(struct platform_device *pdev);
+
+#endif
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 2b0cc18..c237013 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -105,6 +105,7 @@
 static char *msm_pm_sleep_mode_labels[MSM_PM_SLEEP_MODE_NR] = {
 	[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = "power_collapse",
 	[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT] = "wfi",
+	[MSM_PM_SLEEP_MODE_RETENTION] = "retention",
 	[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE] =
 		"standalone_power_collapse",
 };
@@ -324,6 +325,7 @@
 enum msm_pm_time_stats_id {
 	MSM_PM_STAT_REQUESTED_IDLE,
 	MSM_PM_STAT_IDLE_WFI,
+	MSM_PM_STAT_RETENTION,
 	MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE,
 	MSM_PM_STAT_IDLE_POWER_COLLAPSE,
 	MSM_PM_STAT_SUSPEND,
@@ -617,14 +619,27 @@
 	msm_arch_idle();
 }
 
+
+static void msm_pm_retention(void)
+{
+	int ret = 0;
+
+	msm_pm_config_hw_before_swfi();
+	ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_POWER_RETENTION, false);
+	WARN_ON(ret);
+	msm_arch_idle();
+	ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING, false);
+	WARN_ON(ret);
+}
+
 #ifdef CONFIG_CACHE_L2X0
 static inline bool msm_pm_l2x0_power_collapse(void)
 {
 	bool collapsed = 0;
 
-	l2cc_suspend();
+	l2x0_suspend();
 	collapsed = msm_pm_collapse();
-	l2cc_resume(collapsed);
+	l2x0_resume(collapsed);
 
 	return collapsed;
 }
@@ -810,6 +825,11 @@
 			}
 			/* fall through */
 
+		case MSM_PM_SLEEP_MODE_RETENTION:
+			if (!allow)
+				break;
+			/* fall through */
+
 		case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
 			if (!allow)
 				break;
@@ -884,6 +904,13 @@
 #endif
 		break;
 
+	case MSM_PM_SLEEP_MODE_RETENTION:
+		msm_pm_retention();
+#ifdef CONFIG_MSM_IDLE_STATS
+		exit_stat = MSM_PM_STAT_RETENTION;
+#endif
+		break;
+
 	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
 		msm_pm_power_collapse_standalone(true);
 #ifdef CONFIG_MSM_IDLE_STATS
@@ -982,6 +1009,10 @@
 		per_cpu(msm_pm_last_slp_mode, cpu)
 			= MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE;
 		msm_pm_power_collapse_standalone(false);
+	} else if (allow[MSM_PM_SLEEP_MODE_RETENTION]) {
+		per_cpu(msm_pm_last_slp_mode, cpu)
+			= MSM_PM_SLEEP_MODE_RETENTION;
+		msm_pm_retention();
 	} else if (allow[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT]) {
 		per_cpu(msm_pm_last_slp_mode, cpu)
 			= MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE;
@@ -1108,6 +1139,10 @@
 		if (MSM_PM_DEBUG_SUSPEND & msm_pm_debug_mask)
 			pr_info("%s: standalone power collapse\n", __func__);
 		msm_pm_power_collapse_standalone(false);
+	} else if (allow[MSM_PM_SLEEP_MODE_RETENTION]) {
+		if (MSM_PM_DEBUG_SUSPEND & msm_pm_debug_mask)
+			pr_info("%s: retention\n", __func__);
+		msm_pm_retention();
 	} else if (allow[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT]) {
 		if (MSM_PM_DEBUG_SUSPEND & msm_pm_debug_mask)
 			pr_info("%s: swfi\n", __func__);
@@ -1195,6 +1230,10 @@
 		stats[MSM_PM_STAT_IDLE_WFI].first_bucket_time =
 			CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
 
+		stats[MSM_PM_STAT_RETENTION].name = "retention";
+		stats[MSM_PM_STAT_RETENTION].first_bucket_time =
+			CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
 		stats[MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].name =
 			"idle-standalone-power-collapse";
 		stats[MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].
diff --git a/arch/arm/mach-msm/pm-data.c b/arch/arm/mach-msm/pm-data.c
index d7001d7..6f4743f 100644
--- a/arch/arm/mach-msm/pm-data.c
+++ b/arch/arm/mach-msm/pm-data.c
@@ -28,6 +28,13 @@
 		.suspend_enabled = 0,
 	},
 
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_RETENTION)] = {
+		.idle_supported = 1,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
 	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
 		.idle_supported = 1,
 		.suspend_supported = 1,
@@ -49,6 +56,13 @@
 		.suspend_enabled = 0,
 	},
 
+	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_RETENTION)] = {
+		.idle_supported = 1,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
 	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
 		.idle_supported = 1,
 		.suspend_supported = 0,
@@ -70,6 +84,13 @@
 		.suspend_enabled = 0,
 	},
 
+	[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_RETENTION)] = {
+		.idle_supported = 1,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
 	[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
 		.idle_supported = 1,
 		.suspend_supported = 0,
@@ -91,6 +112,13 @@
 		.suspend_enabled = 0,
 	},
 
+	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_RETENTION)] = {
+		.idle_supported = 1,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
 	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
 		.idle_supported = 1,
 		.suspend_supported = 0,
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index 7ef3c34..09494a0 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -44,13 +44,14 @@
 };
 
 enum msm_pm_sleep_mode {
-	MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND,
-	MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
-	MSM_PM_SLEEP_MODE_APPS_SLEEP,
-	MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT,
-	MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
-	MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN,
-	MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE,
+	MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT = 0,
+	MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT = 1,
+	MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE = 2,
+	MSM_PM_SLEEP_MODE_POWER_COLLAPSE = 3,
+	MSM_PM_SLEEP_MODE_APPS_SLEEP = 4,
+	MSM_PM_SLEEP_MODE_RETENTION = MSM_PM_SLEEP_MODE_APPS_SLEEP,
+	MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND = 5,
+	MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN = 6,
 	MSM_PM_SLEEP_MODE_NR
 };
 
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index 4518d7c..4f3c7e4 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -1192,7 +1192,7 @@
 #endif
 
 #ifdef CONFIG_CACHE_L2X0
-	l2cc_suspend();
+	l2x0_suspend();
 #endif
 
 	collapsed = msm_pm_collapse();
@@ -1217,7 +1217,7 @@
 	}
 
 #ifdef CONFIG_CACHE_L2X0
-	l2cc_resume(collapsed);
+	l2x0_resume(collapsed);
 #endif
 
 	msm_pm_boot_config_after_pc(smp_processor_id());
@@ -1434,14 +1434,14 @@
 
 #ifdef CONFIG_CACHE_L2X0
 	if (!cpu_is_msm8625())
-		l2cc_suspend();
+		l2x0_suspend();
 #endif
 
 	collapsed = msm_pm_collapse();
 
 #ifdef CONFIG_CACHE_L2X0
 	if (!cpu_is_msm8625())
-		l2cc_resume(collapsed);
+		l2x0_resume(collapsed);
 #endif
 
 	msm_pm_boot_config_after_pc(smp_processor_id());
diff --git a/arch/arm/mach-msm/qdsp6v2/amrwb_in.c b/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
index 1dd90a7..5df976d 100644
--- a/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
+++ b/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* 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
@@ -201,8 +201,8 @@
 	audio->enc_cfg = kzalloc(sizeof(struct msm_audio_amrwb_enc_config),
 				GFP_KERNEL);
 	if (audio->enc_cfg == NULL) {
-		pr_err("%s: Could not allocate memory for amrwb"
-			"config param\n", __func__);
+		pr_err("%s:session id %d: Could not allocate memory for amrwb"
+			"config param\n", __func__, audio->ac->session);
 		kfree(audio);
 		return -ENOMEM;
 	}
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_aac.c b/arch/arm/mach-msm/qdsp6v2/audio_aac.c
index 438909a..88189f6 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_aac.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_aac.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -274,10 +274,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_aac_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c b/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c
index 9618adb..6768f7a 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -138,10 +138,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_amrnb_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c b/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c
index a15ab28..f95e191 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -140,10 +140,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_amrwb_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_evrc.c b/arch/arm/mach-msm/qdsp6v2/audio_evrc.c
index 5a511c9..12c815d 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_evrc.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -144,10 +144,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_evrc_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_mp3.c b/arch/arm/mach-msm/qdsp6v2/audio_mp3.c
index eff41cc..22552c6 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_mp3.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -141,10 +141,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_mp3_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c b/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
index 0f6b5a6..ee32b80 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -275,10 +275,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_multi_aac_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c b/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c
index 8343beb..7b72c97 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -150,10 +150,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_qcelp_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index 48e0135..644df2d 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -946,8 +946,15 @@
 
 	ac = audio->ac;
 	/* Offset with  appropriate meta */
-	param.paddr = buf_node->paddr + sizeof(struct dec_meta_in);
-	param.len = buf_node->buf.data_len - sizeof(struct dec_meta_in);
+	if (audio->feedback) {
+		/* Non Tunnel mode */
+		param.paddr = buf_node->paddr + sizeof(struct dec_meta_in);
+		param.len = buf_node->buf.data_len - sizeof(struct dec_meta_in);
+	} else {
+		/* Tunnel mode */
+		param.paddr = buf_node->paddr;
+		param.len = buf_node->buf.data_len;
+	}
 	param.msw_ts = buf_node->meta_info.meta_in.ntimestamp.highpart;
 	param.lsw_ts = buf_node->meta_info.meta_in.ntimestamp.lowpart;
 	/* If no meta_info enaled, indicate no time stamp valid */
@@ -1181,19 +1188,21 @@
 	file->private_data = audio;
 	audio->codec_ioctl = audio_aio_ioctl;
 
-	e_node = kmalloc(sizeof(struct audio_aio_event) * AUDIO_EVENT_NUM,
-			GFP_KERNEL);
-	if (e_node) {
-		for (i = 0; i < AUDIO_EVENT_NUM; i++)
-			list_add_tail(&e_node[i].list,
-				&audio->free_event_queue);
-	} else {
-		pr_err("%s[%p]:event pkt alloc failed\n",
-			__func__, audio);
-		rc = -ENOMEM;
-		goto fail;
+	for (i = 0; i < AUDIO_EVENT_NUM; i++) {
+		e_node = kmalloc(sizeof(struct audio_aio_event), GFP_KERNEL);
+		if (e_node)
+			list_add_tail(&e_node->list, &audio->free_event_queue);
+		else {
+			pr_err("%s[%p]:event pkt alloc failed\n",
+				__func__, audio);
+			break;
+		}
 	}
+	return 0;
 fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->codec_cfg);
+	kfree(audio);
 	return rc;
 }
 
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_wma.c b/arch/arm/mach-msm/qdsp6v2/audio_wma.c
index 62d4393..bea0485 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_wma.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_wma.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -185,10 +185,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_wma_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c b/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c
index a83fce9..98d1b30 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -245,10 +245,6 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
-	if (IS_ERR_VALUE(rc)) {
-		pr_err("%s: audio_aio_open failed\n", __func__);
-		goto fail;
-	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_wmapro_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/q6core.c b/arch/arm/mach-msm/qdsp6v2/q6core.c
index bfd4c48..edb1e7d 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6core.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-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
@@ -249,6 +249,8 @@
 	int len;
 	static int t_len;
 
+	if (count < 0)
+		return 0;
 	len = count > 63 ? 63 : count;
 	if (copy_from_user(l_buf + 20 , buf, len)) {
 		pr_info("Unable to copy data from user space\n");
diff --git a/arch/arm/mach-msm/qdsp6v2/rtac.c b/arch/arm/mach-msm/qdsp6v2/rtac.c
index 4fd20d0..4ce9b030 100644
--- a/arch/arm/mach-msm/qdsp6v2/rtac.c
+++ b/arch/arm/mach-msm/qdsp6v2/rtac.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* 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
@@ -443,6 +443,7 @@
 
 
 	if (payload_size > MAX_PAYLOAD_SIZE) {
+
 			pr_err("%s: Invalid payload size = %d\n",
 				__func__, payload_size);
 		goto done;
@@ -487,11 +488,11 @@
 		payload_size);
 	adm_params.src_svc = APR_SVC_ADM;
 	adm_params.src_domain = APR_DOMAIN_APPS;
-	adm_params.src_port = port_index;
+	adm_params.src_port = copp_id;
 	adm_params.dest_svc = APR_SVC_ADM;
 	adm_params.dest_domain = APR_DOMAIN_ADSP;
 	adm_params.dest_port = copp_id;
-	adm_params.token = port_index;
+	adm_params.token = copp_id;
 	adm_params.opcode = opcode;
 
 	memcpy(rtac_adm_buffer, &adm_params, sizeof(adm_params));
@@ -613,6 +614,7 @@
 	}
 
 	if (payload_size > MAX_PAYLOAD_SIZE) {
+
 			pr_err("%s: Invalid payload size = %d\n",
 				__func__, payload_size);
 		goto done;
@@ -623,15 +625,17 @@
 			__func__);
 		goto done;
 	}
-	if (session_id > SESSION_MAX) {
+	if (session_id > (SESSION_MAX + 1)) {
 		pr_err("%s: Invalid Session = %d\n", __func__, session_id);
 		goto done;
 	}
 
 	mutex_lock(&rtac_asm_apr_mutex);
-	if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
-		pr_err("%s: APR not initialized\n", __func__);
-		goto err;
+	if (session_id < SESSION_MAX+1) {
+		if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
+			pr_err("%s: APR not initialized\n", __func__);
+			goto err;
+		}
 	}
 
 	/* Set globals for copy of returned payload */
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index c1e4118..6b42325 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -354,6 +354,7 @@
 static void smd_fake_irq_handler(unsigned long arg);
 static void smsm_cb_snapshot(uint32_t use_wakelock);
 
+static struct workqueue_struct *smsm_cb_wq;
 static void notify_smsm_cb_clients_worker(struct work_struct *work);
 static DECLARE_WORK(smsm_cb_work, notify_smsm_cb_clients_worker);
 static DEFINE_MUTEX(smsm_lock);
@@ -2365,6 +2366,13 @@
 		return -ENOMEM;
 	}
 
+	smsm_cb_wq = create_singlethread_workqueue("smsm_cb_wq");
+	if (!smsm_cb_wq) {
+		pr_err("%s: smsm_cb_wq creation failed\n", __func__);
+		kfree(smsm_states);
+		return -EFAULT;
+	}
+
 	mutex_lock(&smsm_lock);
 	for (n = 0; n < SMSM_NUM_ENTRIES; n++) {
 		state_info = &smsm_states[n];
@@ -2540,7 +2548,7 @@
 		goto restore_snapshot_count;
 	}
 
-	schedule_work(&smsm_cb_work);
+	queue_work(smsm_cb_wq, &smsm_cb_work);
 	return;
 
 restore_snapshot_count:
@@ -2832,7 +2840,6 @@
 				state_info->last_value = new_state;
 			}
 		}
-		mutex_unlock(&smsm_lock);
 
 		/* read wakelock flag */
 		ret = kfifo_out(&smsm_snapshot_fifo, &use_wakelock,
@@ -2840,8 +2847,10 @@
 		if (ret != sizeof(use_wakelock)) {
 			pr_err("%s: snapshot underflow %d\n",
 				__func__, ret);
+			mutex_unlock(&smsm_lock);
 			return;
 		}
+		mutex_unlock(&smsm_lock);
 
 		if (use_wakelock) {
 			spin_lock_irqsave(&smsm_snapshot_count_lock, flags);
diff --git a/arch/arm/mach-msm/subsystem_map.c b/arch/arm/mach-msm/subsystem_map.c
index b5ff244..d6a17e6 100644
--- a/arch/arm/mach-msm/subsystem_map.c
+++ b/arch/arm/mach-msm/subsystem_map.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -34,6 +34,15 @@
 static struct rb_root phys_root;
 DEFINE_MUTEX(msm_buffer_mutex);
 
+static unsigned long subsystem_to_domain_tbl[] = {
+	VIDEO_DOMAIN,
+	VIDEO_DOMAIN,
+	CAMERA_DOMAIN,
+	DISPLAY_DOMAIN,
+	ROTATOR_DOMAIN,
+	0xFFFFFFFF
+};
+
 static struct msm_buffer_node *find_buffer(void *key)
 {
 	struct rb_root *root = &buffer_root;
@@ -208,6 +217,31 @@
 	return 0;
 }
 
+static unsigned long msm_subsystem_get_domain_no(int subsys_id)
+{
+	if (subsys_id > INVALID_SUBSYS_ID && subsys_id <= MAX_SUBSYSTEM_ID &&
+	    subsys_id < ARRAY_SIZE(subsystem_to_domain_tbl))
+		return subsystem_to_domain_tbl[subsys_id];
+	else
+		return subsystem_to_domain_tbl[MAX_SUBSYSTEM_ID];
+}
+
+static unsigned long msm_subsystem_get_partition_no(int subsys_id)
+{
+	switch (subsys_id) {
+	case MSM_SUBSYSTEM_VIDEO_FWARE:
+		return VIDEO_FIRMWARE_POOL;
+	case MSM_SUBSYSTEM_VIDEO:
+		return VIDEO_MAIN_POOL;
+	case MSM_SUBSYSTEM_CAMERA:
+	case MSM_SUBSYSTEM_DISPLAY:
+	case MSM_SUBSYSTEM_ROTATOR:
+		return GEN_POOL;
+	default:
+		return 0xFFFFFFFF;
+	}
+}
+
 phys_addr_t msm_subsystem_check_iova_mapping(int subsys_id, unsigned long iova)
 {
 	struct iommu_domain *subsys_domain;
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index bc4bd21..027aa5b 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -48,8 +48,8 @@
 struct restart_wq_data {
 	struct subsys_data *subsys;
 	struct wake_lock ssr_wake_lock;
-	char wakelockname[64];
-	int coupled;
+	char wlname[64];
+	int use_restart_order;
 	struct work_struct work;
 };
 
@@ -120,26 +120,6 @@
 }
 EXPORT_SYMBOL(get_restart_level);
 
-static void restart_level_changed(void)
-{
-	struct subsys_data *subsys;
-
-	if (cpu_is_msm8x60() && restart_level == RESET_SUBSYS_COUPLED) {
-		restart_orders = orders_8x60_all;
-		n_restart_orders = ARRAY_SIZE(orders_8x60_all);
-	}
-
-	if (cpu_is_msm8x60() && restart_level == RESET_SUBSYS_MIXED) {
-		restart_orders = orders_8x60_modems;
-		n_restart_orders = ARRAY_SIZE(orders_8x60_modems);
-	}
-
-	mutex_lock(&subsystem_list_lock);
-	list_for_each_entry(subsys, &subsystem_list, list)
-		subsys->restart_order = _update_restart_order(subsys);
-	mutex_unlock(&subsystem_list_lock);
-}
-
 static int restart_level_set(const char *val, struct kernel_param *kp)
 {
 	int ret;
@@ -162,20 +142,12 @@
 		pr_info("Phase %d behavior activated.\n", restart_level);
 	break;
 
-	case RESET_SUBSYS_MIXED:
-		pr_info("Phase 2+ behavior activated.\n");
-	break;
-
 	default:
 		restart_level = old_val;
 		return -EINVAL;
 	break;
 
 	}
-
-	if (restart_level != old_val)
-		restart_level_changed();
-
 	return 0;
 }
 
@@ -317,7 +289,7 @@
 	int i;
 	int restart_list_count = 0;
 
-	if (r_work->coupled)
+	if (r_work->use_restart_order)
 		soc_restart_order = subsys->restart_order;
 
 	/* It's OK to not take the registration lock at this point.
@@ -441,11 +413,38 @@
 	kfree(r_work);
 }
 
+static void __subsystem_restart(struct subsys_data *subsys)
+{
+	struct restart_wq_data *data = NULL;
+	int rc;
+
+	pr_debug("Restarting %s [level=%d]!\n", subsys->name,
+				restart_level);
+
+	data = kzalloc(sizeof(struct restart_wq_data), GFP_ATOMIC);
+	if (!data)
+		panic("%s: Unable to allocate memory to restart %s.",
+		      __func__, subsys->name);
+
+	data->subsys = subsys;
+
+	if (restart_level != RESET_SUBSYS_INDEPENDENT)
+		data->use_restart_order = 1;
+
+	snprintf(data->wlname, sizeof(data->wlname), "ssr(%s)", subsys->name);
+	wake_lock_init(&data->ssr_wake_lock, WAKE_LOCK_SUSPEND, data->wlname);
+	wake_lock(&data->ssr_wake_lock);
+
+	INIT_WORK(&data->work, subsystem_restart_wq_func);
+	rc = queue_work(ssr_wq, &data->work);
+	if (rc < 0)
+		panic("%s: Unable to schedule work to restart %s (%d).",
+		     __func__, subsys->name, rc);
+}
+
 int subsystem_restart(const char *subsys_name)
 {
 	struct subsys_data *subsys;
-	struct restart_wq_data *data = NULL;
-	int rc;
 
 	if (!subsys_name) {
 		pr_err("Invalid subsystem name.\n");
@@ -465,42 +464,11 @@
 		return -EINVAL;
 	}
 
-	if (restart_level != RESET_SOC) {
-		data = kzalloc(sizeof(struct restart_wq_data), GFP_KERNEL);
-		if (!data) {
-			restart_level = RESET_SOC;
-			pr_warn("Failed to alloc restart data. Resetting.\n");
-		} else {
-			if (restart_level == RESET_SUBSYS_COUPLED ||
-					restart_level == RESET_SUBSYS_MIXED)
-				data->coupled = 1;
-			else
-				data->coupled = 0;
-
-			data->subsys = subsys;
-		}
-	}
-
 	switch (restart_level) {
 
 	case RESET_SUBSYS_COUPLED:
-	case RESET_SUBSYS_MIXED:
 	case RESET_SUBSYS_INDEPENDENT:
-		pr_debug("Restarting %s [level=%d]!\n", subsys_name,
-				restart_level);
-
-		snprintf(data->wakelockname, sizeof(data->wakelockname),
-				"ssr(%s)", subsys_name);
-		wake_lock_init(&data->ssr_wake_lock, WAKE_LOCK_SUSPEND,
-			data->wakelockname);
-		wake_lock(&data->ssr_wake_lock);
-
-		INIT_WORK(&data->work, subsystem_restart_wq_func);
-		rc = schedule_work(&data->work);
-
-		if (rc < 0)
-			panic("%s: Unable to schedule work to restart %s",
-			     __func__, subsys->name);
+		__subsystem_restart(subsys);
 		break;
 
 	case RESET_SOC:
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index dee5479..db2a9b4 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -30,6 +30,8 @@
 #define CACHE_LINE_SIZE		32
 
 static void __iomem *l2x0_base;
+static uint32_t aux_ctrl_save;
+static uint32_t data_latency_ctrl;
 static DEFINE_RAW_SPINLOCK(l2x0_lock);
 
 static uint32_t l2x0_way_mask;	/* Bitmask of active ways */
@@ -447,6 +449,51 @@
 			ways, cache_id, aux, l2x0_size);
 }
 
+void l2x0_suspend(void)
+{
+	/* Save aux control register value */
+	aux_ctrl_save = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
+	data_latency_ctrl = readl_relaxed(l2x0_base + L2X0_DATA_LATENCY_CTRL);
+	/* Flush all cache */
+	l2x0_flush_all();
+	/* Disable the cache */
+	writel_relaxed(0, l2x0_base + L2X0_CTRL);
+
+	/* Memory barrier */
+	dmb();
+}
+
+void l2x0_resume(int collapsed)
+{
+	if (collapsed) {
+		/* Disable the cache */
+		writel_relaxed(0, l2x0_base + L2X0_CTRL);
+
+		/* Restore aux control register value */
+		writel_relaxed(aux_ctrl_save, l2x0_base + L2X0_AUX_CTRL);
+		writel_relaxed(data_latency_ctrl, l2x0_base +
+				L2X0_DATA_LATENCY_CTRL);
+
+		/* Invalidate the cache */
+		l2x0_inv_all();
+		/*
+		 * TBD: make sure that l2xo_inv_all finished
+		 * before actually enabling the cache. Logically this
+		 * is not required as cache sync is atomic operation.
+		 * but on 8x25, observed the random crashes and they go
+		 * away if we add dmb or disable the L2.
+		 * keeping this as temporary workaround until root
+		 * cause is find out.
+		 */
+		dmb();
+	}
+
+	/* Enable the cache */
+	writel_relaxed(1, l2x0_base + L2X0_CTRL);
+
+	mb();
+}
+
 #ifdef CONFIG_OF
 static void __init l2x0_of_setup(const struct device_node *np,
 				 u32 *aux_val, u32 *aux_mask)
@@ -515,9 +562,8 @@
 			       l2x0_base + L2X0_ADDR_FILTER_START);
 	}
 }
-#endif
 
-static void __init pl310_save(void)
+static void pl310_save(void)
 {
 	u32 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
 		L2X0_CACHE_ID_RTL_MASK;
@@ -591,7 +637,6 @@
 	l2x0_resume();
 }
 
-#ifdef CONFIG_OF
 static const struct l2x0_of_data pl310_data = {
 	pl310_of_setup,
 	pl310_save,
@@ -647,17 +692,3 @@
 	return 0;
 }
 #endif
-
-void l2cc_suspend(void)
-{
-	pl310_save();
-	l2x0_disable();
-	dmb();
-}
-
-void l2cc_resume(int collapsed)
-{
-	if (collapsed)
-		pl310_resume();
-	dmb();
-}
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index d547121..656223b 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -262,8 +262,8 @@
 	int hsic_device_opened;
 	int hsic_suspend;
 	int read_len_mdm;
-	int in_busy_hsic_read_on_mdm;
-	int in_busy_hsic_write_on_mdm;
+	int in_busy_hsic_read_on_device;
+	int in_busy_hsic_write_on_device;
 	int in_busy_hsic_write;
 	int in_busy_hsic_read;
 	int usb_mdm_connected;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 0a156de..34640c3 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -233,6 +233,10 @@
 	if (driver->logging_process_id == current->tgid) {
 		driver->logging_mode = USB_MODE;
 		diagfwd_connect();
+#ifdef CONFIG_DIAG_HSIC_PIPE
+		diagfwd_cancel_hsic();
+		diagfwd_connect_hsic(0);
+#endif
 	}
 #endif /* DIAG over USB */
 	/* Delete the pkt response table entry for the exiting process */
@@ -476,6 +480,9 @@
 #ifdef CONFIG_DIAG_SDIO_PIPE
 			driver->in_busy_sdio = 1;
 #endif
+#ifdef CONFIG_DIAG_HSIC_PIPE
+			diagfwd_disconnect_hsic(0);
+#endif
 		} else if (temp == NO_LOGGING_MODE && driver->logging_mode
 							== MEMORY_DEVICE_MODE) {
 			driver->in_busy_1 = 0;
@@ -501,15 +508,24 @@
 				queue_work(driver->diag_sdio_wq,
 					&(driver->diag_read_sdio_work));
 #endif
+#ifdef CONFIG_DIAG_HSIC_PIPE
+			diagfwd_connect_hsic(0);
+#endif
 		}
 #ifdef CONFIG_DIAG_OVER_USB
 		else if (temp == USB_MODE && driver->logging_mode
-							 == NO_LOGGING_MODE)
+							 == NO_LOGGING_MODE) {
 			diagfwd_disconnect();
-		else if (temp == NO_LOGGING_MODE && driver->logging_mode
-								== USB_MODE)
+#ifdef CONFIG_DIAG_HSIC_PIPE
+			diagfwd_disconnect_hsic(0);
+#endif
+		} else if (temp == NO_LOGGING_MODE && driver->logging_mode
+								== USB_MODE) {
 			diagfwd_connect();
-		else if (temp == USB_MODE && driver->logging_mode
+#ifdef CONFIG_DIAG_HSIC_PIPE
+			diagfwd_connect_hsic(0);
+#endif
+		} else if (temp == USB_MODE && driver->logging_mode
 							== MEMORY_DEVICE_MODE) {
 			diagfwd_disconnect();
 			driver->in_busy_1 = 0;
@@ -535,9 +551,18 @@
 				queue_work(driver->diag_sdio_wq,
 					&(driver->diag_read_sdio_work));
 #endif
-			} else if (temp == MEMORY_DEVICE_MODE &&
-					 driver->logging_mode == USB_MODE)
-				diagfwd_connect();
+#ifdef CONFIG_DIAG_HSIC_PIPE
+			diagfwd_cancel_hsic();
+			diagfwd_connect_hsic(0);
+#endif
+		} else if (temp == MEMORY_DEVICE_MODE &&
+				 driver->logging_mode == USB_MODE) {
+			diagfwd_connect();
+#ifdef CONFIG_DIAG_HSIC_PIPE
+			diagfwd_cancel_hsic();
+			diagfwd_connect_hsic(0);
+#endif
+		}
 #endif /* DIAG over USB */
 		success = 1;
 	}
@@ -565,6 +590,7 @@
 
 	if ((driver->data_ready[index] & USER_SPACE_LOG_TYPE) && (driver->
 					logging_mode == MEMORY_DEVICE_MODE)) {
+		pr_debug("diag: process woken up\n");
 		/*Copy the type of data being passed*/
 		data_type = driver->data_ready[index] & USER_SPACE_LOG_TYPE;
 		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
@@ -693,6 +719,23 @@
 			driver->in_busy_sdio = 0;
 		}
 #endif
+#ifdef CONFIG_DIAG_HSIC_PIPE
+		pr_debug("diag: Copy data to user space %d\n",
+			 driver->in_busy_hsic_write_on_device);
+		if (driver->in_busy_hsic_write_on_device == 1) {
+			num_data++;
+			/*Copy the length of data being passed*/
+			COPY_USER_SPACE_OR_EXIT(buf+ret,
+				 (driver->write_ptr_mdm->length), 4);
+			/*Copy the actual data being passed*/
+			COPY_USER_SPACE_OR_EXIT(buf+ret,
+					*(driver->buf_in_hsic),
+					 driver->write_ptr_mdm->length);
+			pr_debug("diag: data copied\n");
+			/* call the write complete function */
+			diagfwd_write_complete_hsic();
+		}
+#endif
 		/* copy number of data fields */
 		COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4);
 		ret -= 4;
@@ -854,7 +897,32 @@
 			}
 		}
 #endif
-		/* send masks to modem now */
+#ifdef CONFIG_DIAG_HSIC_PIPE
+		/* send masks to 9k too */
+		if (driver->hsic_ch && (payload_size > 0)) {
+			/* wait sending mask updates if HSIC ch not ready */
+			if (driver->in_busy_hsic_write)
+				wait_event_interruptible(driver->wait_q,
+					(driver->in_busy_hsic_write != 1));
+			driver->in_busy_hsic_write = 1;
+			driver->in_busy_hsic_read_on_device = 0;
+			err = diag_bridge_write(driver->user_space_data,
+							 payload_size);
+			if (err) {
+				pr_err("diag: err sending mask to MDM: %d\n",
+									 err);
+				/*
+				* If the error is recoverable, then clear
+				* the write flag, so we will resubmit a
+				* write on the next frame.  Otherwise, don't
+				* resubmit a write on the next frame.
+				*/
+				if ((-ESHUTDOWN) != err)
+					driver->in_busy_hsic_write = 0;
+			}
+		}
+#endif
+		/* send masks to 8k now */
 		diag_process_hdlc((void *)(driver->user_space_data),
 							 payload_size);
 		return 0;
@@ -1181,6 +1249,7 @@
 			diag_read_smd_wcnss_cntl_work_fn);
 		INIT_WORK(&(driver->diag_read_smd_dci_work),
 						 diag_read_smd_dci_work_fn);
+		diag_debugfs_init();
 		diagfwd_init();
 		diagfwd_cntl_init();
 		driver->dci_state = diag_dci_init();
@@ -1214,6 +1283,7 @@
 	return 0;
 
 fail:
+	diag_debugfs_cleanup();
 	diagchar_cleanup();
 	diagfwd_exit();
 	diagfwd_cntl_exit();
@@ -1232,6 +1302,7 @@
 	diagfwd_cntl_exit();
 	diag_sdio_fn(EXIT);
 	diag_hsic_fn(EXIT);
+	diag_debugfs_cleanup();
 	diagchar_cleanup();
 	printk(KERN_INFO "done diagchar exit\n");
 }
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 7066141..a63e344 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -183,7 +183,7 @@
 		return 0;
 }
 
-inline int chk_polling_response(void)
+int chk_polling_response(void)
 {
 	if (!(driver->polling_reg_flag) && chk_apps_master())
 		/*
@@ -273,6 +273,7 @@
 				break;
 		if (i < driver->num_clients) {
 			driver->data_ready[i] |= USER_SPACE_LOG_TYPE;
+			pr_debug("diag: wake up logging process\n");
 			wake_up_interruptible(&driver->wait_q);
 		} else
 			return -EINVAL;
@@ -300,6 +301,15 @@
 				&(driver->diag_read_sdio_work));
 		}
 #endif
+#ifdef CONFIG_DIAG_HSIC_PIPE
+		else if (proc_num == HSIC_DATA) {
+			driver->in_busy_hsic_read = 0;
+			driver->in_busy_hsic_write_on_device = 0;
+			if (driver->hsic_ch)
+				queue_work(driver->diag_hsic_wq,
+					&(driver->diag_read_hsic_work));
+		}
+#endif
 		err = -1;
 	}
 #ifdef CONFIG_DIAG_OVER_USB
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index 0780a8e..f5de2ac 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -27,7 +27,10 @@
 int diag_device_write(void *, int, struct diag_request *);
 int mask_request_validate(unsigned char mask_buf[]);
 void diag_clear_reg(int);
+int chk_config_get_id(void);
 int chk_apps_only(void);
+int chk_apps_master(void);
+int chk_polling_response(void);
 void diag_send_event_mask_update(smd_channel_t *, int num_bytes);
 void diag_send_msg_mask_update(smd_channel_t *, int ssid_first,
 					 int ssid_last, int proc);
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 171168f..8efe10b 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -16,6 +16,9 @@
 #include "diagchar.h"
 #include "diagfwd.h"
 #include "diagfwd_cntl.h"
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#endif
 
 #define HDR_SIZ 8
 
@@ -317,3 +320,281 @@
 	kfree(driver->buf_in_qdsp_cntl);
 	kfree(driver->buf_in_wcnss_cntl);
 }
+
+#ifdef CONFIG_DEBUG_FS
+#define DEBUG_BUF_SIZE	4096
+static struct dentry *diag_dbgfs_dent;
+static int diag_dbgfs_table_index;
+
+static ssize_t diag_dbgfs_read_status(struct file *file, char __user *ubuf,
+				      size_t count, loff_t *ppos)
+{
+	char *buf;
+	int ret;
+
+	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+	if (!buf) {
+		pr_err("diag: %s, Error allocating memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	ret = scnprintf(buf, DEBUG_BUF_SIZE,
+		"modem ch: 0x%x\n"
+		"lpass ch: 0x%x\n"
+		"riva ch: 0x%x\n"
+		"dci ch: 0x%x\n"
+		"modem cntl_ch: 0x%x\n"
+		"lpass cntl_ch: 0x%x\n"
+		"riva cntl_ch: 0x%x\n"
+		"CPU Tools id: %d\n"
+		"Apps only: %d\n"
+		"Apps master: %d\n"
+		"Check Polling Response: %d\n"
+		"polling_reg_flag: %d\n"
+		"uses device tree: %d\n"
+		"in_busy_1: %d\n"
+		"in_busy_2: %d\n"
+		"in_busy_qdsp_1: %d\n"
+		"in_busy_qdsp_2: %d\n"
+		"in_busy_wcnss_1: %d\n"
+		"in_busy_wcnss_2: %d\n"
+		"in_busy_dci: %d\n",
+		(unsigned int)driver->ch,
+		(unsigned int)driver->chqdsp,
+		(unsigned int)driver->ch_wcnss,
+		(unsigned int)driver->ch_dci,
+		(unsigned int)driver->ch_cntl,
+		(unsigned int)driver->chqdsp_cntl,
+		(unsigned int)driver->ch_wcnss_cntl,
+		chk_config_get_id(),
+		chk_apps_only(),
+		chk_apps_master(),
+		chk_polling_response(),
+		driver->polling_reg_flag,
+		driver->use_device_tree,
+		driver->in_busy_1,
+		driver->in_busy_2,
+		driver->in_busy_qdsp_1,
+		driver->in_busy_qdsp_2,
+		driver->in_busy_wcnss_1,
+		driver->in_busy_wcnss_2,
+		driver->in_busy_dci);
+
+#ifdef CONFIG_DIAG_OVER_USB
+	ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
+		"usb_connected: %d\n",
+		driver->usb_connected);
+#endif
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t diag_dbgfs_read_workpending(struct file *file,
+				char __user *ubuf, size_t count, loff_t *ppos)
+{
+	char *buf;
+	int ret;
+
+	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+	if (!buf) {
+		pr_err("diag: %s, Error allocating memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	ret = scnprintf(buf, DEBUG_BUF_SIZE,
+		"Pending status for work_stucts:\n"
+		"diag_drain_work: %d\n"
+		"diag_read_smd_work: %d\n"
+		"diag_read_smd_cntl_work: %d\n"
+		"diag_read_smd_qdsp_work: %d\n"
+		"diag_read_smd_qdsp_cntl_work: %d\n"
+		"diag_read_smd_wcnss_work: %d\n"
+		"diag_read_smd_wcnss_cntl_work: %d\n"
+		"diag_modem_mask_update_work: %d\n"
+		"diag_qdsp_mask_update_work: %d\n"
+		"diag_wcnss_mask_update_work: %d\n"
+		"diag_read_smd_dci_work: %d\n",
+		work_pending(&(driver->diag_drain_work)),
+		work_pending(&(driver->diag_read_smd_work)),
+		work_pending(&(driver->diag_read_smd_cntl_work)),
+		work_pending(&(driver->diag_read_smd_qdsp_work)),
+		work_pending(&(driver->diag_read_smd_qdsp_cntl_work)),
+		work_pending(&(driver->diag_read_smd_wcnss_work)),
+		work_pending(&(driver->diag_read_smd_wcnss_cntl_work)),
+		work_pending(&(driver->diag_modem_mask_update_work)),
+		work_pending(&(driver->diag_qdsp_mask_update_work)),
+		work_pending(&(driver->diag_wcnss_mask_update_work)),
+		work_pending(&(driver->diag_read_smd_dci_work)));
+
+#ifdef CONFIG_DIAG_OVER_USB
+	ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
+		"diag_proc_hdlc_work: %d\n"
+		"diag_read_work: %d\n",
+		work_pending(&(driver->diag_proc_hdlc_work)),
+		work_pending(&(driver->diag_read_work)));
+#endif
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf,
+				     size_t count, loff_t *ppos)
+{
+	char *buf;
+	int ret = 0;
+	int i;
+	int bytes_remaining;
+	int bytes_in_buffer = 0;
+	int bytes_written;
+	int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count;
+
+	if (diag_dbgfs_table_index >= diag_max_reg) {
+		/* Done. Reset to prepare for future requests */
+		diag_dbgfs_table_index = 0;
+		return 0;
+	}
+
+	buf = kzalloc(sizeof(char) * buf_size, GFP_KERNEL);
+	if (!buf) {
+		pr_err("diag: %s, Error allocating memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	bytes_remaining = buf_size;
+	for (i = diag_dbgfs_table_index; i < diag_max_reg; i++) {
+		/* Do not process empty entries in the table */
+		if (driver->table[i].process_id == 0)
+			continue;
+
+		bytes_written = scnprintf(buf+bytes_in_buffer, bytes_remaining,
+			"i: %3d, cmd_code: %4x, subsys_id: %4x, "
+			"client: %2d, cmd_code_lo: %4x, "
+			"cmd_code_hi: %4x, process_id: %5d\n",
+			i,
+			driver->table[i].cmd_code,
+			driver->table[i].subsys_id,
+			driver->table[i].client_id,
+			driver->table[i].cmd_code_lo,
+			driver->table[i].cmd_code_hi,
+			driver->table[i].process_id);
+
+		bytes_in_buffer += bytes_written;
+
+		/* Check if there is room to add another table entry */
+		bytes_remaining = buf_size - bytes_in_buffer;
+		if (bytes_remaining < bytes_written)
+			break;
+	}
+	diag_dbgfs_table_index = i;
+
+	*ppos = 0;
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, bytes_in_buffer);
+
+	kfree(buf);
+	return ret;
+}
+
+#ifdef CONFIG_DIAG_HSIC_PIPE
+static ssize_t diag_dbgfs_read_hsic(struct file *file, char __user *ubuf,
+				    size_t count, loff_t *ppos)
+{
+	char *buf;
+	int ret;
+
+	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+	if (!buf) {
+		pr_err("diag: %s, Error allocating memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	ret = scnprintf(buf, DEBUG_BUF_SIZE,
+		"hsic initialized: %d\n"
+		"hsic ch: %d\n"
+		"hsic enabled: %d\n"
+		"hsic_opened: %d\n"
+		"hisc_suspend: %d\n"
+		"in_busy_hsic_read_on_mdm: %d\n"
+		"in_busy_hsic_write_on_mdm: %d\n"
+		"in_busy_hsic_write: %d\n"
+		"in_busy_hsic_read: %d\n"
+		"usb_mdm_connected: %d\n"
+		"diag_read_mdm_work: %d\n"
+		"diag_read_hsic_work: %d\n"
+		"diag_disconnect_work: %d\n"
+		"diag_usb_read_complete_work: %d\n",
+		driver->hsic_initialized,
+		driver->hsic_ch,
+		driver->hsic_device_enabled,
+		driver->hsic_device_opened,
+		driver->hsic_suspend,
+		driver->in_busy_hsic_read_on_device,
+		driver->in_busy_hsic_write_on_device,
+		driver->in_busy_hsic_write,
+		driver->in_busy_hsic_read,
+		driver->usb_mdm_connected,
+		work_pending(&(driver->diag_read_mdm_work)),
+		work_pending(&(driver->diag_read_hsic_work)),
+		work_pending(&(driver->diag_disconnect_work)),
+		work_pending(&(driver->diag_usb_read_complete_work)));
+
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+
+	kfree(buf);
+	return ret;
+}
+
+const struct file_operations diag_dbgfs_hsic_ops = {
+	.read = diag_dbgfs_read_hsic,
+};
+#endif
+
+const struct file_operations diag_dbgfs_status_ops = {
+	.read = diag_dbgfs_read_status,
+};
+
+const struct file_operations diag_dbgfs_table_ops = {
+	.read = diag_dbgfs_read_table,
+};
+
+const struct file_operations diag_dbgfs_workpending_ops = {
+	.read = diag_dbgfs_read_workpending,
+};
+
+void diag_debugfs_init(void)
+{
+	diag_dbgfs_dent = debugfs_create_dir("diag", 0);
+	if (IS_ERR(diag_dbgfs_dent))
+		return;
+
+	debugfs_create_file("status", 0444, diag_dbgfs_dent, 0,
+		&diag_dbgfs_status_ops);
+
+	debugfs_create_file("table", 0444, diag_dbgfs_dent, 0,
+		&diag_dbgfs_table_ops);
+
+	debugfs_create_file("work_pending", 0444, diag_dbgfs_dent, 0,
+		&diag_dbgfs_workpending_ops);
+
+#ifdef CONFIG_DIAG_HSIC_PIPE
+	debugfs_create_file("hsic", 0444, diag_dbgfs_dent, 0,
+		&diag_dbgfs_hsic_ops);
+#endif
+
+	diag_dbgfs_table_index = 0;
+}
+
+void diag_debugfs_cleanup(void)
+{
+	if (diag_dbgfs_dent) {
+		debugfs_remove_recursive(diag_dbgfs_dent);
+		diag_dbgfs_dent = NULL;
+	}
+}
+#else
+void diag_debugfs_init(void) { }
+void diag_debugfs_cleanup(void) { }
+#endif
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index ad1fec9..743ddc1 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -86,4 +86,7 @@
 void diag_smd_qdsp_cntl_notify(void *ctxt, unsigned event);
 void diag_smd_wcnss_cntl_notify(void *ctxt, unsigned event);
 
+void diag_debugfs_init(void);
+void diag_debugfs_cleanup(void);
+
 #endif
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index b2080b3..a3c6f26 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -36,11 +36,11 @@
 		return;
 	}
 
-	/*
-	 * If there is no hsic data being read from the hsic and there
-	 * is no hsic data being written to the usb mdm channel
+	/* If there is no hsic data being read from the hsic and there
+	 * is no hsic data being written to the device
 	 */
-	if (!driver->in_busy_hsic_read && !driver->in_busy_hsic_write_on_mdm) {
+	if (!driver->in_busy_hsic_read &&
+			 !driver->in_busy_hsic_write_on_device) {
 		/*
 		 * Initiate the read from the hsic.  The hsic read is
 		 * asynchronous.  Once the read is complete the read
@@ -49,6 +49,7 @@
 		int err;
 		driver->in_busy_hsic_read = 1;
 		APPEND_DEBUG('i');
+		pr_debug("diag: read from HSIC\n");
 		err = diag_bridge_read((char *)driver->buf_in_hsic,
 					IN_BUF_SIZE);
 		if (err) {
@@ -97,7 +98,8 @@
 			 * diag_bridge_read(), so buf here should be
 			 * driver->buf_in_hsic
 			 */
-			driver->in_busy_hsic_write_on_mdm = 1;
+			driver->in_busy_hsic_write_on_device = 1;
+			pr_debug("diag: write to device\n");
 			diag_device_write((void *)buf, HSIC_DATA,
 						driver->write_ptr_mdm);
 		}
@@ -109,9 +111,9 @@
 	 * If for some reason there was no hsic data to write to the
 	 * mdm channel, set up another read
 	 */
-	if (!driver->in_busy_hsic_write_on_mdm &&
-			driver->usb_mdm_connected &&
-			!driver->hsic_suspend)
+	if (!driver->in_busy_hsic_write_on_device && ((driver->logging_mode
+			== MEMORY_DEVICE_MODE) || (driver->usb_mdm_connected &&
+						    !driver->hsic_suspend)))
 		queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
 }
 
@@ -135,9 +137,14 @@
 
 static int diag_hsic_suspend(void *ctxt)
 {
+	pr_debug("diag: hsic_suspend\n");
 	if (driver->in_busy_hsic_write)
 		return -EBUSY;
 
+	/* Don't allow suspend if in MEMORY_DEVICE_MODE */
+	if (driver->logging_mode == MEMORY_DEVICE_MODE)
+		return -EBUSY;
+
 	driver->hsic_suspend = 1;
 
 	return 0;
@@ -145,9 +152,11 @@
 
 static void diag_hsic_resume(void *ctxt)
 {
+	pr_debug("diag: hsic_resume\n");
 	driver->hsic_suspend = 0;
 
-	if (!driver->in_busy_hsic_write_on_mdm && driver->usb_mdm_connected)
+	if (!driver->in_busy_hsic_write_on_device && (driver->logging_mode
+			== MEMORY_DEVICE_MODE || driver->usb_mdm_connected))
 		queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
 }
 
@@ -167,28 +176,59 @@
 			driver->hsic_device_opened = 0;
 			diag_bridge_close();
 		}
-		pr_debug("DIAG in %s: closed successfully\n", __func__);
+		pr_debug("diag: in %s: closed successfully\n", __func__);
 	} else {
-		pr_debug("DIAG in %s: already closed\n", __func__);
+		pr_debug("diag: in %s: already closed\n", __func__);
+	}
+
+	return 0;
+}
+
+/* diagfwd_cancel_hsic is called to cancel outstanding read/writes */
+int diagfwd_cancel_hsic(void)
+{
+	int err;
+
+	if (driver->hsic_device_enabled) {
+		if (driver->hsic_device_opened) {
+			driver->hsic_ch = 0;
+			driver->hsic_device_opened = 0;
+			diag_bridge_close();
+			err = diag_bridge_open(&hsic_diag_bridge_ops);
+			if (err) {
+				pr_err("DIAG: HSIC channel open error: %d\n",
+					err);
+			} else {
+				pr_debug("DIAG: opened HSIC channel\n");
+				driver->hsic_device_opened = 1;
+				driver->hsic_ch = 1;
+			}
+		}
 	}
 
 	return 0;
 }
 
 /* diagfwd_connect_hsic is called when the USB mdm channel is connected */
-static int diagfwd_connect_hsic(void)
+int diagfwd_connect_hsic(int process_cable)
 {
 	int err;
 
 	pr_debug("DIAG in %s\n", __func__);
 
-	err = usb_diag_alloc_req(driver->mdm_ch, N_MDM_WRITE, N_MDM_READ);
-	if (err)
-		pr_err("DIAG: unable to alloc USB req on mdm ch err:%d\n", err);
+	/* If the usb cable is being connected */
+	if (process_cable) {
+		err = usb_diag_alloc_req(driver->mdm_ch, N_MDM_WRITE,
+			N_MDM_READ);
+		if (err)
+			pr_err("DIAG: unable to alloc USB req on mdm"
+				" ch err:%d\n", err);
 
-	driver->usb_mdm_connected = 1;
-	driver->in_busy_hsic_write_on_mdm = 0;
-	driver->in_busy_hsic_read_on_mdm = 0;
+		driver->usb_mdm_connected = 1;
+	}
+
+	driver->in_busy_hsic_write_on_device = 0;
+	driver->in_busy_hsic_read_on_device = 0;
 	driver->in_busy_hsic_write = 0;
 	driver->in_busy_hsic_read = 0;
 
@@ -215,7 +255,9 @@
 			driver->hsic_ch = 1;
 
 		/* Poll USB mdm channel to check for data */
-		queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+		if (driver->logging_mode == USB_MODE)
+			queue_work(driver->diag_hsic_wq,
+					&driver->diag_read_mdm_work);
 
 		/* Poll HSIC channel to check for data */
 		queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
@@ -231,33 +273,38 @@
  * diagfwd_disconnect_hsic is called when the USB mdm channel
  * is disconnected
  */
-static int diagfwd_disconnect_hsic(void)
+int diagfwd_disconnect_hsic(int process_cable)
 {
 	pr_debug("DIAG in %s\n", __func__);
 
-	driver->usb_mdm_connected = 0;
-	usb_diag_free_req(driver->mdm_ch);
-	driver->in_busy_hsic_write_on_mdm = 1;
-	driver->in_busy_hsic_read_on_mdm = 1;
-	driver->in_busy_hsic_write = 1;
-	driver->in_busy_hsic_read = 1;
+	/* If the usb cable is being disconnected */
+	if (process_cable) {
+		driver->usb_mdm_connected = 0;
+		usb_diag_free_req(driver->mdm_ch);
+	}
 
-	/* Turn off communication over usb mdm and hsic */
-	return diag_hsic_close();
+	if (driver->logging_mode != MEMORY_DEVICE_MODE) {
+		driver->in_busy_hsic_write_on_device = 1;
+		driver->in_busy_hsic_read_on_device = 1;
+		driver->in_busy_hsic_write = 1;
+		driver->in_busy_hsic_read = 1;
+		/* Turn off communication over usb mdm and hsic */
+		return diag_hsic_close();
+	}
+	return 0;
 }
 
 /*
  * diagfwd_write_complete_hsic is called after the asynchronous
  * usb_diag_write() on mdm channel is complete
  */
-static int diagfwd_write_complete_hsic(void)
+int diagfwd_write_complete_hsic(void)
 {
 	/*
 	 * Clear flag to denote that the write of the hsic data on the
 	 * usb mdm channel is complete
 	 */
-	driver->in_busy_hsic_write_on_mdm = 0;
-
+	driver->in_busy_hsic_write_on_device = 0;
 	if (!driver->hsic_ch) {
 		pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
 		return 0;
@@ -275,7 +322,7 @@
 static int diagfwd_read_complete_hsic(struct diag_request *diag_read_ptr)
 {
 	/* The read of the usb driver on the mdm (not hsic) has completed */
-	driver->in_busy_hsic_read_on_mdm = 0;
+	driver->in_busy_hsic_read_on_device = 0;
 	driver->read_len_mdm = diag_read_ptr->actual;
 
 	if (!driver->hsic_ch) {
@@ -329,7 +376,7 @@
 {
 	switch (event) {
 	case USB_DIAG_CONNECT:
-		diagfwd_connect_hsic();
+		diagfwd_connect_hsic(1);
 		break;
 	case USB_DIAG_DISCONNECT:
 		queue_work(driver->diag_hsic_wq, &driver->diag_disconnect_work);
@@ -355,7 +402,7 @@
 
 static void diag_disconnect_work_fn(struct work_struct *w)
 {
-	diagfwd_disconnect_hsic();
+	diagfwd_disconnect_hsic(1);
 }
 
 static void diag_read_mdm_work_fn(struct work_struct *work)
@@ -370,11 +417,12 @@
 	 * and there is no mdm channel data currently being written
 	 * to the hsic
 	 */
-	if (!driver->in_busy_hsic_read_on_mdm && !driver->in_busy_hsic_write) {
+	if (!driver->in_busy_hsic_read_on_device &&
+				 !driver->in_busy_hsic_write) {
 		APPEND_DEBUG('x');
 
 		/* Setup the next read from usb mdm channel */
-		driver->in_busy_hsic_read_on_mdm = 1;
+		driver->in_busy_hsic_read_on_device = 1;
 		driver->usb_read_mdm_ptr->buf = driver->usb_buf_mdm_out;
 		driver->usb_read_mdm_ptr->length = USB_MAX_OUT_BUF;
 		usb_diag_read(driver->mdm_ch, driver->usb_read_mdm_ptr);
@@ -385,41 +433,77 @@
 	 * If for some reason there was no mdm channel read initiated,
 	 * queue up the reading of data from the mdm channel
 	 */
-	if (!driver->in_busy_hsic_read_on_mdm)
+	if (!driver->in_busy_hsic_read_on_device)
 		queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
 }
 
-int diag_hsic_enable(void)
+static int diag_hsic_probe(struct platform_device *pdev)
 {
-	pr_debug("DIAG in %s\n", __func__);
-
-	driver->read_len_mdm = 0;
-	if (driver->buf_in_hsic == NULL)
-		driver->buf_in_hsic = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
-	if (driver->buf_in_hsic == NULL)
-		goto err;
-	if (driver->usb_buf_mdm_out  == NULL)
-		driver->usb_buf_mdm_out = kzalloc(USB_MAX_OUT_BUF, GFP_KERNEL);
-	if (driver->usb_buf_mdm_out == NULL)
-		goto err;
-	if (driver->write_ptr_mdm == NULL)
-		driver->write_ptr_mdm = kzalloc(
-		sizeof(struct diag_request), GFP_KERNEL);
-	if (driver->write_ptr_mdm == NULL)
-		goto err;
-	if (driver->usb_read_mdm_ptr == NULL)
-		driver->usb_read_mdm_ptr = kzalloc(
-		sizeof(struct diag_request), GFP_KERNEL);
-	if (driver->usb_read_mdm_ptr == NULL)
-		goto err;
+	int err = 0;
+	pr_debug("diag: in %s\n", __func__);
+	if (!driver->hsic_device_enabled) {
+		driver->read_len_mdm = 0;
+		if (driver->buf_in_hsic == NULL)
+			driver->buf_in_hsic = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
+		if (driver->buf_in_hsic == NULL)
+			goto err;
+		if (driver->usb_buf_mdm_out  == NULL)
+			driver->usb_buf_mdm_out = kzalloc(USB_MAX_OUT_BUF,
+								 GFP_KERNEL);
+		if (driver->usb_buf_mdm_out == NULL)
+			goto err;
+		if (driver->write_ptr_mdm == NULL)
+			driver->write_ptr_mdm = kzalloc(
+			sizeof(struct diag_request), GFP_KERNEL);
+		if (driver->write_ptr_mdm == NULL)
+			goto err;
+		if (driver->usb_read_mdm_ptr == NULL)
+			driver->usb_read_mdm_ptr = kzalloc(
+			sizeof(struct diag_request), GFP_KERNEL);
+		if (driver->usb_read_mdm_ptr == NULL)
+			goto err;
 #ifdef CONFIG_DIAG_OVER_USB
-	INIT_WORK(&(driver->diag_read_mdm_work), diag_read_mdm_work_fn);
+		INIT_WORK(&(driver->diag_read_mdm_work), diag_read_mdm_work_fn);
 #endif
-	INIT_WORK(&(driver->diag_read_hsic_work), diag_read_hsic_work_fn);
+		INIT_WORK(&(driver->diag_read_hsic_work),
+						 diag_read_hsic_work_fn);
+		driver->hsic_device_enabled = 1;
+	}
 
-	driver->hsic_device_enabled = 1;
+	/*
+	 * The probe function was called after the usb was connected
+	 * on the legacy channel OR ODL is turned on. Communication over usb
+	 * mdm and hsic needs to be turned on.
+	 */
+	if (driver->usb_mdm_connected || (driver->logging_mode ==
+							 MEMORY_DEVICE_MODE)) {
+		/* The hsic (diag_bridge) platform device driver is enabled */
+		err = diag_bridge_open(&hsic_diag_bridge_ops);
+		if (err) {
+			pr_err("diag: could not open HSIC, err: %d\n", err);
+			driver->hsic_device_opened = 0;
+			return err;
+		}
 
-	return 0;
+		pr_info("diag: opened HSIC channel\n");
+		driver->hsic_device_opened = 1;
+		driver->hsic_ch = 1;
+		driver->in_busy_hsic_write_on_device = 0;
+		driver->in_busy_hsic_read_on_device = 0;
+		driver->in_busy_hsic_write = 0;
+		driver->in_busy_hsic_read = 0;
+
+		if (driver->usb_mdm_connected) {
+			/* Poll USB mdm channel to check for data */
+			queue_work(driver->diag_hsic_wq,
+					 &driver->diag_read_mdm_work);
+		}
+
+		/* Poll HSIC channel to check for data */
+		queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+	}
+
+	return err;
 err:
 	pr_err("DIAG could not initialize buf for HSIC\n");
 	kfree(driver->buf_in_hsic);
@@ -432,50 +516,6 @@
 	return -ENOMEM;
 }
 
-static int diag_hsic_probe(struct platform_device *pdev)
-{
-	int err;
-
-	if (!driver->hsic_device_enabled) {
-		err = diag_hsic_enable();
-		if (err) {
-			pr_err("DIAG could not enable HSIC, err: %d\n", err);
-			return err;
-		}
-	}
-
-	/*
-	 * The probe function was called after the usb was connected
-	 * on the legacy channel. Communication over usb mdm and hsic
-	 * needs to be turned on.
-	 */
-	if (driver->usb_mdm_connected) {
-		/* The hsic (diag_bridge) platform device driver is enabled */
-		err = diag_bridge_open(&hsic_diag_bridge_ops);
-		if (err) {
-			pr_err("DIAG could not open HSIC, err: %d\n", err);
-			driver->hsic_device_opened = 0;
-			return err;
-		}
-
-		pr_debug("DIAG opened HSIC channel\n");
-		driver->hsic_device_opened = 1;
-		driver->hsic_ch = 1;
-		driver->in_busy_hsic_write_on_mdm = 0;
-		driver->in_busy_hsic_read_on_mdm = 0;
-		driver->in_busy_hsic_write = 0;
-		driver->in_busy_hsic_read = 0;
-
-		/* Poll USB mdm channel to check for data */
-		queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
-
-		/* Poll HSIC channel to check for data */
-		queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
-	}
-
-	return err;
-}
-
 static int diag_hsic_remove(struct platform_device *pdev)
 {
 	pr_debug("DIAG: %s called\n", __func__);
@@ -510,8 +550,7 @@
 		   },
 };
 
-
-void __init diagfwd_hsic_init(void)
+void diagfwd_hsic_init(void)
 {
 	int ret;
 
@@ -540,7 +579,7 @@
 	pr_err("DIAG could not initialize for HSIC execution\n");
 }
 
-void __exit diagfwd_hsic_exit(void)
+void diagfwd_hsic_exit(void)
 {
 	pr_debug("DIAG in %s\n", __func__);
 
diff --git a/drivers/char/diag/diagfwd_hsic.h b/drivers/char/diag/diagfwd_hsic.h
index 6769052..8785d9f 100644
--- a/drivers/char/diag/diagfwd_hsic.h
+++ b/drivers/char/diag/diagfwd_hsic.h
@@ -17,7 +17,11 @@
 #define N_MDM_WRITE	1 /* Upgrade to 2 with ping pong buffer */
 #define N_MDM_READ	1
 
-void __init diagfwd_hsic_init(void);
-void __exit diagfwd_hsic_exit(void);
+int diagfwd_connect_hsic(int);
+int diagfwd_disconnect_hsic(int);
+int diagfwd_write_complete_hsic(void);
+int diagfwd_cancel_hsic(void);
+void diagfwd_hsic_init(void);
+void diagfwd_hsic_exit(void);
 
 #endif
diff --git a/drivers/char/hw_random/msm_rng.c b/drivers/char/hw_random/msm_rng.c
index d1a9fe6..974b77e 100644
--- a/drivers/char/hw_random/msm_rng.c
+++ b/drivers/char/hw_random/msm_rng.c
@@ -72,7 +72,7 @@
 		return 0;
 
 	/* enable PRNG clock */
-	ret = clk_enable(msm_rng_dev->prng_clk);
+	ret = clk_prepare_enable(msm_rng_dev->prng_clk);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to enable clock in callback\n");
 		return 0;
@@ -99,7 +99,7 @@
 	} while (currsize < maxsize);
 
 	/* vote to turn off clock */
-	clk_disable(msm_rng_dev->prng_clk);
+	clk_disable_unprepare(msm_rng_dev->prng_clk);
 
 	return currsize;
 }
@@ -116,7 +116,7 @@
 	int ret = 0;
 
 	/* Enable the PRNG CLK */
-	ret = clk_enable(msm_rng_dev->prng_clk);
+	ret = clk_prepare_enable(msm_rng_dev->prng_clk);
 	if (ret) {
 		dev_err(&(msm_rng_dev->pdev)->dev,
 				"failed to enable clock in probe\n");
@@ -146,7 +146,7 @@
 		mb();
 	}
 
-	clk_disable(msm_rng_dev->prng_clk);
+	clk_disable_unprepare(msm_rng_dev->prng_clk);
 
 	return 0;
 }
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index 47bc750..865fcc2 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -1303,15 +1303,15 @@
 			msm_rotator_dev->img_info[first_free_index];
 		*(msm_rotator_dev->img_info[first_free_index]) = info;
 		msm_rotator_dev->fd_info[first_free_index] = fd_info;
-
-		if (copy_to_user((void __user *)arg, &info, sizeof(info)))
-			rc = -EFAULT;
 	} else if (s == MAX_SESSIONS) {
 		dev_dbg(msm_rotator_dev->device, "%s: all sessions in use\n",
 			__func__);
 		rc = -EBUSY;
 	}
 
+	if (rc == 0 && copy_to_user((void __user *)arg, &info, sizeof(info)))
+		rc = -EFAULT;
+
 rotator_start_exit:
 	mutex_unlock(&msm_rotator_dev->rotator_lock);
 
diff --git a/drivers/crypto/msm/qce40.c b/drivers/crypto/msm/qce40.c
index 0d3c4c3..111bc49 100644
--- a/drivers/crypto/msm/qce40.c
+++ b/drivers/crypto/msm/qce40.c
@@ -2505,7 +2505,7 @@
 	pce_dev->ce_clk = ce_clk;
 
 	/* Enable CE core clk */
-	*rc = clk_enable(pce_dev->ce_core_clk);
+	*rc = clk_prepare_enable(pce_dev->ce_core_clk);
 	if (*rc) {
 		if (pce_dev->ce_core_src_clk != NULL)
 			clk_put(pce_dev->ce_core_src_clk);
@@ -2514,9 +2514,9 @@
 		goto err;
 	} else {
 		/* Enable CE clk */
-		*rc = clk_enable(pce_dev->ce_clk);
+		*rc = clk_prepare_enable(pce_dev->ce_clk);
 		if (*rc) {
-			clk_disable(pce_dev->ce_core_clk);
+			clk_disable_unprepare(pce_dev->ce_core_clk);
 			if (pce_dev->ce_core_src_clk != NULL)
 				clk_put(pce_dev->ce_core_src_clk);
 			clk_put(pce_dev->ce_core_clk);
@@ -2567,8 +2567,8 @@
 	if (pce_dev->coh_vmem)
 		dma_free_coherent(pce_dev->pdev, pce_dev->memsize,
 				pce_dev->coh_vmem, pce_dev->coh_pmem);
-	clk_disable(pce_dev->ce_clk);
-	clk_disable(pce_dev->ce_core_clk);
+	clk_disable_unprepare(pce_dev->ce_clk);
+	clk_disable_unprepare(pce_dev->ce_core_clk);
 
 	if (pce_dev->ce_core_src_clk != NULL)
 		clk_put(pce_dev->ce_core_src_clk);
diff --git a/drivers/gpio/qpnp-gpio.c b/drivers/gpio/qpnp-gpio.c
index b09b040..90cc798 100644
--- a/drivers/gpio/qpnp-gpio.c
+++ b/drivers/gpio/qpnp-gpio.c
@@ -168,7 +168,7 @@
 	}
 
 	if (param->direction & QPNP_GPIO_DIR_OUT) {
-		q_spec->regs[Q_REG_I_OUTPUT_CTL2] = (param->inv_int_pol
+		q_spec->regs[Q_REG_I_OUTPUT_CTL2] = (param->output_value
 			    << Q_REG_OUT_INVERT_SHIFT) & Q_REG_OUT_INVERT_MASK;
 		q_spec->regs[Q_REG_I_OUTPUT_CTL2] |= (param->src_select
 			    << Q_REG_SRC_SEL_SHIFT) & Q_REG_SRC_SEL_MASK;
@@ -398,13 +398,11 @@
 	int rc;
 
 	dev_dbg(&spmi->dev, "%s: p[0]: 0x%x p[1]: 0x%x p[2]: 0x%x p[3]:"
-		" 0x%x p[4]: 0x%x p[5]: 0x%x p[6]: 0x%x p[7]: 0x%x"
-		" p[8]: 0x%x\n", __func__,
+		" 0x%x p[4]: 0x%x p[5]: 0x%x p[6]: 0x%x p[7]: 0x%x\n", __func__,
 		be32_to_cpup(&prop[0]), be32_to_cpup(&prop[1]),
 		be32_to_cpup(&prop[2]), be32_to_cpup(&prop[3]),
 		be32_to_cpup(&prop[4]), be32_to_cpup(&prop[5]),
-		be32_to_cpup(&prop[6]), be32_to_cpup(&prop[7]),
-		be32_to_cpup(&prop[8]));
+		be32_to_cpup(&prop[6]), be32_to_cpup(&prop[7]));
 
 	param.direction    =	be32_to_cpup(&prop[0]);
 	param.output_type  =	be32_to_cpup(&prop[1]);
@@ -413,8 +411,7 @@
 	param.vin_sel	   =	be32_to_cpup(&prop[4]);
 	param.out_strength =	be32_to_cpup(&prop[5]);
 	param.src_select   =	be32_to_cpup(&prop[6]);
-	param.inv_int_pol  =	be32_to_cpup(&prop[7]);
-	param.master_en    =	be32_to_cpup(&prop[8]);
+	param.master_en    =	be32_to_cpup(&prop[7]);
 
 	rc = qpnp_gpio_config(gpio, &param);
 	if (rc)
@@ -613,8 +610,8 @@
 		/* It's not an error to not config a default */
 		prop = of_get_property(spmi->dev_node[i].of_node,
 				"qcom,qpnp-gpio-cfg", &len);
-		/* 9 data values constitute one tuple */
-		if (prop && (len != (9 * sizeof(__be32)))) {
+		/* 8 data values constitute one tuple */
+		if (prop && (len != (8 * sizeof(__be32)))) {
 			dev_err(&spmi->dev, "%s: invalid format for"
 				" qcom,qpnp-gpio-cfg property\n",
 							__func__);
@@ -697,10 +694,8 @@
 {
 }
 
-MODULE_AUTHOR(
-	"Michael Bohan <mbohan@codeaurora.org>");
 MODULE_DESCRIPTION("QPNP PMIC gpio driver");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
 
 module_init(qpnp_gpio_init);
 module_exit(qpnp_gpio_exit);
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 0cec423..6823a5a 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -484,7 +484,7 @@
 	valid_handle = ion_handle_validate(client, handle);
 	if (!valid_handle) {
 		mutex_unlock(&client->lock);
-		WARN("%s: invalid handle passed to free.\n", __func__);
+		WARN(1, "%s: invalid handle passed to free.\n", __func__);
 		return;
 	}
 	ion_handle_put(handle);
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index de9e2c4..84789ef 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -54,7 +54,7 @@
 
 	if (!offset) {
 		if ((carveout_heap->total_size -
-		      carveout_heap->allocated_bytes) > size)
+		      carveout_heap->allocated_bytes) >= size)
 			pr_debug("%s: heap %s has enough memory (%lx) but"
 				" the allocation of size %lx still failed."
 				" Memory is probably fragmented.",
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index 7d99482..b383e68 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -224,8 +224,9 @@
 
 	if (!offset) {
 		mutex_lock(&cp_heap->lock);
+		cp_heap->allocated_bytes -= size;
 		if ((cp_heap->total_size -
-		      cp_heap->allocated_bytes) > size)
+		     cp_heap->allocated_bytes) >= size)
 			pr_debug("%s: heap %s has enough memory (%lx) but"
 				" the allocation of size %lx still failed."
 				" Memory is probably fragmented.\n",
@@ -233,8 +234,6 @@
 				cp_heap->total_size -
 				cp_heap->allocated_bytes, size);
 
-		cp_heap->allocated_bytes -= size;
-
 		if (cp_heap->reusable && !cp_heap->allocated_bytes) {
 			if (fmem_set_state(FMEM_T_STATE) != 0)
 				pr_err("%s: unable to transition heap to T-state\n",
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 87f259d..00dba96 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -169,10 +169,9 @@
 
 };
 
-static irqreturn_t adreno_isr(int irq, void *data)
+static irqreturn_t adreno_irq_handler(struct kgsl_device *device)
 {
 	irqreturn_t result;
-	struct kgsl_device *device = data;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 
 	result = adreno_dev->gpudev->irq_handler(adreno_dev);
@@ -490,7 +489,7 @@
 	if (status != 0)
 		goto error;
 
-	status = kgsl_device_platform_probe(device, adreno_isr);
+	status = kgsl_device_platform_probe(device);
 	if (status)
 		goto error_close_rb;
 
@@ -1444,6 +1443,7 @@
 	.irqctrl = adreno_irqctrl,
 	.gpuid = adreno_gpuid,
 	.snapshot = adreno_snapshot,
+	.irq_handler = adreno_irq_handler,
 	/* Optional functions */
 	.setstate = adreno_setstate,
 	.drawctxt_create = adreno_drawctxt_create,
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 491cf62..95378a1 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -181,6 +181,16 @@
 	return (adreno_dev->gpurev >= 300);
 }
 
+static inline int adreno_is_a305(struct adreno_device *adreno_dev)
+{
+	return (adreno_dev->gpurev == ADRENO_REV_A305);
+}
+
+static inline int adreno_is_a320(struct adreno_device *adreno_dev)
+{
+	return (adreno_dev->gpurev == ADRENO_REV_A320);
+}
+
 static inline int adreno_rb_ctxtswitch(unsigned int *cmd)
 {
 	return (cmd[0] == cp_nop_packet(1) &&
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index d773521..0d15fb9 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -280,6 +280,6 @@
 	adreno_dev->gpudev->ctxt_save(adreno_dev, adreno_dev->drawctxt_active);
 
 	/* Set the new context */
-	adreno_dev->drawctxt_active = drawctxt;
 	adreno_dev->gpudev->ctxt_restore(adreno_dev, drawctxt);
+	adreno_dev->drawctxt_active = drawctxt;
 }
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 5f16ff7..a992059 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -339,6 +339,8 @@
 	if (status != 0)
 		return status;
 
+	if (adreno_is_a305(adreno_dev) || adreno_is_a320(adreno_dev))
+		adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000F0602);
 
 	rb->rptr = 0;
 	rb->wptr = 0;
@@ -855,7 +857,7 @@
 	*cmds++ = cp_nop_packet(1);
 	*cmds++ = KGSL_END_OF_IB_IDENTIFIER;
 
-	kgsl_setstate(device,
+	kgsl_setstate(&device->mmu,
 		      kgsl_mmu_pt_get_flags(device->mmu.hwpagetable,
 					device->id));
 
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 9e9bbf2..321c59e 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -122,6 +122,40 @@
 }
 
 /**
+ * kgsl_cancel_events_ctxt - Cancel all events for a context
+ * @device - KGSL device for the events to cancel
+ * @ctxt - context whose events we want to cancel
+ *
+ */
+static void kgsl_cancel_events_ctxt(struct kgsl_device *device,
+	struct kgsl_context *context)
+{
+	struct kgsl_event *event, *event_tmp;
+	unsigned int id, cur;
+
+	cur = device->ftbl->readtimestamp(device, context,
+			KGSL_TIMESTAMP_RETIRED);
+	id = context->id;
+
+	list_for_each_entry_safe(event, event_tmp, &device->events, list) {
+		if (event->context != context)
+			continue;
+
+		/*
+		 * "cancel" the events by calling their callback.
+		 * Currently, events are used for lock and memory
+		 * management, so if the process is dying the right
+		 * thing to do is release or free.
+		 */
+		if (event->func)
+			event->func(device, event->priv, id, cur);
+
+		list_del(&event->list);
+		kfree(event);
+	}
+}
+
+/**
  * kgsl_cancel_events - Cancel all events for a process
  * @device - KGSL device for the events to cancel
  * @owner - driver instance that owns the events to cancel
@@ -457,12 +491,9 @@
 	struct kgsl_context *context, unsigned int timestamp)
 {
 	unsigned int ts_processed;
-	unsigned int global;
 
 	ts_processed = device->ftbl->readtimestamp(device, context,
 		KGSL_TIMESTAMP_RETIRED);
-	global = device->ftbl->readtimestamp(device, NULL,
-		KGSL_TIMESTAMP_RETIRED);
 
 	return (timestamp_cmp(ts_processed, timestamp) >= 0);
 }
@@ -718,6 +749,11 @@
 	mutex_lock(&device->mutex);
 	kgsl_check_suspended(device);
 
+	/* clean up any to-be-freed entries that belong to this
+	 * process and this device
+	 */
+	kgsl_cancel_events(device, dev_priv);
+
 	while (1) {
 		context = idr_get_next(&device->context_idr, &next);
 		if (context == NULL)
@@ -736,10 +772,6 @@
 		result = device->ftbl->stop(device);
 		kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
 	}
-	/* clean up any to-be-freed entries that belong to this
-	 * process and this device
-	 */
-	kgsl_cancel_events(device, dev_priv);
 
 	mutex_unlock(&device->mutex);
 	kfree(dev_priv);
@@ -1239,6 +1271,8 @@
 		goto done;
 	}
 
+	kgsl_cancel_events_ctxt(dev_priv->device, context);
+
 	if (dev_priv->device->ftbl->drawctxt_destroy)
 		dev_priv->device->ftbl->drawctxt_destroy(dev_priv->device,
 			context);
@@ -2261,6 +2295,14 @@
 	return 0;
 }
 
+static irqreturn_t kgsl_irq_handler(int irq, void *data)
+{
+	struct kgsl_device *device = data;
+
+	return device->ftbl->irq_handler(device);
+
+}
+
 static const struct file_operations kgsl_fops = {
 	.owner = THIS_MODULE,
 	.release = kgsl_release,
@@ -2421,8 +2463,7 @@
 }
 EXPORT_SYMBOL(kgsl_register_device);
 
-int kgsl_device_platform_probe(struct kgsl_device *device,
-			       irqreturn_t (*dev_isr) (int, void*))
+int kgsl_device_platform_probe(struct kgsl_device *device)
 {
 	int result;
 	int status = -EINVAL;
@@ -2470,7 +2511,7 @@
 		goto error_release_mem;
 	}
 
-	status = request_irq(device->pwrctrl.interrupt_num, dev_isr,
+	status = request_irq(device->pwrctrl.interrupt_num, kgsl_irq_handler,
 			     IRQF_TRIGGER_HIGH, device->name, device);
 	if (status) {
 		KGSL_DRV_ERR(device, "request_irq(%d) failed: %d\n",
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 5212d0f..9f80a73 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -33,7 +33,7 @@
 #define KGSL_MEMSTORE_MAX	(KGSL_MEMSTORE_SIZE / \
 		sizeof(struct kgsl_devmemstore) - 1)
 
-/* Timestamp window used to detect rollovers */
+/* Timestamp window used to detect rollovers (half of integer range) */
 #define KGSL_TIMESTAMP_WINDOW 0x80000000
 
 /*cache coherency ops */
@@ -229,14 +229,24 @@
 	return hostptr != NULL ? hostptr + (gpuaddr - memdesc->gpuaddr) : NULL;
 }
 
-static inline int timestamp_cmp(unsigned int new, unsigned int old)
+static inline int timestamp_cmp(unsigned int a, unsigned int b)
 {
-	int ts_diff = new - old;
-
-	if (ts_diff == 0)
+	/* check for equal */
+	if (a == b)
 		return 0;
 
-	return ((ts_diff > 0) || (ts_diff < -KGSL_TIMESTAMP_WINDOW)) ? 1 : -1;
+	/* check for greater-than for non-rollover case */
+	if ((a > b) && (a - b < KGSL_TIMESTAMP_WINDOW))
+		return 1;
+
+	/* check for greater-than for rollover case
+	 * note that <= is required to ensure that consistent
+	 * results are returned for values whose difference is
+	 * equal to the window size
+	 */
+	a += KGSL_TIMESTAMP_WINDOW;
+	b += KGSL_TIMESTAMP_WINDOW;
+	return ((a > b) && (a - b <= KGSL_TIMESTAMP_WINDOW)) ? 1 : -1;
 }
 
 static inline void
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 7d3cfca..b42e606 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -94,6 +94,7 @@
 	unsigned int (*gpuid)(struct kgsl_device *device);
 	void * (*snapshot)(struct kgsl_device *device, void *snapshot,
 		int *remain, int hang);
+	irqreturn_t (*irq_handler)(struct kgsl_device *device);
 	/* Optional functions - these functions are not mandatory.  The
 	   driver will check that the function pointer is not NULL before
 	   calling the hook */
@@ -340,8 +341,8 @@
 int kgsl_unregister_ts_notifier(struct kgsl_device *device,
 				struct notifier_block *nb);
 
-int kgsl_device_platform_probe(struct kgsl_device *device,
-		irqreturn_t (*dev_isr) (int, void*));
+int kgsl_device_platform_probe(struct kgsl_device *device);
+
 void kgsl_device_platform_remove(struct kgsl_device *device);
 
 const char *kgsl_pwrstate_to_str(unsigned int state);
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index bbb5d46..1d80a30 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -397,34 +397,15 @@
 	return baseptr[pte] & GSL_PT_PAGE_ADDR_MASK;
 }
 
-static unsigned int kgsl_gpummu_pt_get_flags(struct kgsl_pagetable *pt,
-				enum kgsl_deviceid id)
-{
-	unsigned int result = 0;
-	struct kgsl_gpummu_pt *gpummu_pt;
-
-	if (pt == NULL)
-		return 0;
-	gpummu_pt = pt->priv;
-
-	spin_lock(&pt->lock);
-	if (gpummu_pt->tlb_flags && (1<<id)) {
-		result = KGSL_MMUFLAGS_TLBFLUSH;
-		gpummu_pt->tlb_flags &= ~(1<<id);
-	}
-	spin_unlock(&pt->lock);
-	return result;
-}
-
-static void kgsl_gpummu_pagefault(struct kgsl_device *device)
+static void kgsl_gpummu_pagefault(struct kgsl_mmu *mmu)
 {
 	unsigned int reg;
 	unsigned int ptbase;
 
-	kgsl_regread(device, MH_MMU_PAGE_FAULT, &reg);
-	kgsl_regread(device, MH_MMU_PT_BASE, &ptbase);
+	kgsl_regread(mmu->device, MH_MMU_PAGE_FAULT, &reg);
+	kgsl_regread(mmu->device, MH_MMU_PT_BASE, &ptbase);
 
-	KGSL_MEM_CRIT(device,
+	KGSL_MEM_CRIT(mmu->device,
 			"mmu page fault: page=0x%lx pt=%d op=%s axi=%d\n",
 			reg & ~(PAGE_SIZE - 1),
 			kgsl_mmu_get_ptname_from_ptbase(ptbase),
@@ -440,7 +421,6 @@
 	if (!gpummu_pt)
 		return NULL;
 
-	gpummu_pt->tlb_flags = 0;
 	gpummu_pt->last_superpte = 0;
 
 	gpummu_pt->tlbflushfilter.size = (CONFIG_MSM_KGSL_PAGE_TABLE_SIZE /
@@ -480,7 +460,7 @@
 	return NULL;
 }
 
-static void kgsl_gpummu_default_setstate(struct kgsl_device *device,
+static void kgsl_gpummu_default_setstate(struct kgsl_mmu *mmu,
 					uint32_t flags)
 {
 	struct kgsl_gpummu_pt *gpummu_pt;
@@ -488,43 +468,40 @@
 		return;
 
 	if (flags & KGSL_MMUFLAGS_PTUPDATE) {
-		kgsl_idle(device, KGSL_TIMEOUT_DEFAULT);
-		gpummu_pt = device->mmu.hwpagetable->priv;
-		kgsl_regwrite(device, MH_MMU_PT_BASE,
+		kgsl_idle(mmu->device, KGSL_TIMEOUT_DEFAULT);
+		gpummu_pt = mmu->hwpagetable->priv;
+		kgsl_regwrite(mmu->device, MH_MMU_PT_BASE,
 			gpummu_pt->base.gpuaddr);
 	}
 
 	if (flags & KGSL_MMUFLAGS_TLBFLUSH) {
 		/* Invalidate all and tc */
-		kgsl_regwrite(device, MH_MMU_INVALIDATE,  0x00000003);
+		kgsl_regwrite(mmu->device, MH_MMU_INVALIDATE,  0x00000003);
 	}
 }
 
-static void kgsl_gpummu_setstate(struct kgsl_device *device,
+static void kgsl_gpummu_setstate(struct kgsl_mmu *mmu,
 				struct kgsl_pagetable *pagetable)
 {
-	struct kgsl_mmu *mmu = &device->mmu;
-	struct kgsl_gpummu_pt *gpummu_pt;
-
 	if (mmu->flags & KGSL_FLAGS_STARTED) {
 		/* page table not current, then setup mmu to use new
 		 *  specified page table
 		 */
 		if (mmu->hwpagetable != pagetable) {
 			mmu->hwpagetable = pagetable;
-			spin_lock(&mmu->hwpagetable->lock);
-			gpummu_pt = mmu->hwpagetable->priv;
-			gpummu_pt->tlb_flags &= ~(1<<device->id);
-			spin_unlock(&mmu->hwpagetable->lock);
+			/* Since we do a TLB flush the tlb_flags should
+			 * be cleared by calling kgsl_mmu_pt_get_flags
+			 */
+			kgsl_mmu_pt_get_flags(pagetable, mmu->device->id);
 
 			/* call device specific set page table */
-			kgsl_setstate(mmu->device, KGSL_MMUFLAGS_TLBFLUSH |
+			kgsl_setstate(mmu, KGSL_MMUFLAGS_TLBFLUSH |
 				KGSL_MMUFLAGS_PTUPDATE);
 		}
 	}
 }
 
-static int kgsl_gpummu_init(struct kgsl_device *device)
+static int kgsl_gpummu_init(struct kgsl_mmu *mmu)
 {
 	/*
 	 * intialize device mmu
@@ -532,9 +509,6 @@
 	 * call this with the global lock held
 	 */
 	int status = 0;
-	struct kgsl_mmu *mmu = &device->mmu;
-
-	mmu->device = device;
 
 	/* sub-client MMU lookups require address translation */
 	if ((mmu->config & ~0x1) > 0) {
@@ -554,12 +528,12 @@
 					   mmu->setstate_memory.size);
 	}
 
-	dev_info(device->dev, "|%s| MMU type set for device is GPUMMU\n",
+	dev_info(mmu->device->dev, "|%s| MMU type set for device is GPUMMU\n",
 		__func__);
 	return status;
 }
 
-static int kgsl_gpummu_start(struct kgsl_device *device)
+static int kgsl_gpummu_start(struct kgsl_mmu *mmu)
 {
 	/*
 	 * intialize device mmu
@@ -567,7 +541,7 @@
 	 * call this with the global lock held
 	 */
 
-	struct kgsl_mmu *mmu = &device->mmu;
+	struct kgsl_device *device = mmu->device;
 	struct kgsl_gpummu_pt *gpummu_pt;
 
 	if (mmu->flags & KGSL_FLAGS_STARTED)
@@ -608,12 +582,12 @@
 
 	mmu->hwpagetable = mmu->defaultpagetable;
 	gpummu_pt = mmu->hwpagetable->priv;
-	kgsl_regwrite(device, MH_MMU_PT_BASE,
+	kgsl_regwrite(mmu->device, MH_MMU_PT_BASE,
 		      gpummu_pt->base.gpuaddr);
-	kgsl_regwrite(device, MH_MMU_VA_RANGE,
+	kgsl_regwrite(mmu->device, MH_MMU_VA_RANGE,
 		      (KGSL_PAGETABLE_BASE |
 		      (CONFIG_MSM_KGSL_PAGE_TABLE_SIZE >> 16)));
-	kgsl_setstate(device, KGSL_MMUFLAGS_TLBFLUSH);
+	kgsl_setstate(mmu, KGSL_MMUFLAGS_TLBFLUSH);
 	mmu->flags |= KGSL_FLAGS_STARTED;
 
 	return 0;
@@ -670,7 +644,8 @@
 static int
 kgsl_gpummu_map(void *mmu_specific_pt,
 		struct kgsl_memdesc *memdesc,
-		unsigned int protflags)
+		unsigned int protflags,
+		unsigned int *tlb_flags)
 {
 	unsigned int pte;
 	struct kgsl_gpummu_pt *gpummu_pt = mmu_specific_pt;
@@ -704,32 +679,28 @@
 
 	if (flushtlb) {
 		/*set all devices as needing flushing*/
-		gpummu_pt->tlb_flags = UINT_MAX;
+		*tlb_flags = UINT_MAX;
 		GSL_TLBFLUSH_FILTER_RESET();
 	}
 
 	return 0;
 }
 
-static int kgsl_gpummu_stop(struct kgsl_device *device)
+static int kgsl_gpummu_stop(struct kgsl_mmu *mmu)
 {
-	struct kgsl_mmu *mmu = &device->mmu;
-
-	kgsl_regwrite(device, MH_MMU_CONFIG, 0x00000000);
+	kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000000);
 	mmu->flags &= ~KGSL_FLAGS_STARTED;
 
 	return 0;
 }
 
-static int kgsl_gpummu_close(struct kgsl_device *device)
+static int kgsl_gpummu_close(struct kgsl_mmu *mmu)
 {
 	/*
 	 *  close device mmu
 	 *
 	 *  call this with the global lock held
 	 */
-	struct kgsl_mmu *mmu = &device->mmu;
-
 	if (mmu->setstate_memory.gpuaddr)
 		kgsl_sharedmem_free(&mmu->setstate_memory);
 
@@ -740,10 +711,10 @@
 }
 
 static unsigned int
-kgsl_gpummu_get_current_ptbase(struct kgsl_device *device)
+kgsl_gpummu_get_current_ptbase(struct kgsl_mmu *mmu)
 {
 	unsigned int ptbase;
-	kgsl_regread(device, MH_MMU_PT_BASE, &ptbase);
+	kgsl_regread(mmu->device, MH_MMU_PT_BASE, &ptbase);
 	return ptbase;
 }
 
@@ -764,5 +735,4 @@
 	.mmu_create_pagetable = kgsl_gpummu_create_pagetable,
 	.mmu_destroy_pagetable = kgsl_gpummu_destroy_pagetable,
 	.mmu_pt_equal = kgsl_gpummu_pt_equal,
-	.mmu_pt_get_flags = kgsl_gpummu_pt_get_flags,
 };
diff --git a/drivers/gpu/msm/kgsl_gpummu.h b/drivers/gpu/msm/kgsl_gpummu.h
index cac6930..c61a8b2 100644
--- a/drivers/gpu/msm/kgsl_gpummu.h
+++ b/drivers/gpu/msm/kgsl_gpummu.h
@@ -47,7 +47,6 @@
 struct kgsl_gpummu_pt {
 	struct kgsl_memdesc  base;
 	unsigned int   last_superpte;
-	unsigned int tlb_flags;
 	/* Maintain filter to manage tlb flushing */
 	struct kgsl_tlbflushfilter tlbflushfilter;
 };
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 50086d2..bf2a4ee 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -166,17 +166,15 @@
 	return ret;
 }
 
-static void kgsl_iommu_setstate(struct kgsl_device *device,
+static void kgsl_iommu_setstate(struct kgsl_mmu *mmu,
 				struct kgsl_pagetable *pagetable)
 {
-	struct kgsl_mmu *mmu = &device->mmu;
-
 	if (mmu->flags & KGSL_FLAGS_STARTED) {
 		/* page table not current, then setup mmu to use new
 		 *  specified page table
 		 */
 		if (mmu->hwpagetable != pagetable) {
-			kgsl_idle(device, KGSL_TIMEOUT_DEFAULT);
+			kgsl_idle(mmu->device, KGSL_TIMEOUT_DEFAULT);
 			kgsl_detach_pagetable_iommu_domain(mmu);
 			mmu->hwpagetable = pagetable;
 			if (mmu->hwpagetable)
@@ -185,7 +183,7 @@
 	}
 }
 
-static int kgsl_iommu_init(struct kgsl_device *device)
+static int kgsl_iommu_init(struct kgsl_mmu *mmu)
 {
 	/*
 	 * intialize device mmu
@@ -193,11 +191,8 @@
 	 * call this with the global lock held
 	 */
 	int status = 0;
-	struct kgsl_mmu *mmu = &device->mmu;
 	struct kgsl_iommu *iommu;
 
-	mmu->device = device;
-
 	iommu = kzalloc(sizeof(struct kgsl_iommu), GFP_KERNEL);
 	if (!iommu) {
 		KGSL_CORE_ERR("kzalloc(%d) failed\n",
@@ -205,27 +200,26 @@
 		return -ENOMEM;
 	}
 
-	status = kgsl_get_iommu_ctxt(iommu, device);
+	status = kgsl_get_iommu_ctxt(iommu, mmu->device);
 	if (status) {
 		kfree(iommu);
 		iommu = NULL;
 	}
 	mmu->priv = iommu;
 
-	dev_info(device->dev, "|%s| MMU type set for device is IOMMU\n",
+	dev_info(mmu->device->dev, "|%s| MMU type set for device is IOMMU\n",
 			__func__);
 	return status;
 }
 
-static int kgsl_iommu_start(struct kgsl_device *device)
+static int kgsl_iommu_start(struct kgsl_mmu *mmu)
 {
 	int status;
-	struct kgsl_mmu *mmu = &device->mmu;
 
 	if (mmu->flags & KGSL_FLAGS_STARTED)
 		return 0;
 
-	kgsl_regwrite(device, MH_MMU_CONFIG, 0x00000000);
+	kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000000);
 	if (mmu->defaultpagetable == NULL)
 		mmu->defaultpagetable =
 			kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
@@ -271,7 +265,8 @@
 static int
 kgsl_iommu_map(void *mmu_specific_pt,
 			struct kgsl_memdesc *memdesc,
-			unsigned int protflags)
+			unsigned int protflags,
+			unsigned int *tlb_flags)
 {
 	int ret;
 	unsigned int iommu_virt_addr;
@@ -292,17 +287,24 @@
 		return ret;
 	}
 
+#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE
+	/*
+	 * Flushing only required if per process pagetables are used. With
+	 * global case, flushing will happen inside iommu_map function
+	 */
+	if (!ret)
+		*tlb_flags = UINT_MAX;
+#endif
 	return ret;
 }
 
-static int kgsl_iommu_stop(struct kgsl_device *device)
+static int kgsl_iommu_stop(struct kgsl_mmu *mmu)
 {
 	/*
 	 *  stop device mmu
 	 *
 	 *  call this with the global lock held
 	 */
-	struct kgsl_mmu *mmu = &device->mmu;
 
 	if (mmu->flags & KGSL_FLAGS_STARTED) {
 		/* detach iommu attachment */
@@ -314,9 +316,8 @@
 	return 0;
 }
 
-static int kgsl_iommu_close(struct kgsl_device *device)
+static int kgsl_iommu_close(struct kgsl_mmu *mmu)
 {
-	struct kgsl_mmu *mmu = &device->mmu;
 	if (mmu->defaultpagetable)
 		kgsl_mmu_putpagetable(mmu->defaultpagetable);
 
@@ -324,13 +325,13 @@
 }
 
 static unsigned int
-kgsl_iommu_get_current_ptbase(struct kgsl_device *device)
+kgsl_iommu_get_current_ptbase(struct kgsl_mmu *mmu)
 {
 	/* Current base is always the hwpagetables domain as we
 	 * do not use per process pagetables right not for iommu.
 	 * This will change when we switch to per process pagetables.
 	 */
-	return (unsigned int)device->mmu.hwpagetable->priv;
+	return (unsigned int)mmu->hwpagetable->priv;
 }
 
 struct kgsl_mmu_ops iommu_ops = {
@@ -350,5 +351,4 @@
 	.mmu_create_pagetable = kgsl_iommu_create_pagetable,
 	.mmu_destroy_pagetable = kgsl_iommu_destroy_pagetable,
 	.mmu_pt_equal = kgsl_iommu_pt_equal,
-	.mmu_pt_get_flags = NULL,
 };
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 7eb5ee9..2b359ec 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -36,7 +36,8 @@
 {
 	int i;
 	/* For IOMMU only unmap the global structures to global pt */
-	if ((KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type) &&
+	if ((KGSL_MMU_TYPE_NONE != kgsl_mmu_type) &&
+		(KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type) &&
 		(KGSL_MMU_GLOBAL_PT !=  pt->name))
 		return 0;
 	for (i = 0; i < KGSL_DEVICE_MAX; i++) {
@@ -47,6 +48,36 @@
 	return 0;
 }
 
+
+static int kgsl_setup_pt(struct kgsl_pagetable *pt)
+{
+	int i = 0;
+	int status = 0;
+
+	/* For IOMMU only map the global structures to global pt */
+	if ((KGSL_MMU_TYPE_NONE != kgsl_mmu_type) &&
+		(KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type) &&
+		(KGSL_MMU_GLOBAL_PT !=  pt->name))
+		return 0;
+	for (i = 0; i < KGSL_DEVICE_MAX; i++) {
+		struct kgsl_device *device = kgsl_driver.devp[i];
+		if (device) {
+			status = device->ftbl->setup_pt(device, pt);
+			if (status)
+				goto error_pt;
+		}
+	}
+	return status;
+error_pt:
+	while (i >= 0) {
+		struct kgsl_device *device = kgsl_driver.devp[i];
+		if (device)
+			device->ftbl->cleanup_pt(device, pt);
+		i--;
+	}
+	return status;
+}
+
 static void kgsl_destroy_pagetable(struct kref *kref)
 {
 	struct kgsl_pagetable *pagetable = container_of(kref,
@@ -297,7 +328,7 @@
 	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
 		return 0;
 	else
-		return mmu->mmu_ops->mmu_get_current_ptbase(device);
+		return mmu->mmu_ops->mmu_get_current_ptbase(mmu);
 }
 EXPORT_SYMBOL(kgsl_mmu_get_current_ptbase);
 
@@ -328,7 +359,7 @@
 	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
 		return;
 	else
-		mmu->mmu_ops->mmu_setstate(device,
+		mmu->mmu_ops->mmu_setstate(mmu,
 					pagetable);
 }
 EXPORT_SYMBOL(kgsl_mmu_setstate);
@@ -340,15 +371,21 @@
 	mmu->device = device;
 
 	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type) {
-		dev_info(device->dev, "|%s| MMU type set for device is "
-			"NOMMU\n", __func__);
-		return 0;
+		int status = 0;
+		status = kgsl_allocate_contiguous(&mmu->setstate_memory, 64);
+		if (!status) {
+			kgsl_sharedmem_set(&mmu->setstate_memory, 0, 0,
+					mmu->setstate_memory.size);
+			dev_info(device->dev, "|%s| MMU type set for device is "
+				"NOMMU\n", __func__);
+		}
+		return status;
 	} else if (KGSL_MMU_TYPE_GPU == kgsl_mmu_type)
 		mmu->mmu_ops = &gpummu_ops;
 	else if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type)
 		mmu->mmu_ops = &iommu_ops;
 
-	return mmu->mmu_ops->mmu_init(device);
+	return mmu->mmu_ops->mmu_init(mmu);
 }
 EXPORT_SYMBOL(kgsl_mmu_init);
 
@@ -358,9 +395,12 @@
 
 	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
 		kgsl_regwrite(device, MH_MMU_CONFIG, 0);
+		/* Setup gpuaddr of global mappings */
+		if (!mmu->setstate_memory.gpuaddr)
+			kgsl_setup_pt(NULL);
 		return 0;
 	} else {
-		return mmu->mmu_ops->mmu_start(device);
+		return mmu->mmu_ops->mmu_start(mmu);
 	}
 }
 EXPORT_SYMBOL(kgsl_mmu_start);
@@ -378,41 +418,13 @@
 	if (status & MH_INTERRUPT_MASK__AXI_WRITE_ERROR)
 		KGSL_MEM_CRIT(device, "axi write error interrupt: %08x\n", reg);
 	if (status & MH_INTERRUPT_MASK__MMU_PAGE_FAULT)
-		device->mmu.mmu_ops->mmu_pagefault(device);
+		device->mmu.mmu_ops->mmu_pagefault(&device->mmu);
 
 	status &= KGSL_MMU_INT_MASK;
 	kgsl_regwrite(device, MH_INTERRUPT_CLEAR, status);
 }
 EXPORT_SYMBOL(kgsl_mh_intrcallback);
 
-static int kgsl_setup_pt(struct kgsl_pagetable *pt)
-{
-	int i = 0;
-	int status = 0;
-
-	/* For IOMMU only map the global structures to global pt */
-	if ((KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type) &&
-		(KGSL_MMU_GLOBAL_PT !=  pt->name))
-		return 0;
-	for (i = 0; i < KGSL_DEVICE_MAX; i++) {
-		struct kgsl_device *device = kgsl_driver.devp[i];
-		if (device) {
-			status = device->ftbl->setup_pt(device, pt);
-			if (status)
-				goto error_pt;
-		}
-	}
-	return status;
-error_pt:
-	while (i >= 0) {
-		struct kgsl_device *device = kgsl_driver.devp[i];
-		if (device)
-			device->ftbl->cleanup_pt(device, pt);
-		i--;
-	}
-	return status;
-}
-
 static struct kgsl_pagetable *kgsl_mmu_createpagetableobject(
 				unsigned int name)
 {
@@ -531,15 +543,15 @@
 }
 EXPORT_SYMBOL(kgsl_mmu_putpagetable);
 
-void kgsl_setstate(struct kgsl_device *device, uint32_t flags)
+void kgsl_setstate(struct kgsl_mmu *mmu, uint32_t flags)
 {
-	struct kgsl_mmu *mmu = &device->mmu;
+	struct kgsl_device *device = mmu->device;
 	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
 		return;
 	else if (device->ftbl->setstate)
 		device->ftbl->setstate(device, flags);
 	else if (mmu->mmu_ops->mmu_device_setstate)
-		mmu->mmu_ops->mmu_device_setstate(device, flags);
+		mmu->mmu_ops->mmu_device_setstate(mmu, flags);
 }
 EXPORT_SYMBOL(kgsl_setstate);
 
@@ -549,7 +561,7 @@
 	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
 		return;
 	else if (mmu->mmu_ops->mmu_device_setstate)
-		mmu->mmu_ops->mmu_device_setstate(device, flags);
+		mmu->mmu_ops->mmu_device_setstate(mmu, flags);
 }
 EXPORT_SYMBOL(kgsl_mmu_device_setstate);
 
@@ -589,7 +601,14 @@
 
 	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
 		if (memdesc->sglen == 1) {
-			memdesc->gpuaddr = sg_phys(memdesc->sg);
+			memdesc->gpuaddr = sg_dma_address(memdesc->sg);
+			if (!memdesc->gpuaddr)
+				memdesc->gpuaddr = sg_phys(memdesc->sg);
+			if (!memdesc->gpuaddr) {
+				KGSL_CORE_ERR("Unable to get a valid physical "
+					"address for memdesc\n");
+				return -EINVAL;
+			}
 			return 0;
 		} else {
 			KGSL_CORE_ERR("Memory is not contigious "
@@ -621,7 +640,8 @@
 
 	if (KGSL_MMU_TYPE_IOMMU != kgsl_mmu_get_mmutype())
 		spin_lock(&pagetable->lock);
-	ret = pagetable->pt_ops->mmu_map(pagetable->priv, memdesc, protflags);
+	ret = pagetable->pt_ops->mmu_map(pagetable->priv, memdesc, protflags,
+						&pagetable->tlb_flags);
 	if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype())
 		spin_lock(&pagetable->lock);
 
@@ -733,7 +753,7 @@
 	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE)
 		return 0;
 	else
-		return mmu->mmu_ops->mmu_stop(device);
+		return mmu->mmu_ops->mmu_stop(mmu);
 }
 EXPORT_SYMBOL(kgsl_mmu_stop);
 
@@ -741,20 +761,30 @@
 {
 	struct kgsl_mmu *mmu = &device->mmu;
 
-	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE)
+	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
+		kgsl_sharedmem_free(&mmu->setstate_memory);
 		return 0;
-	else
-		return mmu->mmu_ops->mmu_close(device);
+	} else {
+		return mmu->mmu_ops->mmu_close(mmu);
+	}
 }
 EXPORT_SYMBOL(kgsl_mmu_close);
 
 int kgsl_mmu_pt_get_flags(struct kgsl_pagetable *pt,
 			enum kgsl_deviceid id)
 {
-	if (KGSL_MMU_TYPE_GPU == kgsl_mmu_type)
-		return pt->pt_ops->mmu_pt_get_flags(pt, id);
-	else
+	unsigned int result = 0;
+
+	if (pt == NULL)
 		return 0;
+
+	spin_lock(&pt->lock);
+	if (pt->tlb_flags && (1<<id)) {
+		result = KGSL_MMUFLAGS_TLBFLUSH;
+		pt->tlb_flags &= ~(1<<id);
+	}
+	spin_unlock(&pt->lock);
+	return result;
 }
 EXPORT_SYMBOL(kgsl_mmu_pt_get_flags);
 
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index bff41bf..e35f368 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -112,35 +112,37 @@
 		unsigned int max_entries;
 	} stats;
 	const struct kgsl_mmu_pt_ops *pt_ops;
+	unsigned int tlb_flags;
 	void *priv;
 };
 
+struct kgsl_mmu;
+
 struct kgsl_mmu_ops {
-	int (*mmu_init) (struct kgsl_device *device);
-	int (*mmu_close) (struct kgsl_device *device);
-	int (*mmu_start) (struct kgsl_device *device);
-	int (*mmu_stop) (struct kgsl_device *device);
-	void (*mmu_setstate) (struct kgsl_device *device,
+	int (*mmu_init) (struct kgsl_mmu *mmu);
+	int (*mmu_close) (struct kgsl_mmu *mmu);
+	int (*mmu_start) (struct kgsl_mmu *mmu);
+	int (*mmu_stop) (struct kgsl_mmu *mmu);
+	void (*mmu_setstate) (struct kgsl_mmu *mmu,
 		struct kgsl_pagetable *pagetable);
-	void (*mmu_device_setstate) (struct kgsl_device *device,
+	void (*mmu_device_setstate) (struct kgsl_mmu *mmu,
 					uint32_t flags);
-	void (*mmu_pagefault) (struct kgsl_device *device);
+	void (*mmu_pagefault) (struct kgsl_mmu *mmu);
 	unsigned int (*mmu_get_current_ptbase)
-			(struct kgsl_device *device);
+			(struct kgsl_mmu *mmu);
 };
 
 struct kgsl_mmu_pt_ops {
 	int (*mmu_map) (void *mmu_pt,
 			struct kgsl_memdesc *memdesc,
-			unsigned int protflags);
+			unsigned int protflags,
+			unsigned int *tlb_flags);
 	int (*mmu_unmap) (void *mmu_pt,
 			struct kgsl_memdesc *memdesc);
 	void *(*mmu_create_pagetable) (void);
 	void (*mmu_destroy_pagetable) (void *pt);
 	int (*mmu_pt_equal) (struct kgsl_pagetable *pt,
 			unsigned int pt_base);
-	unsigned int (*mmu_pt_get_flags) (struct kgsl_pagetable *pt,
-				enum kgsl_deviceid id);
 };
 
 struct kgsl_mmu {
@@ -177,7 +179,7 @@
 int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
 		    struct kgsl_memdesc *memdesc);
 unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
-void kgsl_setstate(struct kgsl_device *device, uint32_t flags);
+void kgsl_setstate(struct kgsl_mmu *mmu, uint32_t flags);
 void kgsl_mmu_device_setstate(struct kgsl_device *device, uint32_t flags);
 void kgsl_mmu_setstate(struct kgsl_device *device,
 			struct kgsl_pagetable *pt);
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index b2b3071..47b6bb2 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -244,8 +244,8 @@
 void kgsl_pwrscale_idle(struct kgsl_device *device)
 {
 	if (PWRSCALE_ACTIVE(device) && device->pwrscale.policy->idle)
-		if (device->requested_state !=
-			(KGSL_STATE_SLUMBER | KGSL_STATE_SLEEP))
+		if (device->requested_state != KGSL_STATE_SLUMBER &&
+			device->requested_state != KGSL_STATE_SLEEP)
 			device->pwrscale.policy->idle(device,
 					&device->pwrscale);
 	device->pwrscale.gpu_busy = 0;
diff --git a/drivers/gpu/msm/kgsl_pwrscale_msm.c b/drivers/gpu/msm/kgsl_pwrscale_msm.c
index f77a02b..61d4b2d 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_msm.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_msm.c
@@ -16,6 +16,7 @@
 #include "kgsl.h"
 #include "kgsl_pwrscale.h"
 #include "kgsl_device.h"
+#include "a2xx_reg.h"
 
 struct msm_priv {
 	struct kgsl_device *device;
@@ -97,7 +98,11 @@
 			struct kgsl_pwrscale *pwrscale)
 {
 	struct msm_priv *priv = pwrscale->priv;
-	if (priv->enabled && pwrscale->gpu_busy)
+	unsigned int rb_rptr, rb_wptr;
+	kgsl_regread(device, REG_CP_RB_RPTR, &rb_rptr);
+	kgsl_regread(device, REG_CP_RB_WPTR, &rb_wptr);
+
+	if (priv->enabled && (rb_rptr == rb_wptr))
 		msm_dcvs_idle(priv->handle, MSM_DCVS_IDLE_ENTER, 0);
 
 	return;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index c8db702..24ea571 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -511,6 +511,8 @@
 	KGSL_DRV_ERR(device, "snapshot created at va %p pa %lx size %d\n",
 			device->snapshot, __pa(device->snapshot),
 			device->snapshot_size);
+	if (hang)
+		sysfs_notify(&device->snapshot_kobj, NULL, "timestamp");
 	return 0;
 }
 EXPORT_SYMBOL(kgsl_device_snapshot);
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 8c29535..3ca9e18 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -206,11 +206,10 @@
 	},
 };
 
-static irqreturn_t z180_isr(int irq, void *data)
+static irqreturn_t z180_irq_handler(struct kgsl_device *device)
 {
 	irqreturn_t result = IRQ_NONE;
 	unsigned int status;
-	struct kgsl_device *device = (struct kgsl_device *) data;
 	struct z180_device *z180_dev = Z180_DEVICE(device);
 
 	z180_regread(device, ADDR_VGC_IRQSTATUS >> 2, &status);
@@ -469,8 +468,9 @@
 		cnt = PACKETSIZE_STATESTREAM;
 		ofs = 0;
 	}
-	kgsl_setstate(device, kgsl_mmu_pt_get_flags(device->mmu.hwpagetable,
-						    device->id));
+	kgsl_setstate(&device->mmu,
+			kgsl_mmu_pt_get_flags(device->mmu.hwpagetable,
+			device->id));
 
 	result = wait_event_interruptible_timeout(device->wait_queue,
 				  room_in_rb(z180_dev),
@@ -546,7 +546,7 @@
 	if (status != 0)
 		goto error;
 
-	status = kgsl_device_platform_probe(device, z180_isr);
+	status = kgsl_device_platform_probe(device);
 	if (status)
 		goto error_close_ringbuffer;
 
@@ -882,7 +882,7 @@
 	if (z180_dev->ringbuffer.prevctx == context->id) {
 		z180_dev->ringbuffer.prevctx = Z180_INVALID_CONTEXT;
 		device->mmu.hwpagetable = device->mmu.defaultpagetable;
-		kgsl_setstate(device, KGSL_MMUFLAGS_PTUPDATE);
+		kgsl_setstate(&device->mmu, KGSL_MMUFLAGS_PTUPDATE);
 	}
 }
 
@@ -945,6 +945,7 @@
 	.power_stats = z180_power_stats,
 	.irqctrl = z180_irqctrl,
 	.gpuid = z180_gpuid,
+	.irq_handler = z180_irq_handler,
 	/* Optional functions */
 	.drawctxt_create = NULL,
 	.drawctxt_destroy = z180_drawctxt_destroy,
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index daa0b58..0bd9cbc 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -805,7 +805,7 @@
 	},
 };
 
-static int epm_adc_probe(struct platform_device *pdev)
+static int __devinit epm_adc_probe(struct platform_device *pdev)
 {
 	struct epm_adc_drv *epm_adc;
 	struct epm_adc_platform_data *pdata = pdev->dev.platform_data;
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 0eeb338..3238d33 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -2209,7 +2209,7 @@
 	.release	= single_release,
 };
 
-static void __init mxt_debugfs_init(struct mxt_data *data)
+static void __devinit mxt_debugfs_init(struct mxt_data *data)
 {
 	debug_base = debugfs_create_dir(MXT_DEBUGFS_DIR, NULL);
 	if (IS_ERR_OR_NULL(debug_base))
diff --git a/drivers/input/touchscreen/msm_ts.c b/drivers/input/touchscreen/msm_ts.c
index 122b45d..eb2e73b 100644
--- a/drivers/input/touchscreen/msm_ts.c
+++ b/drivers/input/touchscreen/msm_ts.c
@@ -1,7 +1,7 @@
 /* drivers/input/touchscreen/msm_ts.c
  *
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -207,7 +207,7 @@
 #undef __dump_tssc_reg
 }
 
-static int __devinit msm_ts_hw_init(struct msm_ts *ts)
+static int msm_ts_hw_init(struct msm_ts *ts)
 {
 	uint32_t tmp;
 
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index 741c3a1..acf551e 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -2157,6 +2157,7 @@
 	marimba_set_fm_status(radio->marimba, false);
 	wait_for_completion(&radio->shutdown_done);
 	radio->handle_irq = 1;
+	radio->lp_mode = 1;
 	atomic_inc(&radio->users);
 	radio->marimba->mod_id = SLAVE_ID_BAHAMA;
 	flush_workqueue(radio->wqueue);
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index 6744479..6d8cc5c 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -87,7 +87,7 @@
 	rcdev->input_name = GPIO_IR_DEVICE_NAME;
 	rcdev->input_id.bustype = BUS_HOST;
 	rcdev->driver_name = GPIO_IR_DRIVER_NAME;
-	rcdev->map_name = RC_MAP_EMPTY;
+	rcdev->map_name = RC_MAP_RC6_PHILIPS;
 
 	gpio_dev->rcdev = rcdev;
 	gpio_dev->gpio_nr = pdata->gpio_nr;
@@ -115,6 +115,8 @@
 	if (rc < 0)
 		goto err_request_irq;
 
+	device_init_wakeup(pdata->can_wakeup);
+
 	return 0;
 
 err_request_irq:
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 3dea4e9..4fd6e49 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -3,10 +3,10 @@
 CFLAGS_REMOVE_msm_vfe8x.o = -Wframe-larger-than=1024
 endif
 
+EXTRA_CFLAGS += -Idrivers/media/video/msm/io
 obj-$(CONFIG_MSM_CAMERA) += io/
 ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
   EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
-  EXTRA_CFLAGS += -Idrivers/media/video/msm/io
   EXTRA_CFLAGS += -Idrivers/media/video/msm/sensors
   obj-$(CONFIG_MSM_CAMERA) += msm_isp.o msm.o msm_mem.o msm_mctl.o msm_mctl_buf.o msm_mctl_pp.o
   obj-$(CONFIG_MSM_CAMERA) += sensors/ actuators/ csi/
diff --git a/drivers/media/video/msm/csi/msm_csic.c b/drivers/media/video/msm/csi/msm_csic.c
index 00828c9..b4adbaf 100644
--- a/drivers/media/video/msm/csi/msm_csic.c
+++ b/drivers/media/video/msm/csi/msm_csic.c
@@ -285,6 +285,7 @@
 		if (rc < 0) {
 			csic_dev->hw_version = 0;
 			iounmap(csic_dev->base);
+			csic_dev->base = NULL;
 			return rc;
 		}
 	}
@@ -427,6 +428,7 @@
 	}
 	disable_irq(new_csic_dev->irq->start);
 	iounmap(new_csic_dev->base);
+	new_csic_dev->base = NULL;
 
 	new_csic_dev->pdev = pdev;
 	return 0;
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index 1ecbfca..0cd2cf0 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -224,6 +224,7 @@
 		ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
 vreg_config_failed:
 	iounmap(csid_dev->base);
+	csid_dev->base = NULL;
 	return rc;
 }
 
@@ -244,6 +245,7 @@
 		ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
 
 	iounmap(csid_dev->base);
+	csid_dev->base = NULL;
 	return 0;
 }
 
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
index 36385ca..aef017f 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.c
+++ b/drivers/media/video/msm/csi/msm_csiphy.c
@@ -201,6 +201,7 @@
 
 	if (rc < 0) {
 		iounmap(csiphy_dev->base);
+		csiphy_dev->base = NULL;
 		return rc;
 	}
 
@@ -231,6 +232,7 @@
 		csiphy_dev->csiphy_clk, ARRAY_SIZE(csiphy_clk_info), 0);
 
 	iounmap(csiphy_dev->base);
+	csiphy_dev->base = NULL;
 	return 0;
 }
 
diff --git a/drivers/media/video/msm/gemini/msm_gemini_platform.c b/drivers/media/video/msm/gemini/msm_gemini_platform.c
index ee0ff2f..fb5b035 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_platform.c
+++ b/drivers/media/video/msm/gemini/msm_gemini_platform.c
@@ -20,6 +20,7 @@
 #include <mach/msm_subsystem_map.h>
 
 #include "msm_gemini_platform.h"
+#include "msm_gemini_sync.h"
 #include "msm_gemini_common.h"
 #include "msm_gemini_hw.h"
 
@@ -80,6 +81,20 @@
 	return 0;
 }
 
+static struct msm_cam_clk_info gemini_8x_clk_info[] = {
+	{"ijpeg_clk", 228571000},
+	{"ijpeg_pclk", -1},
+};
+
+static struct msm_cam_clk_info gemini_7x_clk_info[] = {
+	{"jpeg_clk", 153600000},
+	{"jpeg_pclk", -1},
+};
+
+static struct msm_cam_clk_info gemini_imem_clk_info[] = {
+	{"imem_clk", -1},
+};
+
 int msm_gemini_platform_init(struct platform_device *pdev,
 	struct resource **mem,
 	void **base,
@@ -91,6 +106,8 @@
 	int gemini_irq;
 	struct resource *gemini_mem, *gemini_io, *gemini_irq_res;
 	void *gemini_base;
+	struct msm_gemini_device *pgmn_dev =
+		(struct msm_gemini_device *) context;
 
 	gemini_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!gemini_mem) {
@@ -119,10 +136,43 @@
 		goto fail1;
 	}
 
-	rc = msm_camio_jpeg_clk_enable();
-	if (rc) {
-		GMN_PR_ERR("%s: clk failed rc = %d\n", __func__, rc);
-		goto fail2;
+	pgmn_dev->hw_version = GEMINI_8X60;
+	rc = msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_8x_clk_info,
+	 pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_8x_clk_info), 1);
+	if (rc < 0) {
+		pgmn_dev->hw_version = GEMINI_7X;
+		rc = msm_cam_clk_enable(&pgmn_dev->pdev->dev,
+			gemini_7x_clk_info, pgmn_dev->gemini_clk,
+			ARRAY_SIZE(gemini_7x_clk_info), 1);
+		if (rc < 0) {
+			GMN_PR_ERR("%s: clk failed rc = %d\n", __func__, rc);
+			goto fail2;
+		}
+	} else {
+		rc = msm_cam_clk_enable(&pgmn_dev->pdev->dev,
+				gemini_imem_clk_info, &pgmn_dev->gemini_clk[2],
+				ARRAY_SIZE(gemini_imem_clk_info), 1);
+		if (!rc)
+			pgmn_dev->hw_version = GEMINI_8960;
+	}
+
+	if (pgmn_dev->hw_version != GEMINI_7X) {
+		if (pgmn_dev->gemini_fs == NULL) {
+			pgmn_dev->gemini_fs =
+				regulator_get(&pgmn_dev->pdev->dev, "fs_ijpeg");
+			if (IS_ERR(pgmn_dev->gemini_fs)) {
+				pr_err("%s: Regulator FS_ijpeg get failed %ld\n",
+					__func__, PTR_ERR(pgmn_dev->gemini_fs));
+				pgmn_dev->gemini_fs = NULL;
+				goto gemini_fs_failed;
+			} else if (regulator_enable(pgmn_dev->gemini_fs)) {
+				pr_err("%s: Regulator FS_ijpeg enable failed\n",
+								__func__);
+				regulator_put(pgmn_dev->gemini_fs);
+				pgmn_dev->gemini_fs = NULL;
+				goto gemini_fs_failed;
+			}
+		}
 	}
 
 	msm_gemini_hw_init(gemini_base, resource_size(gemini_mem));
@@ -146,7 +196,21 @@
 	return rc;
 
 fail3:
-	msm_camio_jpeg_clk_disable();
+	if (pgmn_dev->hw_version != GEMINI_7X) {
+		regulator_disable(pgmn_dev->gemini_fs);
+		regulator_put(pgmn_dev->gemini_fs);
+		pgmn_dev->gemini_fs = NULL;
+	}
+gemini_fs_failed:
+	if (pgmn_dev->hw_version == GEMINI_8960)
+		msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_imem_clk_info,
+		 &pgmn_dev->gemini_clk[2], ARRAY_SIZE(gemini_imem_clk_info), 0);
+	if (pgmn_dev->hw_version != GEMINI_7X)
+		msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_8x_clk_info,
+		pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_8x_clk_info), 0);
+	else
+		msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_7x_clk_info,
+		pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_7x_clk_info), 0);
 fail2:
 	iounmap(gemini_base);
 fail1:
@@ -158,10 +222,28 @@
 int msm_gemini_platform_release(struct resource *mem, void *base, int irq,
 	void *context)
 {
-	int result;
+	int result = 0;
+	struct msm_gemini_device *pgmn_dev =
+		(struct msm_gemini_device *) context;
 
 	free_irq(irq, context);
-	result = msm_camio_jpeg_clk_disable();
+
+	if (pgmn_dev->hw_version != GEMINI_7X) {
+		regulator_disable(pgmn_dev->gemini_fs);
+		regulator_put(pgmn_dev->gemini_fs);
+		pgmn_dev->gemini_fs = NULL;
+	}
+
+	if (pgmn_dev->hw_version == GEMINI_8960)
+		msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_imem_clk_info,
+		 &pgmn_dev->gemini_clk[2], ARRAY_SIZE(gemini_imem_clk_info), 0);
+	if (pgmn_dev->hw_version != GEMINI_7X)
+		msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_8x_clk_info,
+		pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_8x_clk_info), 0);
+	else
+		msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_7x_clk_info,
+		pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_7x_clk_info), 0);
+
 	iounmap(base);
 	release_mem_region(mem->start, resource_size(mem));
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
diff --git a/drivers/media/video/msm/gemini/msm_gemini_sync.h b/drivers/media/video/msm/gemini/msm_gemini_sync.h
index a47e766..1c6726d 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_sync.h
+++ b/drivers/media/video/msm/gemini/msm_gemini_sync.h
@@ -21,6 +21,10 @@
 #include <media/v4l2-subdev.h>
 #include "msm_gemini_core.h"
 
+#define GEMINI_7X 0x1
+#define GEMINI_8X60 (0x1 << 1)
+#define GEMINI_8960 (0x1 << 2)
+
 struct msm_gemini_q {
 	char const	*name;
 	struct list_head  q;
@@ -39,6 +43,9 @@
 	struct resource        *mem;
 	int                     irq;
 	void                   *base;
+	struct clk *gemini_clk[3];
+	struct regulator *gemini_fs;
+	uint32_t hw_version;
 
 	struct device *device;
 	struct cdev   cdev;
diff --git a/drivers/media/video/msm/io/msm_io_8960.c b/drivers/media/video/msm/io/msm_io_8960.c
index 1ab4223..f9c454a 100644
--- a/drivers/media/video/msm/io/msm_io_8960.c
+++ b/drivers/media/video/msm/io/msm_io_8960.c
@@ -27,141 +27,11 @@
 
 #define BUFF_SIZE_128 128
 
-static struct clk *camio_jpeg_clk;
-static struct clk *camio_jpeg_pclk;
-static struct clk *camio_imem_clk;
-static struct regulator *fs_ijpeg;
-
-int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
-{
-	int rc = 0;
-	struct clk *clk = NULL;
-
-	switch (clktype) {
-	case CAMIO_JPEG_CLK:
-		camio_jpeg_clk =
-		clk = clk_get(NULL, "ijpeg_clk");
-		clk_set_rate(clk, 228571000);
-		break;
-
-	case CAMIO_JPEG_PCLK:
-		camio_jpeg_pclk =
-		clk = clk_get(NULL, "ijpeg_pclk");
-		break;
-
-	case CAMIO_IMEM_CLK:
-		camio_imem_clk =
-		clk = clk_get(NULL, "imem_clk");
-		break;
-
-	default:
-		break;
-	}
-
-	if (!IS_ERR(clk))
-		rc = clk_enable(clk);
-	else
-		rc = PTR_ERR(clk);
-
-	if (rc < 0)
-		pr_err("%s(%d) failed %d\n", __func__, clktype, rc);
-
-	return rc;
-}
-
-int msm_camio_clk_disable(enum msm_camio_clk_type clktype)
-{
-	int rc = 0;
-	struct clk *clk = NULL;
-
-	switch (clktype) {
-	case CAMIO_JPEG_CLK:
-		clk = camio_jpeg_clk;
-		break;
-
-	case CAMIO_JPEG_PCLK:
-		clk = camio_jpeg_pclk;
-		break;
-
-	case CAMIO_IMEM_CLK:
-		clk = camio_imem_clk;
-		break;
-
-	default:
-		break;
-	}
-
-	if (!IS_ERR(clk)) {
-		clk_disable(clk);
-		clk_put(clk);
-	} else
-		rc = PTR_ERR(clk);
-
-	if (rc < 0)
-		pr_err("%s(%d) failed %d\n", __func__, clktype, rc);
-
-	return rc;
-}
-
 void msm_camio_clk_rate_set_2(struct clk *clk, int rate)
 {
 	clk_set_rate(clk, rate);
 }
 
-int msm_camio_jpeg_clk_disable(void)
-{
-	int rc = 0;
-	rc = msm_camio_clk_disable(CAMIO_JPEG_PCLK);
-	if (rc < 0)
-		return rc;
-	rc = msm_camio_clk_disable(CAMIO_JPEG_CLK);
-	if (rc < 0)
-		return rc;
-	rc = msm_camio_clk_disable(CAMIO_IMEM_CLK);
-	if (rc < 0)
-		return rc;
-
-	if (fs_ijpeg) {
-		rc = regulator_disable(fs_ijpeg);
-		if (rc < 0) {
-			pr_err("%s: Regulator disable failed %d\n",
-						__func__, rc);
-			return rc;
-		}
-		regulator_put(fs_ijpeg);
-	}
-	CDBG("%s: exit %d\n", __func__, rc);
-	return rc;
-}
-
-int msm_camio_jpeg_clk_enable(void)
-{
-	int rc = 0;
-	fs_ijpeg = regulator_get(NULL, "fs_ijpeg");
-	if (IS_ERR(fs_ijpeg)) {
-		pr_err("%s: Regulator FS_IJPEG get failed %ld\n",
-			__func__, PTR_ERR(fs_ijpeg));
-		fs_ijpeg = NULL;
-	} else if (regulator_enable(fs_ijpeg)) {
-		pr_err("%s: Regulator FS_IJPEG enable failed\n", __func__);
-		regulator_put(fs_ijpeg);
-	}
-
-	rc = msm_camio_clk_enable(CAMIO_JPEG_CLK);
-	if (rc < 0)
-		return rc;
-	rc = msm_camio_clk_enable(CAMIO_JPEG_PCLK);
-	if (rc < 0)
-		return rc;
-
-	rc = msm_camio_clk_enable(CAMIO_IMEM_CLK);
-	if (rc < 0)
-		return rc;
-
-	CDBG("%s: exit %d\n", __func__, rc);
-	return rc;
-}
-
 void msm_camio_bus_scale_cfg(struct msm_bus_scale_pdata *cam_bus_scale_table,
 		enum msm_bus_perf_setting perf_setting)
 {
diff --git a/drivers/media/video/msm/io/msm_io_8x60.c b/drivers/media/video/msm/io/msm_io_8x60.c
index 4e8dc25..baa1245 100644
--- a/drivers/media/video/msm/io/msm_io_8x60.c
+++ b/drivers/media/video/msm/io/msm_io_8x60.c
@@ -85,12 +85,9 @@
 static struct clk *camio_csi0_pclk;
 static struct clk *camio_csi1_pclk;
 static struct clk *camio_vfe_pclk;
-static struct clk *camio_jpeg_clk;
-static struct clk *camio_jpeg_pclk;
 static struct clk *camio_vpe_clk;
 static struct clk *camio_vpe_pclk;
 static struct regulator *fs_vfe;
-static struct regulator *fs_ijpeg;
 static struct regulator *fs_vpe;
 static struct regulator *ldo15;
 static struct regulator *lvs0;
@@ -254,17 +251,6 @@
 		clk = clk_get(&camio_dev->dev, "csi_pclk");
 		break;
 
-	case CAMIO_JPEG_CLK:
-		camio_jpeg_clk =
-		clk = clk_get(NULL, "ijpeg_clk");
-		msm_camio_clk_rate_set_2(clk, 228571000);
-		break;
-
-	case CAMIO_JPEG_PCLK:
-		camio_jpeg_pclk =
-		clk = clk_get(NULL, "ijpeg_pclk");
-		break;
-
 	case CAMIO_VPE_CLK:
 		camio_vpe_clk =
 		clk = clk_get(NULL, "vpe_clk");
@@ -334,14 +320,6 @@
 		clk = camio_csi1_pclk;
 		break;
 
-	case CAMIO_JPEG_CLK:
-		clk = camio_jpeg_clk;
-		break;
-
-	case CAMIO_JPEG_PCLK:
-		clk = camio_jpeg_pclk;
-		break;
-
 	case CAMIO_VPE_CLK:
 		clk = camio_vpe_clk;
 		break;
@@ -393,47 +371,6 @@
 	return IRQ_HANDLED;
 }
 
-int msm_camio_jpeg_clk_disable(void)
-{
-	int rc = 0;
-	if (fs_ijpeg) {
-		rc = regulator_disable(fs_ijpeg);
-		if (rc < 0) {
-			CDBG("%s: Regulator disable failed %d\n", __func__, rc);
-			return rc;
-		}
-		regulator_put(fs_ijpeg);
-	}
-	rc = msm_camio_clk_disable(CAMIO_JPEG_PCLK);
-	if (rc < 0)
-		return rc;
-	rc = msm_camio_clk_disable(CAMIO_JPEG_CLK);
-	CDBG("%s: exit %d\n", __func__, rc);
-	return rc;
-}
-
-int msm_camio_jpeg_clk_enable(void)
-{
-	int rc = 0;
-	rc = msm_camio_clk_enable(CAMIO_JPEG_CLK);
-	if (rc < 0)
-		return rc;
-	rc = msm_camio_clk_enable(CAMIO_JPEG_PCLK);
-	if (rc < 0)
-		return rc;
-	fs_ijpeg = regulator_get(NULL, "fs_ijpeg");
-	if (IS_ERR(fs_ijpeg)) {
-		CDBG("%s: Regulator FS_IJPEG get failed %ld\n", __func__,
-			PTR_ERR(fs_ijpeg));
-		fs_ijpeg = NULL;
-	} else if (regulator_enable(fs_ijpeg)) {
-		CDBG("%s: Regulator FS_IJPEG enable failed\n", __func__);
-		regulator_put(fs_ijpeg);
-	}
-	CDBG("%s: exit %d\n", __func__, rc);
-	return rc;
-}
-
 int msm_camio_vpe_clk_disable(void)
 {
 	int rc = 0;
diff --git a/drivers/media/video/msm/io/msm_io_vfe31.c b/drivers/media/video/msm/io/msm_io_vfe31.c
index 7f3b7ae..24bba59 100644
--- a/drivers/media/video/msm/io/msm_io_vfe31.c
+++ b/drivers/media/video/msm/io/msm_io_vfe31.c
@@ -108,8 +108,6 @@
 static struct clk *camio_csi_clk;
 static struct clk *camio_csi_pclk;
 static struct clk *camio_csi_vfe_clk;
-static struct clk *camio_jpeg_clk;
-static struct clk *camio_jpeg_pclk;
 static struct clk *camio_vpe_clk;
 static struct regulator *fs_vpe;
 static struct msm_camera_io_ext camio_ext;
@@ -117,7 +115,6 @@
 static struct resource *camifpadio, *csiio;
 void __iomem *camifpadbase, *csibase;
 static uint32_t vpe_clk_rate;
-static uint32_t jpeg_clk_rate;
 
 static struct regulator_bulk_data regs[] = {
 	{ .supply = "gp2",  .min_uV = 2600000, .max_uV = 2600000 },
@@ -239,16 +236,6 @@
 		clk = clk_get(NULL, "csi_pclk");
 		break;
 
-	case CAMIO_JPEG_CLK:
-		camio_jpeg_clk =
-		clk = clk_get(NULL, "jpeg_clk");
-		jpeg_clk_rate = clk_round_rate(clk, 144000000);
-		clk_set_rate(clk, jpeg_clk_rate);
-		break;
-	case CAMIO_JPEG_PCLK:
-		camio_jpeg_pclk =
-		clk = clk_get(NULL, "jpeg_pclk");
-		break;
 	case CAMIO_VPE_CLK:
 		camio_vpe_clk =
 		clk = clk_get(NULL, "vpe_clk");
@@ -308,12 +295,6 @@
 	case CAMIO_CSI0_PCLK:
 		clk = camio_csi_pclk;
 		break;
-	case CAMIO_JPEG_CLK:
-		clk = camio_jpeg_clk;
-		break;
-	case CAMIO_JPEG_PCLK:
-		clk = camio_jpeg_pclk;
-		break;
 	case CAMIO_VPE_CLK:
 		clk = camio_vpe_clk;
 		break;
@@ -356,22 +337,6 @@
 	return IRQ_HANDLED;
 }
 
-int msm_camio_jpeg_clk_disable(void)
-{
-	msm_camio_clk_disable(CAMIO_JPEG_CLK);
-	msm_camio_clk_disable(CAMIO_JPEG_PCLK);
-	/* Need to add the code for remove PM QOS requirement */
-	return 0;
-}
-
-
-int msm_camio_jpeg_clk_enable(void)
-{
-	msm_camio_clk_enable(CAMIO_JPEG_CLK);
-	msm_camio_clk_enable(CAMIO_JPEG_PCLK);
-	return 0;
-}
-
 int msm_camio_vpe_clk_disable(void)
 {
 	msm_camio_clk_disable(CAMIO_VPE_CLK);
diff --git a/drivers/media/video/msm/io/msm_io_vfe31_v4l2.c b/drivers/media/video/msm/io/msm_io_vfe31_v4l2.c
index 451cb5a..a1270ea 100644
--- a/drivers/media/video/msm/io/msm_io_vfe31_v4l2.c
+++ b/drivers/media/video/msm/io/msm_io_vfe31_v4l2.c
@@ -33,12 +33,9 @@
 
 #define BUFF_SIZE_128 128
 
-static struct clk *camio_jpeg_clk;
 static struct clk *camio_vfe_clk;
-static struct clk *camio_jpeg_pclk;
 static struct clk *camio_vpe_clk;
 static struct clk *camio_vpe_pclk;
-static struct regulator *fs_ijpeg;
 static struct regulator *fs_vpe;
 
 static int vpe_clk_rate;
@@ -49,19 +46,6 @@
 	struct clk *clk = NULL;
 
 	switch (clktype) {
-	case CAMIO_JPEG_CLK:
-		camio_jpeg_clk =
-		clk = clk_get(NULL, "ijpeg_clk");
-		rc = clk_set_rate(clk, 228571000);
-		if (rc < 0)
-			rc = clk_set_rate(clk, 153600000);
-		break;
-
-	case CAMIO_JPEG_PCLK:
-		camio_jpeg_pclk =
-		clk = clk_get(NULL, "ijpeg_pclk");
-		break;
-
 	case CAMIO_VPE_CLK:
 		camio_vpe_clk =
 		clk = clk_get(NULL, "vpe_clk");
@@ -93,14 +77,6 @@
 	struct clk *clk = NULL;
 
 	switch (clktype) {
-	case CAMIO_JPEG_CLK:
-		clk = camio_jpeg_clk;
-		break;
-
-	case CAMIO_JPEG_PCLK:
-		clk = camio_jpeg_pclk;
-		break;
-
 	case CAMIO_VPE_CLK:
 		clk = camio_vpe_clk;
 		break;
@@ -138,47 +114,6 @@
 	clk_set_rate(clk, rate);
 }
 
-int msm_camio_jpeg_clk_disable(void)
-{
-	int rc = 0;
-	if (fs_ijpeg) {
-		rc = regulator_disable(fs_ijpeg);
-		if (rc < 0) {
-			CDBG("%s: Regulator disable failed %d\n", __func__, rc);
-			return rc;
-		}
-		regulator_put(fs_ijpeg);
-	}
-	rc = msm_camio_clk_disable(CAMIO_JPEG_PCLK);
-	if (rc < 0)
-		return rc;
-	rc = msm_camio_clk_disable(CAMIO_JPEG_CLK);
-	CDBG("%s: exit %d\n", __func__, rc);
-	return rc;
-}
-
-int msm_camio_jpeg_clk_enable(void)
-{
-	int rc = 0;
-	rc = msm_camio_clk_enable(CAMIO_JPEG_CLK);
-	if (rc < 0)
-		return rc;
-	rc = msm_camio_clk_enable(CAMIO_JPEG_PCLK);
-	if (rc < 0)
-		return rc;
-	fs_ijpeg = regulator_get(NULL, "fs_ijpeg");
-	if (IS_ERR(fs_ijpeg)) {
-		CDBG("%s: Regulator FS_IJPEG get failed %ld\n", __func__,
-			PTR_ERR(fs_ijpeg));
-		fs_ijpeg = NULL;
-	} else if (regulator_enable(fs_ijpeg)) {
-		CDBG("%s: Regulator FS_IJPEG enable failed\n", __func__);
-		regulator_put(fs_ijpeg);
-	}
-	CDBG("%s: exit %d\n", __func__, rc);
-	return rc;
-}
-
 int msm_camio_vpe_clk_disable(void)
 {
 	int rc = 0;
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index da38acc..ff97fa3 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -66,6 +66,33 @@
 	spin_unlock_irqrestore(&queue->lock, flags);
 }
 
+static void msm_drain_eventq(struct msm_device_queue *queue)
+{
+	unsigned long flags;
+	struct msm_queue_cmd *qcmd;
+	spin_lock_irqsave(&queue->lock, flags);
+	while (!list_empty(&queue->list)) {
+		qcmd = list_first_entry(&queue->list,
+			struct msm_queue_cmd, list_eventdata);
+		list_del_init(&qcmd->list_eventdata);
+		kfree(qcmd->command);
+		free_qcmd(qcmd);
+	}
+	spin_unlock_irqrestore(&queue->lock, flags);
+}
+
+static int32_t msm_find_free_queue(void)
+{
+	int i;
+	for (i = 0; i < NUM_SERVER_QUEUE; i++) {
+		struct msm_cam_server_queue *queue;
+		queue = &g_server_dev.server_queue[i];
+		if (!queue->queue_active)
+			return i;
+	}
+	return -EINVAL;
+}
+
 /* callback function from all subdevices of a msm_cam_v4l2_device */
 static void msm_cam_v4l2_subdev_notify(struct v4l2_subdev *sd,
 				unsigned int notification, void *arg)
@@ -86,29 +113,46 @@
 	}
 }
 
-static int msm_ctrl_cmd_done(void __user *arg)
+static int msm_ctrl_cmd_done(void *arg)
 {
 	void __user *uptr;
 	struct msm_queue_cmd *qcmd;
-	struct msm_ctrl_cmd *command = &g_server_dev.ctrl;
+	struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
+	struct msm_ctrl_cmd *command =
+		kzalloc(sizeof(struct msm_ctrl_cmd), GFP_KERNEL);
+	if (!command) {
+		pr_err("%s Insufficient memory. return", __func__);
+		return -ENOMEM;
+	}
 
 	D("%s\n", __func__);
-
-	if (copy_from_user(command, arg,
-			sizeof(struct msm_ctrl_cmd)))
+	if (copy_from_user(command, (void __user *)ioctl_ptr->ioctl_ptr,
+					   sizeof(struct msm_ctrl_cmd))) {
+		pr_err("%s: copy_from_user failed, size=%d\n",
+			   __func__, sizeof(struct msm_ctrl_cmd));
 		return -EINVAL;
+	}
 
+	g_server_dev.server_queue[command->queue_idx].ctrl = command;
+	if (command->evt_id !=
+		g_server_dev.server_queue[command->queue_idx].evt_id) {
+		pr_err("Invalid event id from userspace\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&g_server_dev.server_queue_lock);
 	qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
 	atomic_set(&qcmd->on_heap, 1);
 	uptr = command->value;
 	qcmd->command = command;
 
 	if (command->length > 0) {
-		command->value = g_server_dev.ctrl_data;
-		if (command->length > sizeof(g_server_dev.ctrl_data)) {
+		command->value =
+			g_server_dev.server_queue[command->queue_idx].ctrl_data;
+		if (command->length > max_control_command_size) {
 			pr_err("%s: user data %d is too big (max %d)\n",
 				__func__, command->length,
-				sizeof(g_server_dev.ctrl_data));
+				max_control_command_size);
 			free_qcmd(qcmd);
 			return -EINVAL;
 		}
@@ -117,8 +161,9 @@
 			return -EINVAL;
 		}
 	}
-
-	msm_enqueue(&g_server_dev.ctrl_q, &qcmd->list_control);
+	msm_enqueue(&g_server_dev.server_queue
+		[command->queue_idx].ctrl_q, &qcmd->list_control);
+	mutex_unlock(&g_server_dev.server_queue_lock);
 	return 0;
 }
 
@@ -129,8 +174,10 @@
 	int rc = 0;
 	void *value;
 	struct msm_queue_cmd *rcmd;
+	struct msm_queue_cmd *event_qcmd;
 	struct msm_ctrl_cmd *ctrlcmd;
-	struct msm_device_queue *queue =  &server_dev->ctrl_q;
+	struct msm_device_queue *queue =
+		&server_dev->server_queue[out->queue_idx].ctrl_q;
 
 	struct v4l2_event v4l2_evt;
 	struct msm_isp_event_ctrl *isp_event;
@@ -139,19 +186,38 @@
 		pr_err("%s Insufficient memory. return", __func__);
 		return -ENOMEM;
 	}
-	D("%s\n", __func__);
+	event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
+	if (!event_qcmd) {
+		pr_err("%s Insufficient memory. return", __func__);
+		return -ENOMEM;
+	}
 
+	D("%s\n", __func__);
+	mutex_lock(&server_dev->server_queue_lock);
+	if (++server_dev->server_evt_id == 0)
+		server_dev->server_evt_id++;
+
+	server_dev->server_queue[out->queue_idx].evt_id =
+		server_dev->server_evt_id;
 	v4l2_evt.type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_V4L2;
+	v4l2_evt.u.data[0] = out->queue_idx;
 	/* setup event object to transfer the command; */
-	*((uint32_t *)v4l2_evt.u.data) = (uint32_t)isp_event;
 	isp_event->resptype = MSM_CAM_RESP_V4L2;
 	isp_event->isp_data.ctrl = *out;
+	isp_event->isp_data.ctrl.evt_id = server_dev->server_evt_id;
+
+	atomic_set(&event_qcmd->on_heap, 1);
+	event_qcmd->command = isp_event;
+
+	msm_enqueue(&server_dev->server_queue[out->queue_idx].eventData_q,
+				&event_qcmd->list_eventdata);
+
 	/* now send command to config thread in userspace,
 	 * and wait for results */
 	v4l2_event_queue(server_dev->server_command_queue.pvdev,
 					  &v4l2_evt);
-
 	D("%s v4l2_event_queue: type = 0x%x\n", __func__, v4l2_evt.type);
+	mutex_unlock(&server_dev->server_queue_lock);
 
 	/* wait for config return status */
 	D("Waiting for config status\n");
@@ -163,9 +229,6 @@
 		if (!rc)
 			rc = -ETIMEDOUT;
 		if (rc < 0) {
-			rcmd = msm_dequeue(queue, list_control);
-			if (!rcmd)
-				free_qcmd(rcmd);
 			kfree(isp_event);
 			pr_err("%s: wait_event error %d\n", __func__, rc);
 			return rc;
@@ -184,6 +247,9 @@
 	memcpy(out, ctrlcmd, sizeof(struct msm_ctrl_cmd));
 	out->value = value;
 
+	kfree(ctrlcmd);
+	server_dev->server_queue[out->queue_idx].ctrl = NULL;
+
 	free_qcmd(rcmd);
 	kfree(isp_event);
 	D("%s: rc %d\n", __func__, rc);
@@ -201,7 +267,7 @@
 }
 
 /*send open command to server*/
-static int msm_send_open_server(int vnode_id)
+static int msm_send_open_server(struct msm_cam_v4l2_device *pcam)
 {
 	int rc = 0;
 	struct msm_ctrl_cmd ctrlcmd;
@@ -211,7 +277,8 @@
 	ctrlcmd.length	 = strnlen(g_server_dev.config_info.config_dev_name[0],
 				MAX_DEV_NAME_LEN)+1;
 	ctrlcmd.value    = (char *)g_server_dev.config_info.config_dev_name[0];
-	ctrlcmd.vnode_id = vnode_id;
+	ctrlcmd.vnode_id = pcam->vnode_id;
+	ctrlcmd.queue_idx = pcam->server_queue_idx;
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 
 	/* send command to config thread in usersspace, and get return value */
@@ -220,7 +287,7 @@
 	return rc;
 }
 
-static int msm_send_close_server(int vnode_id)
+static int msm_send_close_server(struct msm_cam_v4l2_device *pcam)
 {
 	int rc = 0;
 	struct msm_ctrl_cmd ctrlcmd;
@@ -230,7 +297,8 @@
 	ctrlcmd.length	 = strnlen(g_server_dev.config_info.config_dev_name[0],
 				MAX_DEV_NAME_LEN)+1;
 	ctrlcmd.value    = (char *)g_server_dev.config_info.config_dev_name[0];
-	ctrlcmd.vnode_id = vnode_id;
+	ctrlcmd.vnode_id = pcam->vnode_id;
+	ctrlcmd.queue_idx = pcam->server_queue_idx;
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 
 	/* send command to config thread in usersspace, and get return value */
@@ -275,6 +343,7 @@
 	ctrlcmd.value      = (void *)&plane_info;
 	ctrlcmd.timeout_ms = 10000;
 	ctrlcmd.vnode_id   = pcam->vnode_id;
+	ctrlcmd.queue_idx = pcam->server_queue_idx;
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 
 	/* send command to config thread in usersspace, and get return value */
@@ -339,6 +408,7 @@
 	ctrlcmd.value      = (void *)&plane_info;
 	ctrlcmd.timeout_ms = 10000;
 	ctrlcmd.vnode_id   = pcam->vnode_id;
+	ctrlcmd.queue_idx = pcam->server_queue_idx;
 
 	/* send command to config thread in usersspace, and get return value */
 	rc = msm_server_control(&g_server_dev, &ctrlcmd);
@@ -367,6 +437,7 @@
 	ctrlcmd.value    = NULL;
 	ctrlcmd.stream_type = pcam->dev_inst[idx]->image_mode;
 	ctrlcmd.vnode_id = pcam->vnode_id;
+	ctrlcmd.queue_idx = pcam->server_queue_idx;
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 
 
@@ -388,6 +459,7 @@
 	ctrlcmd.value       = NULL;
 	ctrlcmd.stream_type = pcam->dev_inst[idx]->image_mode;
 	ctrlcmd.vnode_id = pcam->vnode_id;
+	ctrlcmd.queue_idx = pcam->server_queue_idx;
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 
 	/* send command to config thread in usersspace, and get return value */
@@ -446,6 +518,7 @@
 	ctrlcmd.value = (void *)ctrl_data;
 	ctrlcmd.timeout_ms = 1000;
 	ctrlcmd.vnode_id = pcam->vnode_id;
+	ctrlcmd.queue_idx = pcam->server_queue_idx;
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 	/* send command to config thread in usersspace, and get return value */
 	rc = msm_server_control(&g_server_dev, &ctrlcmd);
@@ -499,6 +572,7 @@
 	memcpy(ctrlcmd.value, ctrl, ctrlcmd.length);
 	ctrlcmd.timeout_ms = 1000;
 	ctrlcmd.vnode_id = pcam->vnode_id;
+	ctrlcmd.queue_idx = pcam->server_queue_idx;
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 
 	/* send command to config thread in usersspace, and get return value */
@@ -530,6 +604,7 @@
 	memcpy(ctrlcmd.value, ctrl, ctrlcmd.length);
 	ctrlcmd.timeout_ms = 1000;
 	ctrlcmd.vnode_id = pcam->vnode_id;
+	ctrlcmd.queue_idx = pcam->server_queue_idx;
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 
 	/* send command to config thread in usersspace, and get return value */
@@ -556,6 +631,7 @@
 	memcpy(ctrlcmd.value, queryctrl, ctrlcmd.length);
 	ctrlcmd.timeout_ms = 1000;
 	ctrlcmd.vnode_id = pcam->vnode_id;
+	ctrlcmd.queue_idx = pcam->server_queue_idx;
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 
 	/* send command to config thread in userspace, and get return value */
@@ -666,6 +742,7 @@
 	ctrlcmd.value = (void *)crop;
 	ctrlcmd.timeout_ms = 1000;
 	ctrlcmd.vnode_id = pcam->vnode_id;
+	ctrlcmd.queue_idx = pcam->server_queue_idx;
 	ctrlcmd.stream_type = pcam->dev_inst[idx]->image_mode;
 	ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
 
@@ -1429,6 +1506,7 @@
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	int ion_client_created = 0;
 #endif
+	int server_q_idx = 0;
 	/*struct msm_isp_ops *p_isp = 0;*/
 	/* get the video device */
 	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
@@ -1449,6 +1527,11 @@
 		if (pcam->dev_inst[i] == NULL)
 			break;
 	}
+
+	server_q_idx = msm_find_free_queue();
+	if (server_q_idx < 0)
+		return server_q_idx;
+
 	/* if no instance is available, return error */
 	if (i == MSM_DEV_INST_MAX) {
 		mutex_unlock(&pcam->vid_lock);
@@ -1469,6 +1552,15 @@
 			pcam->vnode_id, pcam->use_count);
 	pcam->use_count++;
 	if (pcam->use_count == 1) {
+		struct msm_cam_server_queue *queue;
+		pcam->server_queue_idx = server_q_idx;
+		queue = &g_server_dev.server_queue[server_q_idx];
+		queue->ctrl = NULL;
+		queue->ctrl_data = kzalloc(sizeof(uint8_t) *
+				max_control_command_size, GFP_KERNEL);
+		msm_queue_init(&queue->ctrl_q, "control");
+		msm_queue_init(&queue->eventData_q, "eventdata");
+		queue->queue_active = 1;
 
 		rc = msm_cam_server_open_session(&g_server_dev, pcam);
 		if (rc < 0) {
@@ -1530,8 +1622,7 @@
 
 
 	if (pcam->use_count == 1) {
-		msm_queue_init(&g_server_dev.ctrl_q, "control");
-		rc = msm_send_open_server(pcam->vnode_id);
+		rc = msm_send_open_server(pcam);
 		if (rc < 0) {
 			mutex_unlock(&pcam->vid_lock);
 			pr_err("%s failed\n", __func__);
@@ -1630,6 +1721,7 @@
 	int rc = 0;
 	struct msm_cam_v4l2_device *pcam;
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	struct msm_cam_server_queue *queue;
 	pcam_inst = container_of(f->private_data,
 		struct msm_cam_v4l2_dev_inst, eventHandle);
 	pcam = pcam_inst->pcam;
@@ -1637,10 +1729,6 @@
 		pr_err("%s NULL pointer of camera device!\n", __func__);
 		return -EINVAL;
 	}
-	if (!g_server_dev.use_count) {
-		pr_err("%s: error, daemon not yet started.", __func__);
-		return -EINVAL;
-	}
 
 	mutex_lock(&pcam->vid_lock);
 
@@ -1679,7 +1767,7 @@
 			pr_err("msm_cam_server_close_session fails %d\n", rc);
 
 		if (g_server_dev.use_count > 0) {
-			rc = msm_send_close_server(pcam->vnode_id);
+			rc = msm_send_close_server(pcam);
 			if (rc < 0)
 				pr_err("msm_send_close_server failed %d\n", rc);
 		}
@@ -1691,6 +1779,14 @@
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		kref_put(&pcam->mctl.refcount, msm_release_ion_client);
 #endif
+		queue = &g_server_dev.server_queue[pcam->server_queue_idx];
+		queue->queue_active = 0;
+		kfree(queue->ctrl);
+		queue->ctrl = NULL;
+		kfree(queue->ctrl_data);
+		queue->ctrl_data = NULL;
+		msm_queue_drain(&queue->ctrl_q, list_control);
+		msm_drain_eventq(&queue->eventData_q);
 		if (g_server_dev.use_count == 0)
 			mutex_unlock(&g_server_dev.server_lock);
 	}
@@ -1741,23 +1837,23 @@
 
 	return rc;
 }
-static long msm_ioctl_server(struct file *fp, unsigned int cmd,
-	unsigned long arg)
+static long msm_ioctl_server(struct file *file, void *fh,
+		bool valid_prio, int cmd, void *arg)
 {
 	int rc = -EINVAL;
-	struct v4l2_event ev;
+	struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
 	struct msm_camera_info temp_cam_info;
 	struct msm_cam_config_dev_info temp_config_info;
 	struct msm_mctl_node_info temp_mctl_info;
-	struct v4l2_event_subscription temp_sub;
 	int i;
 
 	D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
 
 	switch (cmd) {
-	case MSM_CAM_IOCTL_GET_CAMERA_INFO:
-		if (copy_from_user(&temp_cam_info, (void __user *)arg,
-					  sizeof(struct msm_camera_info))) {
+	case MSM_CAM_V4L2_IOCTL_GET_CAMERA_INFO:
+		if (copy_from_user(&temp_cam_info,
+				(void __user *)ioctl_ptr->ioctl_ptr,
+				sizeof(struct msm_camera_info))) {
 			rc = -EINVAL;
 			return rc;
 		}
@@ -1781,18 +1877,20 @@
 		}
 		temp_cam_info.num_cameras =
 			g_server_dev.camera_info.num_cameras;
-		if (copy_to_user((void __user *)arg,
-							  &temp_cam_info,
+		if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
+				&temp_cam_info,
 				sizeof(struct msm_camera_info))) {
-			rc = -EINVAL;
-			return rc;
+					rc = -EINVAL;
+					return rc;
 		}
 		rc = 0;
 		break;
 
-	case MSM_CAM_IOCTL_GET_CONFIG_INFO:
-		if (copy_from_user(&temp_config_info, (void __user *)arg,
-				  sizeof(struct msm_cam_config_dev_info))) {
+	case MSM_CAM_V4L2_IOCTL_GET_CONFIG_INFO:
+		if (copy_from_user(&temp_config_info,
+				(void __user *)ioctl_ptr->ioctl_ptr,
+				sizeof(struct msm_cam_config_dev_info))) {
+
 			rc = -EINVAL;
 			return rc;
 		}
@@ -1808,7 +1906,7 @@
 		}
 		temp_config_info.num_config_nodes =
 			g_server_dev.config_info.num_config_nodes;
-		if (copy_to_user((void __user *)arg,
+		if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
 							  &temp_config_info,
 				sizeof(struct msm_cam_config_dev_info))) {
 			rc = -EINVAL;
@@ -1816,13 +1914,13 @@
 		}
 		rc = 0;
 		break;
-	case MSM_CAM_IOCTL_GET_MCTL_INFO:
-		if (copy_from_user(&temp_mctl_info, (void __user *)arg,
-				  sizeof(struct msm_mctl_node_info))) {
+	case MSM_CAM_V4L2_IOCTL_GET_MCTL_INFO:
+		if (copy_from_user(&temp_mctl_info,
+				(void __user *)ioctl_ptr->ioctl_ptr,
+				sizeof(struct msm_mctl_node_info))) {
 			rc = -EINVAL;
 			return rc;
 		}
-
 		for (i = 0; i < g_server_dev.mctl_node_info.num_mctl_nodes;
 				i++) {
 			if (copy_to_user((void __user *)
@@ -1836,7 +1934,7 @@
 		}
 		temp_mctl_info.num_mctl_nodes =
 			g_server_dev.mctl_node_info.num_mctl_nodes;
-		if (copy_to_user((void __user *)arg,
+		if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
 							  &temp_mctl_info,
 				sizeof(struct msm_mctl_node_info))) {
 			rc = -EINVAL;
@@ -1845,122 +1943,79 @@
 		rc = 0;
 	break;
 
-	case VIDIOC_SUBSCRIBE_EVENT:
-		if (copy_from_user(&temp_sub, (void __user *)arg,
-				  sizeof(struct v4l2_event_subscription))) {
+	case MSM_CAM_V4L2_IOCTL_CTRL_CMD_DONE:
+		D("%s: MSM_CAM_IOCTL_CTRL_CMD_DONE\n", __func__);
+		rc = msm_ctrl_cmd_done(arg);
+		break;
+
+	case MSM_CAM_V4L2_IOCTL_GET_EVENT_PAYLOAD: {
+		struct msm_queue_cmd *event_cmd;
+		struct msm_isp_event_ctrl u_isp_event;
+		struct msm_isp_event_ctrl *k_isp_event;
+		struct msm_device_queue *queue;
+		void __user *u_ctrl_value = NULL;
+		if (copy_from_user(&u_isp_event,
+			(void __user *)ioctl_ptr->ioctl_ptr,
+			sizeof(struct msm_isp_event_ctrl))) {
 			rc = -EINVAL;
 			return rc;
 		}
-		rc = msm_server_v4l2_subscribe_event
-			(&g_server_dev.server_command_queue.eventHandle,
-			 &temp_sub);
-		if (rc < 0)
+		queue = &g_server_dev.server_queue
+			[u_isp_event.isp_data.ctrl.queue_idx].eventData_q;
+		event_cmd = msm_dequeue(queue, list_eventdata);
+		if (!event_cmd) {
+			pr_err("%s: No event payload\n", __func__);
+			rc = -EINVAL;
 			return rc;
-
-		break;
-
-	case VIDIOC_DQEVENT: {
-		void __user *u_ctrl_value = NULL, *user_ptr = NULL;
-		struct msm_isp_event_ctrl u_isp_event;
-		struct msm_isp_event_ctrl *k_isp_event;
-
-		/* First, copy the event structure from userspace */
-		D("%s: VIDIOC_DQEVENT\n", __func__);
-		if (copy_from_user(&ev, (void __user *)arg,
-				sizeof(struct v4l2_event))) {
-			break;
 		}
-		/* Next, get the pointer to event_ctrl structure
-		 * embedded inside the v4l2_event.u.data array. */
-		user_ptr = (void __user *)(*((uint32_t *)ev.u.data));
-
-		/* Next, copy the userspace event ctrl structure */
-		if (copy_from_user((void *)&u_isp_event, user_ptr,
-				sizeof(struct msm_isp_event_ctrl))) {
-			break;
-		}
+		k_isp_event = (struct msm_isp_event_ctrl *)
+				event_cmd->command;
+		free_qcmd(event_cmd);
 
 		/* Save the pointer of the user allocated command buffer*/
 		u_ctrl_value = u_isp_event.isp_data.ctrl.value;
 
-		/* Dequeue the event queued into the v4l2 queue*/
-		rc = v4l2_event_dequeue(
-			&g_server_dev.server_command_queue.eventHandle,
-			&ev, fp->f_flags & O_NONBLOCK);
-		if (rc < 0) {
-			pr_err("no pending events?");
-			break;
-		}
-
-		/* Use k_isp_event to point to the event_ctrl structure
-		 * embedded inside v4l2_event.u.data */
-		k_isp_event = (struct msm_isp_event_ctrl *)
-				(*((uint32_t *)ev.u.data));
-		if (!k_isp_event) {
-			pr_err("%s Invalid event ctrl structure. ", __func__);
-			break;
-		}
-
 		/* Copy the event structure into user struct*/
 		u_isp_event = *k_isp_event;
 
 		/* Restore the saved pointer of the user
 		 * allocated command buffer. */
 		u_isp_event.isp_data.ctrl.value = u_ctrl_value;
-		if (ev.type == V4L2_EVENT_PRIVATE_START+MSM_CAM_RESP_V4L2) {
-			/* Copy the ctrl cmd, if present*/
-			if (k_isp_event->isp_data.ctrl.length > 0) {
-				void *k_ctrl_value =
-					k_isp_event->isp_data.ctrl.value;
-				if (copy_to_user(u_ctrl_value, k_ctrl_value,
-					 k_isp_event->isp_data.ctrl.length)) {
-					rc = -EINVAL;
-					break;
-				}
-			}
-			/* Copy the event ctrl structure back into
-			 * user's structure. */
-			if (copy_to_user(user_ptr, (void *)&u_isp_event,
-					 sizeof(struct msm_isp_event_ctrl))) {
+
+		/* Copy the ctrl cmd, if present*/
+		if (k_isp_event->isp_data.ctrl.length > 0) {
+			void *k_ctrl_value =
+				k_isp_event->isp_data.ctrl.value;
+			if (copy_to_user(u_ctrl_value, k_ctrl_value,
+				 k_isp_event->isp_data.ctrl.length)) {
 				rc = -EINVAL;
 				break;
 			}
 		}
-
-		/* Copy the v4l2_event structure back to the user*/
-		if (copy_to_user((void __user *)arg, &ev,
-				sizeof(struct v4l2_event))) {
+		if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
+							  &u_isp_event,
+				sizeof(struct msm_isp_event_ctrl))) {
 			rc = -EINVAL;
-			break;
+			return rc;
 		}
-		}
+		rc = 0;
 		break;
-
-	case MSM_CAM_IOCTL_CTRL_CMD_DONE:
-		D("%s: MSM_CAM_IOCTL_CTRL_CMD_DONE\n", __func__);
-		rc = msm_ctrl_cmd_done((void __user *)arg);
-		break;
-
+	}
 	default:
 		break;
 	}
 	return rc;
 }
 
-static int msm_open_server(struct inode *inode, struct file *fp)
+static int msm_open_server(struct file *fp)
 {
-	int rc;
+	int rc = 0;
 	D("%s: open %s\n", __func__, fp->f_path.dentry->d_name.name);
 	mutex_lock(&g_server_dev.server_lock);
-	rc = nonseekable_open(inode, fp);
-	if (rc < 0) {
-		pr_err("%s: nonseekable_open error %d\n", __func__, rc);
-		mutex_unlock(&g_server_dev.server_lock);
-		return rc;
-	}
 	g_server_dev.use_count++;
 	if (g_server_dev.use_count == 1)
-		msm_queue_init(&g_server_dev.ctrl_q, "control");
+		fp->private_data =
+			&g_server_dev.server_command_queue.eventHandle;
 	mutex_unlock(&g_server_dev.server_lock);
 	return rc;
 }
@@ -1982,8 +2037,9 @@
 	return rc;
 }
 
-static int msm_close_server(struct inode *inode, struct file *fp)
+static int msm_close_server(struct file *fp)
 {
+	D("%s\n", __func__);
 	mutex_lock(&g_server_dev.server_lock);
 	if (g_server_dev.use_count > 0)
 		g_server_dev.use_count--;
@@ -1999,7 +2055,6 @@
 			v4l2_event_queue(
 				g_server_dev.pcam_active->pvdev, &v4l2_ev);
 		}
-		msm_queue_drain(&g_server_dev.ctrl_q, list_control);
 	}
 	return 0;
 }
@@ -2269,14 +2324,19 @@
  * which will create a config device (/dev/config0/ and plug in
  * ISP's operation "v4l2_ioctl_ops*"
  */
-static const struct file_operations msm_fops_server = {
+static const struct v4l2_file_operations msm_fops_server = {
 	.owner = THIS_MODULE,
 	.open  = msm_open_server,
 	.poll  = msm_poll_server,
-	.unlocked_ioctl = msm_ioctl_server,
+	.unlocked_ioctl = video_ioctl2,
 	.release = msm_close_server,
 };
 
+static const struct v4l2_ioctl_ops msm_ioctl_ops_server = {
+	.vidioc_subscribe_event = msm_server_v4l2_subscribe_event,
+	.vidioc_default = msm_ioctl_server,
+};
+
 static const struct file_operations msm_fops_config = {
 	.owner = THIS_MODULE,
 	.open  = msm_open_config,
@@ -2379,53 +2439,70 @@
 
 }
 
-static int msm_setup_server_dev(int node, char *device_name)
+static int msm_setup_server_dev(struct platform_device *pdev)
 {
-	int rc = -ENODEV;
-	struct device *device_server;
-	int dev_num = node;
-	dev_t devno;
+	int rc = -ENODEV, i;
 
 	D("%s\n", __func__);
+	g_server_dev.server_pdev = pdev;
+	g_server_dev.v4l2_dev.dev = &pdev->dev;
 
-	devno = MKDEV(MAJOR(msm_devno), dev_num);
-	device_server = device_create(msm_class, NULL,
-			devno, NULL, "%s", device_name);
+	rc = v4l2_device_register(g_server_dev.v4l2_dev.dev,
+			&g_server_dev.v4l2_dev);
+	if (rc < 0)
+		return -EINVAL;
 
-	if (IS_ERR(device_server)) {
-		rc = PTR_ERR(device_server);
-		pr_err("%s: error creating device: %d\n", __func__, rc);
+	g_server_dev.video_dev = video_device_alloc();
+	if (g_server_dev.video_dev == NULL) {
+		pr_err("%s: video_device_alloc failed\n", __func__);
 		return rc;
 	}
 
-	cdev_init(&g_server_dev.server_cdev, &msm_fops_server);
-	g_server_dev.server_cdev.owner = THIS_MODULE;
+	strlcpy(g_server_dev.video_dev->name, pdev->name,
+			sizeof(g_server_dev.video_dev->name));
 
-	rc = cdev_add(&g_server_dev.server_cdev, devno, 1);
-	if (rc < 0) {
-		pr_err("%s: error adding cdev: %d\n", __func__, rc);
-		device_destroy(msm_class, devno);
-		return rc;
-	}
+	g_server_dev.video_dev->v4l2_dev = &g_server_dev.v4l2_dev;
+	g_server_dev.video_dev->fops = &msm_fops_server;
+	g_server_dev.video_dev->ioctl_ops = &msm_ioctl_ops_server;
+	g_server_dev.video_dev->release   = video_device_release;
+	g_server_dev.video_dev->minor = 100;
+	g_server_dev.video_dev->vfl_type = 1;
+
+	video_set_drvdata(g_server_dev.video_dev, &g_server_dev);
+
+	strlcpy(g_server_dev.media_dev.model, "qcamera",
+			sizeof(g_server_dev.media_dev.model));
+	g_server_dev.media_dev.dev = &pdev->dev;
+	rc = media_device_register(&g_server_dev.media_dev);
+	g_server_dev.v4l2_dev.mdev = &g_server_dev.media_dev;
+
+	rc = video_register_device(g_server_dev.video_dev,
+			VFL_TYPE_GRABBER, 100);
 
 	mutex_init(&g_server_dev.server_lock);
+	mutex_init(&g_server_dev.server_queue_lock);
 	g_server_dev.pcam_active = NULL;
 	g_server_dev.camera_info.num_cameras = 0;
 	atomic_set(&g_server_dev.number_pcam_active, 0);
+	g_server_dev.server_evt_id = 0;
 
 	/*initialize fake video device and event queue*/
 
-	g_server_dev.server_command_queue.pvdev = video_device_alloc();
-	if (g_server_dev.server_command_queue.pvdev == NULL) {
-		pr_err("%s: video_device_alloc failed\n", __func__);
-		return -ENOMEM;
-	}
+	g_server_dev.server_command_queue.pvdev = g_server_dev.video_dev;
 	rc = msm_setup_v4l2_event_queue(
 		&g_server_dev.server_command_queue.eventHandle,
 		g_server_dev.server_command_queue.pvdev);
+
 	if (rc < 0)
 		pr_err("%s failed to initialize event queue\n", __func__);
 
+	for (i = 0; i < NUM_SERVER_QUEUE; i++) {
+		struct msm_cam_server_queue *queue;
+		queue = &g_server_dev.server_queue[i];
+		queue->queue_active = 0;
+		msm_queue_init(&queue->ctrl_q, "control");
+		msm_queue_init(&queue->eventData_q, "eventdata");
+	}
 	return rc;
 }
 
@@ -2717,7 +2794,7 @@
 }
 EXPORT_SYMBOL(msm_sensor_register);
 
-static int __init msm_camera_init(void)
+static int __devinit msm_camera_probe(struct platform_device *pdev)
 {
 	int rc = 0, i;
 	/*for now just create a config 0 node
@@ -2749,7 +2826,7 @@
 	}
 
 	D("creating server and config nodes\n");
-	rc = msm_setup_server_dev(0, "video_msm");
+	rc = msm_setup_server_dev(pdev);
 	if (rc < 0) {
 		pr_err("%s: failed to create server dev: %d\n", __func__,
 		rc);
@@ -2769,10 +2846,31 @@
 	return rc;
 }
 
-static void __exit msm_camera_exit(void)
+static int __exit msm_camera_exit(struct platform_device *pdev)
 {
 	msm_isp_unregister(&g_server_dev);
+	return 0;
+}
+
+
+static struct platform_driver msm_cam_server_driver = {
+	.probe = msm_camera_probe,
+	.remove = msm_camera_exit,
+	.driver = {
+		.name = "msm_cam_server",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_camera_init(void)
+{
+	return platform_driver_register(&msm_cam_server_driver);
+}
+
+static void __exit msm_cam_server_exit(void)
+{
+	platform_driver_unregister(&msm_cam_server_driver);
 }
 
 module_init(msm_camera_init);
-module_exit(msm_camera_exit);
+module_exit(msm_cam_server_exit);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index dd65c01..c4373a7 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -356,6 +356,7 @@
 	 * control thread.  It is accessed only from a process context.
 	 * TO BE REMOVED
 	 */
+	uint32_t server_queue_idx;
 	struct msm_device_queue ctrl_q;
 
 	struct mutex lock;
@@ -387,11 +388,27 @@
 	struct msm_mem_map_info mem_map;
 };
 
+#define NUM_SERVER_QUEUE 5
+
+struct msm_cam_server_queue {
+	uint32_t queue_active;
+	struct msm_device_queue ctrl_q;
+	struct msm_device_queue eventData_q;
+	struct msm_ctrl_cmd *ctrl;
+	uint8_t *ctrl_data;
+	uint32_t evt_id;
+};
+
 /* abstract camera server device for all sensor successfully probed*/
 struct msm_cam_server_dev {
 
 	/* config node device*/
-	struct cdev server_cdev;
+	struct platform_device *server_pdev;
+	/* server node v4l2 device */
+	struct v4l2_device v4l2_dev;
+	struct video_device *video_dev;
+	struct media_device media_dev;
+
 	/* info of sensors successfully probed*/
 	struct msm_camera_info camera_info;
 	/* info of configs successfully created*/
@@ -401,18 +418,20 @@
 	/* number of camera devices opened*/
 	atomic_t number_pcam_active;
 	struct v4l2_queue_util server_command_queue;
+
 	/* This queue used by the config thread to send responses back to the
 	 * control thread.  It is accessed only from a process context.
 	 */
-	struct msm_device_queue ctrl_q;
-	uint8_t ctrl_data[max_control_command_size];
-	struct msm_ctrl_cmd ctrl;
+	struct msm_cam_server_queue server_queue[NUM_SERVER_QUEUE];
+	uint32_t server_evt_id;
+
 	int use_count;
 	/* all the registered ISP subdevice*/
 	struct msm_isp_ops *isp_subdev[MSM_MAX_CAMERA_CONFIGS];
 	/* info of MCTL nodes successfully probed*/
 	struct msm_mctl_node_info mctl_node_info;
 	struct mutex server_lock;
+	struct mutex server_queue_lock;
 };
 
 /* camera server related functions */
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 3e2ddee..59e37dd 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -296,6 +296,7 @@
 
 		isp_event->isp_data.isp_msg.msg_id = isp_msg->msg_id;
 		isp_event->isp_data.isp_msg.frame_id = isp_msg->sof_count;
+		getnstimeofday(&(isp_event->isp_data.isp_msg.timestamp));
 		break;
 	}
 	case NOTIFY_VFE_MSG_OUT: {
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.c b/drivers/media/video/msm/msm_vfe31_v4l2.c
index da9e071..d60f4b7 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.c
@@ -367,6 +367,8 @@
 
 static void vfe31_stop(void)
 {
+
+	uint8_t  axiBusyFlag = true;
 	unsigned long flags;
 
 	atomic_set(&vfe31_ctrl->vstate, 0);
@@ -377,12 +379,6 @@
 	spin_unlock_irqrestore(&vfe31_ctrl->stop_flag_lock, flags);
 
 	/* disable all interrupts.  */
-	/* in either continuous or snapshot mode, stop command can be issued
-	 * at any time. stop camif immediately. */
-	msm_camera_io_w_mb(CAMIF_COMMAND_STOP_IMMEDIATELY,
-		vfe31_ctrl->vfebase + VFE_CAMIF_COMMAND);
-
-	/* disable all interrupts.  */
 	msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
 		vfe31_ctrl->vfebase + VFE_IRQ_MASK_0);
 	msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
@@ -398,16 +394,30 @@
 	msm_camera_io_w_mb(1,
 		vfe31_ctrl->vfebase + VFE_IRQ_CMD);
 
+	/* in either continuous or snapshot mode, stop command can be issued
+	 * at any time. stop camif immediately. */
+	msm_camera_io_w_mb(CAMIF_COMMAND_STOP_IMMEDIATELY,
+		vfe31_ctrl->vfebase + VFE_CAMIF_COMMAND);
+
+	/* axi halt command. */
+	msm_camera_io_w(AXI_HALT,
+		vfe31_ctrl->vfebase + VFE_AXI_CMD);
+	wmb();
+	while (axiBusyFlag) {
+		if (msm_camera_io_r(vfe31_ctrl->vfebase + VFE_AXI_STATUS) & 0x1)
+			axiBusyFlag = false;
+	}
+	/* Ensure the write order while writing
+	to the command register using the barrier */
+	msm_camera_io_w_mb(AXI_HALT_CLEAR,
+		vfe31_ctrl->vfebase + VFE_AXI_CMD);
+
 	/* now enable only halt_irq & reset_irq */
 	msm_camera_io_w(0xf0000000,          /* this is for async timer. */
 		vfe31_ctrl->vfebase + VFE_IRQ_MASK_0);
 	msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1,
 		vfe31_ctrl->vfebase + VFE_IRQ_MASK_1);
 
-	/* then apply axi halt command. */
-	msm_camera_io_w_mb(AXI_HALT,
-		vfe31_ctrl->vfebase + VFE_AXI_CMD);
-
 	msm_camera_io_w_mb(VFE_RESET_UPON_STOP_CMD,
 		vfe31_ctrl->vfebase + VFE_GLOBAL_RESET);
 }
@@ -2362,8 +2372,7 @@
 		/* later we need to add check for live snapshot mode. */
 		if (vfe31_ctrl->frame_skip_pattern & (0x1 <<
 			(vfe31_ctrl->snapshot_frame_cnt %
-			vfe31_ctrl->frame_skip_cnt))) {
-			vfe31_ctrl->vfe_capture_count--;
+				vfe31_ctrl->frame_skip_cnt))) {
 			/* if last frame to be captured: */
 			if (vfe31_ctrl->vfe_capture_count == 0) {
 				/* stop the bus output:write master enable = 0*/
@@ -2393,7 +2402,6 @@
 				vfe31_ctrl->frame_skip_pattern = 0xffffffff;
 			} /*if snapshot count is 0*/
 		} /*if frame is not being dropped*/
-		vfe31_ctrl->snapshot_frame_cnt++;
 		/* then do reg_update. */
 		msm_camera_io_w(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 	} /* if snapshot mode. */
@@ -2493,6 +2501,17 @@
 		else
 			vfe31_ctrl->sync_timer_repeat_count--;
 	}
+	if ((vfe31_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) ||
+		(vfe31_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB) ||
+		(vfe31_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) ||
+		(vfe31_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB)) {
+		if (vfe31_ctrl->frame_skip_pattern & (0x1 <<
+			(vfe31_ctrl->snapshot_frame_cnt %
+				vfe31_ctrl->frame_skip_cnt))) {
+			vfe31_ctrl->vfe_capture_count--;
+		}
+		vfe31_ctrl->snapshot_frame_cnt++;
+	}
 }
 
 static void vfe31_process_error_irq(uint32_t errStatus)
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 2f0b6c9..b8344fb 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -4022,6 +4022,7 @@
 	vfe32_ctrl->fs_vfe = NULL;
 vfe_fs_failed:
 	iounmap(vfe32_ctrl->vfebase);
+	vfe32_ctrl->vfebase = NULL;
 vfe_remap_failed:
 	disable_irq(vfe32_ctrl->vfeirq->start);
 	return rc;
@@ -4041,6 +4042,7 @@
 		vfe32_ctrl->fs_vfe = NULL;
 	}
 	iounmap(vfe32_ctrl->vfebase);
+	vfe32_ctrl->vfebase = NULL;
 
 	if (atomic_read(&irq_cnt))
 		pr_warning("%s, Warning IRQ Count not ZERO\n", __func__);
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index 8567fb3..cd503f9 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -86,6 +86,15 @@
 {
 	uint32_t vpe_version;
 	uint32_t rc = 0;
+	unsigned long flags = 0;
+
+	spin_lock_irqsave(&vpe_ctrl->lock, flags);
+	if (vpe_ctrl->state == VPE_STATE_IDLE) {
+		CDBG("%s: VPE already disabled.", __func__);
+		spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
+		return rc;
+	}
+	spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
 
 	vpe_reset_state_variables();
 	vpe_version = msm_camera_io_r(
@@ -673,6 +682,7 @@
 /* from this part it is error handling. */
 vpe_unmap_mem_region:
 	iounmap(vpe_ctrl->vpebase);
+	vpe_ctrl->vpebase = NULL;
 	return rc;  /* this rc should have error code. */
 }
 
@@ -684,7 +694,10 @@
 		return;
 	}
 
+	vpe_reset();
+	vpe_disable();
 	iounmap(vpe_ctrl->vpebase);
+	vpe_ctrl->vpebase = NULL;
 	atomic_set(&vpe_init_done, 0);
 }
 EXPORT_SYMBOL(msm_vpe_subdev_release);
diff --git a/drivers/media/video/msm/msm_vpe1.c b/drivers/media/video/msm/msm_vpe1.c
index 96988a9..984aea5 100644
--- a/drivers/media/video/msm/msm_vpe1.c
+++ b/drivers/media/video/msm/msm_vpe1.c
@@ -1422,7 +1422,7 @@
 	return rc;  /* this rc should be zero.*/
 
 	iounmap(vpe_device->vpebase);  /* this path should never occur */
-
+	vpe_device->vpebase = NULL;
 /* from this part it is error handling. */
 vpe_release_mem_region:
 	release_mem_region(vpemem->start, (vpemem->end - vpemem->start) + 1);
@@ -1436,6 +1436,7 @@
 	vpemem = vpe_device->vpemem;
 
 	iounmap(vpe_device->vpebase);
+	vpe_device->vpebase = NULL;
 	release_mem_region(vpemem->start,
 					(vpemem->end - vpemem->start) + 1);
 	return 0;
diff --git a/drivers/media/video/msm/sensors/mt9e013_v4l2.c b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
index 7f0fbc3..e6e2d52 100644
--- a/drivers/media/video/msm/sensors/mt9e013_v4l2.c
+++ b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
@@ -271,8 +271,6 @@
 	ARRAY_SIZE(mt9e013_prev_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
 	{&mt9e013_hfr60_settings[0],
 	ARRAY_SIZE(mt9e013_hfr60_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
-	{&mt9e013_hfr60_settings[0],
-	ARRAY_SIZE(mt9e013_hfr60_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
 	{&mt9e013_hfr90_settings[0],
 	ARRAY_SIZE(mt9e013_hfr90_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
 	{&mt9e013_hfr120_settings[0],
@@ -312,15 +310,6 @@
 		.y_output = 0x212,
 		.line_length_pclk = 0x970,
 		.frame_length_lines = 0x2A1,
-		.vt_pixel_clk = 98400000,
-		.op_pixel_clk = 98400000,
-		.binning_factor = 1,
-	},
-	{
-		.x_output = 0x340,
-		.y_output = 0x212,
-		.line_length_pclk = 0x970,
-		.frame_length_lines = 0x2A1,
 		.vt_pixel_clk = 146400000,
 		.op_pixel_clk = 146400000,
 		.binning_factor = 1,
@@ -350,7 +339,6 @@
 	&mt9e013_csi_params,
 	&mt9e013_csi_params,
 	&mt9e013_csi_params,
-	&mt9e013_csi_params,
 };
 
 static struct msm_sensor_output_reg_addr_t mt9e013_reg_addr = {
diff --git a/drivers/media/video/msm/sn12m0pz.c b/drivers/media/video/msm/sn12m0pz.c
index affa581..2eabb3c 100644
--- a/drivers/media/video/msm/sn12m0pz.c
+++ b/drivers/media/video/msm/sn12m0pz.c
@@ -1579,7 +1579,7 @@
 	CDBG("init_done");
 	return rc;
 }
-static int __init sn12m0pz_init_client(struct i2c_client *client)
+static int __devinit sn12m0pz_init_client(struct i2c_client *client)
 {
 	/* Initialize the MSM_CAMI2C Chip */
 	init_waitqueue_head(&sn12m0pz_wait_queue);
@@ -1591,7 +1591,7 @@
 	{ }
 };
 
-static int sn12m0pz_i2c_probe(struct i2c_client *client,
+static int __devinit sn12m0pz_i2c_probe(struct i2c_client *client,
 	const struct i2c_device_id *id)
 {
 	int rc = 0;
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index 483eab0..95cdc59 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -33,6 +33,7 @@
 			struct mem_region *mregion);
 	u32 width;
 	u32 height;
+	int secure;
 };
 
 struct venc {
@@ -72,7 +73,7 @@
 	u32 i;
 	u32 found = false;
 
-	for (i = 0; i < VIDC_MAX_NUM_CLIENTS; i++) {
+	for (i = 0; i < VID_ENC_MAX_ENCODER_CLIENTS; i++) {
 		if (!venc_p.venc_clients[i].venc_client.vcd_handle) {
 			found = true;
 			break;
@@ -266,6 +267,7 @@
 	struct venc_inst *inst;
 	struct video_client_ctx *client_ctx;
 	struct venc_msg_ops *vmops  =  arg;
+	int flags = 0;
 	mutex_lock(&venc_p.lock);
 	client_index = venc_get_empty_client_index();
 	if (client_index < 0) {
@@ -284,7 +286,11 @@
 	inst->op_buffer_done = vmops->op_buffer_done;
 	inst->ip_buffer_done = vmops->ip_buffer_done;
 	inst->cbdata = vmops->cbdata;
-
+	inst->secure = vmops->secure;
+	if (vmops->secure) {
+		WFD_MSG_ERR("OPENING SECURE SESSION\n");
+		flags |= VCD_CP_SESSION;
+	}
 	if (vcd_get_ion_status()) {
 		client_ctx->user_ion_client = vcd_get_ion_client();
 		if (!client_ctx->user_ion_client) {
@@ -294,9 +300,10 @@
 	}
 
 	rc = vcd_open(venc_p.device_handle, false, venc_cb,
-					inst);
+				inst, flags);
 	if (rc) {
 		WFD_MSG_ERR("vcd_open failed, rc = %d\n", rc);
+		rc = -ENODEV;
 		goto no_free_client;
 	}
 	wait_for_completion(&client_ctx->event);
@@ -1522,6 +1529,87 @@
 	return rc;
 }
 
+static long venc_set_entropy_mode(struct video_client_ctx *client_ctx,
+		__s32 value)
+{
+	struct vcd_property_hdr vcd_property_hdr;
+	struct vcd_property_entropy_control entropy_control;
+	int rc = 0;
+
+	if (!client_ctx) {
+		WFD_MSG_ERR("Invalid parameters\n");
+		rc = -EINVAL;
+		goto set_entropy_mode_fail;
+	}
+
+	vcd_property_hdr.prop_id = VCD_I_ENTROPY_CTRL;
+	vcd_property_hdr.sz = sizeof(entropy_control);
+
+	switch (value) {
+	case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC:
+		entropy_control.entropy_sel = VCD_ENTROPY_SEL_CAVLC;
+		break;
+	case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC:
+		entropy_control.entropy_sel = VCD_ENTROPY_SEL_CABAC;
+		entropy_control.cabac_model = VCD_CABAC_MODEL_NUMBER_0;
+		break;
+	default:
+		WFD_MSG_ERR("Entropy type %d not supported\n", value);
+		rc = -ENOTSUPP;
+		goto set_entropy_mode_fail;
+	}
+	rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
+			&entropy_control);
+	if (rc) {
+		WFD_MSG_ERR("Failed to set entropy mode\n");
+		goto set_entropy_mode_fail;
+	}
+
+set_entropy_mode_fail:
+	return rc;
+}
+
+static long venc_get_entropy_mode(struct video_client_ctx *client_ctx,
+		__s32 *value)
+{
+	struct vcd_property_hdr vcd_property_hdr;
+	struct vcd_property_entropy_control entropy_control;
+	int rc = 0;
+
+	if (!client_ctx || !value) {
+		WFD_MSG_ERR("Invalid parameters\n");
+		rc = -EINVAL;
+		goto get_entropy_mode_fail;
+	}
+
+	vcd_property_hdr.prop_id = VCD_I_ENTROPY_CTRL;
+	vcd_property_hdr.sz = sizeof(entropy_control);
+
+	rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+			&entropy_control);
+
+	if (rc) {
+		WFD_MSG_ERR("Failed to get entropy mode\n");
+		goto get_entropy_mode_fail;
+	}
+
+	switch (entropy_control.entropy_sel) {
+	case VCD_ENTROPY_SEL_CAVLC:
+		*value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC;
+		break;
+	case VCD_ENTROPY_SEL_CABAC:
+		*value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC;
+		break;
+	default:
+		WFD_MSG_ERR("Entropy type %d not known\n",
+				entropy_control.entropy_sel);
+		rc = -EINVAL;
+		goto get_entropy_mode_fail;
+	}
+get_entropy_mode_fail:
+	return rc;
+}
+
 static long venc_set_input_buffer(struct v4l2_subdev *sd, void *arg)
 {
 	struct mem_region *mregion = arg;
@@ -1684,6 +1772,7 @@
 	struct vcd_property_enc_recon_buffer *ctrl = NULL;
 	unsigned long phy_addr;
 	int i = 0;
+	int flags = 0;
 	u32 len;
 	control.width = inst->width;
 	control.height = inst->height;
@@ -1696,6 +1785,8 @@
 		WFD_MSG_ERR("Failed to get recon buf size\n");
 		goto err;
 	}
+	flags = ION_HEAP(ION_CP_MM_HEAP_ID);
+	flags |= inst->secure ? ION_SECURE : ION_HEAP(ION_IOMMU_HEAP_ID);
 
 	if (vcd_get_ion_status()) {
 		for (i = 0; i < 4; ++i) {
@@ -1706,8 +1797,7 @@
 			ctrl->user_virtual_addr = (void *)i;
 			client_ctx->recon_buffer_ion_handle[i]
 				= ion_alloc(client_ctx->user_ion_client,
-			control.size, SZ_8K, ION_HEAP(ION_IOMMU_HEAP_ID) |
-			ION_HEAP(ION_CP_MM_HEAP_ID));
+			control.size, SZ_8K, flags);
 
 			ctrl->kernel_virtual_addr = ion_map_kernel(
 				client_ctx->user_ion_client,
@@ -1895,6 +1985,9 @@
 	case V4L2_CID_MPEG_QCOM_SET_PERF_LEVEL:
 		rc = venc_set_max_perf_level(client_ctx, ctrl->value);
 		break;
+	case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+		rc = venc_set_entropy_mode(client_ctx, ctrl->value);
+		break;
 	default:
 		WFD_MSG_ERR("Set property not suported: %d\n", ctrl->id);
 		rc = -ENOTSUPP;
@@ -1954,6 +2047,9 @@
 		rc = venc_get_multislicing_mode(client_ctx, ctrl->id,
 				&ctrl->value);
 		break;
+	case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+		rc = venc_get_entropy_mode(client_ctx, &ctrl->value);
+		break;
 	default:
 		WFD_MSG_ERR("Get property not suported: %d\n", ctrl->id);
 		rc = -ENOTSUPP;
diff --git a/drivers/media/video/msm/wfd/enc-subdev.h b/drivers/media/video/msm/wfd/enc-subdev.h
index 69e7521..cafc9d5 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.h
+++ b/drivers/media/video/msm/wfd/enc-subdev.h
@@ -44,6 +44,7 @@
 struct venc_msg_ops {
 	void *cookie;
 	void *cbdata;
+	int secure;
 	void (*op_buffer_done)(void *cookie, u32 status,
 			struct vb2_buffer *buf);
 	void (*ip_buffer_done)(void *cookie, u32 status,
diff --git a/drivers/media/video/msm/wfd/mdp-subdev.c b/drivers/media/video/msm/wfd/mdp-subdev.c
index e519a4d..a6d244f 100644
--- a/drivers/media/video/msm/wfd/mdp-subdev.c
+++ b/drivers/media/video/msm/wfd/mdp-subdev.c
@@ -45,13 +45,6 @@
 		goto exit;
 	}
 
-	/*Tell HDMI daemon to open fb1*/
-	rc = kobject_uevent(&fbi->dev->kobj, KOBJ_ADD);
-	if (rc) {
-		WFD_MSG_ERR("Failed add to kobj");
-		goto exit;
-	}
-
 	msm_fb_writeback_init(fbi);
 	inst->mdp = fbi;
 	*cookie = inst;
@@ -78,9 +71,6 @@
 			rc = -ENODEV;
 			goto exit;
 		}
-		rc = kobject_uevent(&fbi->dev->kobj, KOBJ_ONLINE);
-		if (rc)
-			WFD_MSG_ERR("Failed to send ONLINE event\n");
 	}
 exit:
 	return rc;
@@ -89,19 +79,12 @@
 {
 	struct mdp_instance *inst = arg;
 	int rc = 0;
-	struct fb_info *fbi = NULL;
 	if (inst) {
 		rc = msm_fb_writeback_stop(inst->mdp);
 		if (rc) {
 			WFD_MSG_ERR("Failed to stop writeback mode\n");
 			return rc;
 		}
-		fbi = (struct fb_info *)inst->mdp;
-		rc = kobject_uevent(&fbi->dev->kobj, KOBJ_OFFLINE);
-		if (rc) {
-			WFD_MSG_ERR("Failed to send offline event\n");
-			return -EIO;
-		}
 	}
 	return 0;
 }
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
index 2c2c551..7ab5d17 100644
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -43,6 +43,7 @@
 #define VENC_INPUT_BUFFERS 4
 
 struct wfd_device {
+	struct mutex dev_lock;
 	struct platform_device *pdev;
 	struct v4l2_device v4l2_dev;
 	struct video_device *pvdev;
@@ -51,6 +52,7 @@
 	struct v4l2_subdev vsg_sdev;
 	struct ion_client *ion_client;
 	bool secure_device;
+	bool in_use;
 };
 
 struct mem_info {
@@ -152,7 +154,7 @@
 	int rc;
 
 	alloc_regions = ION_HEAP(ION_CP_MM_HEAP_ID);
-	alloc_regions |= secure ? 0 :
+	alloc_regions |= secure ? ION_SECURE :
 				ION_HEAP(ION_IOMMU_HEAP_ID);
 	handle = ion_alloc(client,
 			mregion->size, SZ_4K, alloc_regions);
@@ -1243,13 +1245,25 @@
 static int wfd_open(struct file *filp)
 {
 	int rc = 0;
-	struct wfd_inst *inst;
-	struct wfd_device *wfd_dev;
+	struct wfd_inst *inst = NULL;
+	struct wfd_device *wfd_dev = NULL;
 	struct venc_msg_ops enc_mops;
 	struct vsg_msg_ops vsg_mops;
 
 	WFD_MSG_DBG("wfd_open: E\n");
 	wfd_dev = video_drvdata(filp);
+
+	mutex_lock(&wfd_dev->dev_lock);
+	if (wfd_dev->in_use) {
+		WFD_MSG_ERR("Device already in use.\n");
+		rc = -EBUSY;
+		mutex_unlock(&wfd_dev->dev_lock);
+		goto err_dev_busy;
+	}
+
+	wfd_dev->in_use = true;
+	mutex_unlock(&wfd_dev->dev_lock);
+
 	inst = kzalloc(sizeof(struct wfd_inst), GFP_KERNEL);
 	if (!inst || !wfd_dev) {
 		WFD_MSG_ERR("Could not allocate memory for "
@@ -1279,6 +1293,7 @@
 	enc_mops.op_buffer_done = venc_op_buffer_done;
 	enc_mops.ip_buffer_done = venc_ip_buffer_done;
 	enc_mops.cbdata = filp;
+	enc_mops.secure = wfd_dev->secure_device;
 	rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl, OPEN,
 				(void *)&enc_mops);
 	if (rc || !enc_mops.cookie) {
@@ -1309,6 +1324,7 @@
 				MDP_CLOSE, (void *)inst->mdp_inst);
 err_mdp_open:
 	kfree(inst);
+err_dev_busy:
 	return rc;
 }
 
@@ -1340,10 +1356,14 @@
 		if (rc)
 			WFD_MSG_ERR("Failed to CLOSE vsg subdev: %d\n", rc);
 
+		wfd_stats_deinit(&inst->stats);
 		kfree(inst);
 	}
 
-	wfd_stats_deinit(&inst->stats);
+	mutex_lock(&wfd_dev->dev_lock);
+	wfd_dev->in_use = false;
+	mutex_unlock(&wfd_dev->dev_lock);
+
 	WFD_MSG_DBG("wfd_close: X\n");
 	return 0;
 }
@@ -1486,7 +1506,9 @@
 		}
 
 		/* Other device specific stuff */
+		mutex_init(&wfd_dev[c].dev_lock);
 		wfd_dev[c].ion_client = ion_client;
+		wfd_dev[c].in_use = false;
 		switch (WFD_DEVICE_NUMBER_BASE + c) {
 		case WFD_DEVICE_SECURE:
 			wfd_dev[c].secure_device = true;
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 6443250..670d0f8 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -154,7 +154,10 @@
 				unsigned int *nplanes, unsigned long sizes[],
 				void *alloc_ctxs[])
 {
-	*nbuffers = 3;
+	*nbuffers += 2;
+	if (*nbuffers > VIDEO_MAX_FRAME)
+		return -EINVAL;
+
 	*nplanes = 1;
 	return 0;
 }
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index e1a6ffd..0e096eb 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -168,16 +168,12 @@
 /* Prevent idle power collapse(pc) while operating in peripheral mode */
 static void msmsdcc_pm_qos_update_latency(struct msmsdcc_host *host, int vote)
 {
-	u32 swfi_latency = 0;
-
-	if (!host->plat->swfi_latency)
+	if (!host->cpu_dma_latency)
 		return;
 
-	swfi_latency = host->plat->swfi_latency + 1;
-
 	if (vote)
 		pm_qos_update_request(&host->pm_qos_req_dma,
-					swfi_latency);
+				host->cpu_dma_latency);
 	else
 		pm_qos_update_request(&host->pm_qos_req_dma,
 					PM_QOS_DEFAULT_VALUE);
@@ -4082,21 +4078,22 @@
 };
 #endif
 
-void msmsdcc_print_regs(const char *name, void __iomem *base,
-			unsigned int no_of_regs)
+static void msmsdcc_print_regs(const char *name, void __iomem *base,
+			       u32 phys_base, unsigned int no_of_regs)
 {
 	unsigned int i;
 
 	if (!base)
 		return;
-	pr_info("===== %s: Register Dumps @base=0x%x =====\n",
-		name, (u32)base);
+
+	pr_info("===== %s: Register Dumps @phys_base=0x%x, @virt_base=0x%x"
+		" =====\n", name, phys_base, (u32)base);
 	for (i = 0; i < no_of_regs; i = i + 4) {
-		pr_info("Reg=0x%.2x: 0x%.8x, 0x%.8x, 0x%.8x, 0x%.8x.\n", i*4,
-				(u32)readl_relaxed(base + i*4),
-				(u32)readl_relaxed(base + ((i+1)*4)),
-				(u32)readl_relaxed(base + ((i+2)*4)),
-				(u32)readl_relaxed(base + ((i+3)*4)));
+		pr_info("Reg=0x%.2x: 0x%.8x, 0x%.8x, 0x%.8x, 0x%.8x\n", i*4,
+			(u32)readl_relaxed(base + i*4),
+			(u32)readl_relaxed(base + ((i+1)*4)),
+			(u32)readl_relaxed(base + ((i+2)*4)),
+			(u32)readl_relaxed(base + ((i+3)*4)));
 	}
 }
 
@@ -4104,17 +4101,17 @@
 {
 	/* Dump current state of SDCC clocks, power and irq */
 	pr_info("%s: SDCC PWR is %s\n", mmc_hostname(host->mmc),
-			(host->pwr ? "ON" : "OFF"));
+		(host->pwr ? "ON" : "OFF"));
 	pr_info("%s: SDCC clks are %s, MCLK rate=%d\n",
-			mmc_hostname(host->mmc),
-			(host->clks_on ? "ON" : "OFF"),
-			(u32)clk_get_rate(host->clk));
+		mmc_hostname(host->mmc), (host->clks_on ? "ON" : "OFF"),
+		(u32)clk_get_rate(host->clk));
 	pr_info("%s: SDCC irq is %s\n", mmc_hostname(host->mmc),
 		(host->sdcc_irq_disabled ? "disabled" : "enabled"));
 
 	/* Now dump SDCC registers. Don't print FIFO registers */
 	if (host->clks_on)
-		msmsdcc_print_regs("SDCC-CORE", host->base, 28);
+		msmsdcc_print_regs("SDCC-CORE", host->base,
+				   host->core_memres->start, 28);
 
 	if (host->curr.data) {
 		if (!msmsdcc_is_dma_possible(host, host->curr.data))
@@ -4123,22 +4120,27 @@
 			pr_info("%s: ADM mode: busy=%d, chnl=%d, crci=%d\n",
 				mmc_hostname(host->mmc), host->dma.busy,
 				host->dma.channel, host->dma.crci);
-		else if (host->is_sps_mode)
+		else if (host->is_sps_mode) {
+			if (host->sps.busy)
+				msmsdcc_print_regs("SDCC-DML", host->dml_base,
+						   host->dml_memres->start,
+						   16);
 			pr_info("%s: SPS mode: busy=%d\n",
 				mmc_hostname(host->mmc), host->sps.busy);
+		}
 
 		pr_info("%s: xfer_size=%d, data_xfered=%d, xfer_remain=%d\n",
 			mmc_hostname(host->mmc), host->curr.xfer_size,
 			host->curr.data_xfered, host->curr.xfer_remain);
-		pr_info("%s: got_dataend=%d, prog_enable=%d,"
-			" wait_for_auto_prog_done=%d,"
-			" got_auto_prog_done=%d\n",
-			mmc_hostname(host->mmc), host->curr.got_dataend,
-			host->prog_enable, host->curr.wait_for_auto_prog_done,
-			host->curr.got_auto_prog_done);
 	}
 
+	pr_info("%s: got_dataend=%d, prog_enable=%d,"
+		" wait_for_auto_prog_done=%d, got_auto_prog_done=%d\n",
+		mmc_hostname(host->mmc), host->curr.got_dataend,
+		host->prog_enable, host->curr.wait_for_auto_prog_done,
+		host->curr.got_auto_prog_done);
 }
+
 static void msmsdcc_req_tout_timer_hdlr(unsigned long data)
 {
 	struct msmsdcc_host *host = (struct msmsdcc_host *)data;
@@ -4537,9 +4539,13 @@
 	/* Apply Hard reset to SDCC to put it in power on default state */
 	msmsdcc_hard_reset(host);
 
+#define MSM_MMC_DEFAULT_CPUDMA_LATENCY 200 /* usecs */
 	/* pm qos request to prevent apps idle power collapse */
-	if (host->plat->swfi_latency)
-		pm_qos_add_request(&host->pm_qos_req_dma,
+	if (host->plat->cpu_dma_latency)
+		host->cpu_dma_latency = host->plat->cpu_dma_latency;
+	else
+		host->cpu_dma_latency = MSM_MMC_DEFAULT_CPUDMA_LATENCY;
+	pm_qos_add_request(&host->pm_qos_req_dma,
 			PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
 
 	ret = msmsdcc_vreg_init(host, true);
@@ -4825,7 +4831,7 @@
 	msmsdcc_vreg_init(host, false);
  clk_disable:
 	clk_disable(host->clk);
-	if (host->plat->swfi_latency)
+	if (host->cpu_dma_latency)
 		pm_qos_remove_request(&host->pm_qos_req_dma);
  clk_put:
 	clk_put(host->clk);
@@ -4899,7 +4905,7 @@
 	if (!IS_ERR_OR_NULL(host->dfab_pclk))
 		clk_put(host->dfab_pclk);
 
-	if (host->plat->swfi_latency)
+	if (host->cpu_dma_latency)
 		pm_qos_remove_request(&host->pm_qos_req_dma);
 
 	msmsdcc_vreg_init(host, false);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 406af4f..50477da 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -395,6 +395,7 @@
 	bool sdio_gpio_lpm;
 	bool irq_wake_enabled;
 	struct pm_qos_request_list pm_qos_req_dma;
+	u32 cpu_dma_latency;
 	bool sdcc_suspending;
 	bool sdcc_irq_disabled;
 	bool sdcc_suspended;
diff --git a/drivers/mtd/devices/msm_nand.c b/drivers/mtd/devices/msm_nand.c
index 2479a11..3675d2c 100644
--- a/drivers/mtd/devices/msm_nand.c
+++ b/drivers/mtd/devices/msm_nand.c
@@ -6720,6 +6720,14 @@
 							((devcfg >> 4) & 0x3);
 			supported_flash.oobsize = (8 << ((devcfg >> 2) & 0x3)) *
 				(supported_flash.pagesize >> 9);
+
+			if ((supported_flash.oobsize > 64) &&
+				(supported_flash.pagesize == 2048)) {
+				pr_info("msm_nand: Found a 2K page device with"
+					" %d oobsize - changing oobsize to 64 "
+					"bytes.\n", supported_flash.oobsize);
+				supported_flash.oobsize = 64;
+			}
 		} else {
 			supported_flash.flash_id = flash_id;
 			supported_flash.density = flashdev->chipsize << 20;
diff --git a/drivers/net/msm_rmnet_sdio.c b/drivers/net/msm_rmnet_sdio.c
index 883c649..acdffd1 100644
--- a/drivers/net/msm_rmnet_sdio.c
+++ b/drivers/net/msm_rmnet_sdio.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -78,6 +78,7 @@
 #endif
 	struct sk_buff *skb;
 	spinlock_t lock;
+	spinlock_t tx_queue_lock;
 	struct tasklet_struct tsklt;
 	u32 operation_mode; /* IOCTL specified mode (protocol, QoS header) */
 	uint8_t device_up;
@@ -361,6 +362,7 @@
 static void sdio_write_done(void *dev, struct sk_buff *skb)
 {
 	struct rmnet_private *p = netdev_priv(dev);
+	unsigned long flags;
 
 	if (skb)
 		dev_kfree_skb_any(skb);
@@ -368,12 +370,14 @@
 	if (!p->in_reset) {
 		DBG1("%s: write complete skb=%p\n",	__func__, skb);
 
+		spin_lock_irqsave(&p->tx_queue_lock, flags);
 		if (netif_queue_stopped(dev) &&
 				msm_sdio_dmux_is_ch_low(p->ch_id)) {
 			DBG0("%s: Low WM hit, waking queue=%p\n",
 					__func__, skb);
 			netif_wake_queue(dev);
 		}
+		spin_unlock_irqrestore(&p->tx_queue_lock, flags);
 	} else {
 		DBG1("%s: write in reset skb=%p\n",	__func__, skb);
 	}
@@ -454,6 +458,7 @@
 static int rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct rmnet_private *p = netdev_priv(dev);
+	unsigned long flags;
 
 	if (netif_queue_stopped(dev)) {
 		pr_err("[%s]fatal: rmnet_xmit called when "
@@ -463,10 +468,12 @@
 
 	_rmnet_xmit(skb, dev);
 
+	spin_lock_irqsave(&p->tx_queue_lock, flags);
 	if (msm_sdio_dmux_is_ch_full(p->ch_id)) {
 		netif_stop_queue(dev);
 		DBG0("%s: High WM hit, stopping queue=%p\n",	__func__, skb);
 	}
+	spin_unlock_irqrestore(&p->tx_queue_lock, flags);
 
 	return 0;
 }
@@ -667,6 +674,7 @@
 		p->operation_mode = RMNET_MODE_LLP_ETH;
 		p->ch_id = n;
 		spin_lock_init(&p->lock);
+		spin_lock_init(&p->tx_queue_lock);
 #ifdef CONFIG_MSM_RMNET_DEBUG
 		p->timeout_us = timeout_us;
 		p->wakeups_xmit = p->wakeups_rcv = 0;
diff --git a/drivers/net/usb/rmnet_usb_data.c b/drivers/net/usb/rmnet_usb_data.c
index ae3f934..3352380 100644
--- a/drivers/net/usb/rmnet_usb_data.c
+++ b/drivers/net/usb/rmnet_usb_data.c
@@ -13,6 +13,8 @@
 #include <linux/mii.h>
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include <linux/usb.h>
 #include <linux/usb/usbnet.h>
 #include <linux/msm_rmnet.h>
@@ -416,6 +418,90 @@
 	dev->watchdog_timeo = 1000; /* 10 seconds? */
 }
 
+static int rmnet_usb_data_status(struct seq_file *s, void *unused)
+{
+	struct usbnet *unet = s->private;
+
+	seq_printf(s, "RMNET_MODE_LLP_IP:  %d\n",
+			test_bit(RMNET_MODE_LLP_IP, &unet->data[0]));
+	seq_printf(s, "RMNET_MODE_LLP_ETH: %d\n",
+			test_bit(RMNET_MODE_LLP_ETH, &unet->data[0]));
+	seq_printf(s, "RMNET_MODE_QOS:     %d\n",
+			test_bit(RMNET_MODE_QOS, &unet->data[0]));
+	seq_printf(s, "Net MTU:            %u\n", unet->net->mtu);
+	seq_printf(s, "rx_urb_size:        %u\n", unet->rx_urb_size);
+	seq_printf(s, "rx skb q len:       %u\n", unet->rxq.qlen);
+	seq_printf(s, "rx skb done q len:  %u\n", unet->done.qlen);
+	seq_printf(s, "rx errors:          %lu\n", unet->net->stats.rx_errors);
+	seq_printf(s, "rx over errors:     %lu\n",
+			unet->net->stats.rx_over_errors);
+	seq_printf(s, "rx length errors:   %lu\n",
+			unet->net->stats.rx_length_errors);
+	seq_printf(s, "rx packets:         %lu\n", unet->net->stats.rx_packets);
+	seq_printf(s, "rx bytes:           %lu\n", unet->net->stats.rx_bytes);
+	seq_printf(s, "tx skb q len:       %u\n", unet->txq.qlen);
+	seq_printf(s, "tx errors:          %lu\n", unet->net->stats.tx_errors);
+	seq_printf(s, "tx packets:         %lu\n", unet->net->stats.tx_packets);
+	seq_printf(s, "tx bytes:           %lu\n", unet->net->stats.tx_bytes);
+	seq_printf(s, "suspend count:      %d\n", unet->suspend_count);
+	seq_printf(s, "EVENT_DEV_OPEN:     %d\n",
+			test_bit(EVENT_DEV_OPEN, &unet->flags));
+	seq_printf(s, "EVENT_TX_HALT:      %d\n",
+			test_bit(EVENT_TX_HALT, &unet->flags));
+	seq_printf(s, "EVENT_RX_HALT:      %d\n",
+			test_bit(EVENT_RX_HALT, &unet->flags));
+	seq_printf(s, "EVENT_RX_MEMORY:    %d\n",
+			test_bit(EVENT_RX_MEMORY, &unet->flags));
+	seq_printf(s, "EVENT_DEV_ASLEEP:   %d\n",
+			test_bit(EVENT_DEV_ASLEEP, &unet->flags));
+
+	return 0;
+}
+
+static int rmnet_usb_data_status_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, rmnet_usb_data_status, inode->i_private);
+}
+
+const struct file_operations rmnet_usb_data_fops = {
+	.open = rmnet_usb_data_status_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int rmnet_usb_data_debugfs_init(struct usbnet *unet)
+{
+	struct dentry *rmnet_usb_data_dbg_root;
+	struct dentry *rmnet_usb_data_dentry;
+
+	rmnet_usb_data_dbg_root = debugfs_create_dir(unet->net->name, NULL);
+	if (!rmnet_usb_data_dbg_root || IS_ERR(rmnet_usb_data_dbg_root))
+		return -ENODEV;
+
+	rmnet_usb_data_dentry = debugfs_create_file("status",
+		S_IRUGO | S_IWUSR,
+		rmnet_usb_data_dbg_root, unet,
+		&rmnet_usb_data_fops);
+
+	if (!rmnet_usb_data_dentry) {
+		debugfs_remove_recursive(rmnet_usb_data_dbg_root);
+		return -ENODEV;
+	}
+
+	unet->data[2] = (unsigned long)rmnet_usb_data_dbg_root;
+
+	return 0;
+}
+
+static void rmnet_usb_data_debugfs_cleanup(struct usbnet *unet)
+{
+	struct dentry *root = (struct dentry *)unet->data[2];
+
+	debugfs_remove_recursive(root);
+	unet->data[2] = 0;
+}
+
 static int rmnet_usb_probe(struct usb_interface *iface,
 		const struct usb_device_id *prod)
 {
@@ -469,6 +555,10 @@
 	if (status)
 		goto out;
 
+	status = rmnet_usb_data_debugfs_init(unet);
+	if (status)
+		dev_dbg(&udev->dev, "mode debugfs file is not available\n");
+
 	/* allow modem to wake up suspended system */
 	device_set_wakeup_enable(&udev->dev, 1);
 out:
@@ -490,6 +580,8 @@
 		return;
 	}
 
+	rmnet_usb_data_debugfs_cleanup(unet);
+
 	dev = (struct rmnet_ctrl_dev *)unet->data[1];
 	if (!dev) {
 		dev_err(&udev->dev, "%s:ctrl device not found\n", __func__);
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index ce748f5..aa1a589 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -78,9 +78,13 @@
 /**
  * struct pm8921_bms_chip -
  * @bms_output_lock:	lock to prevent concurrent bms reads
- * @bms_100_lock:	lock to prevent concurrent updates to values that force
- *			100% charge
  *
+ * @last_ocv_uv_mutex:	mutex to protect simultaneous invocations of calculate
+ *			state of charge, note that last_ocv_uv could be
+ *			changed as soc is adjusted. This mutex protects
+ *			simultaneous updates of last_ocv_uv as well. This mutex
+ *			also protects changes to *_at_100 variables used in
+ *			faking 100% SOC.
  */
 struct pm8921_bms_chip {
 	struct device		*dev;
@@ -111,7 +115,6 @@
 	unsigned int		pmic_bms_irq[PM_BMS_MAX_INTS];
 	DECLARE_BITMAP(enabled_irqs, PM_BMS_MAX_INTS);
 	struct mutex		bms_output_lock;
-	spinlock_t		bms_100_lock;
 	struct single_row_lut	*adjusted_fcc_temp_lut;
 	unsigned int		charging_began;
 	unsigned int		start_percent;
@@ -127,6 +130,8 @@
 	int			amux_2_trim_delta;
 	uint16_t		prev_last_good_ocv_raw;
 	unsigned int		rconn_mohm;
+	struct mutex		last_ocv_uv_mutex;
+	int			last_ocv_uv;
 };
 
 static struct pm8921_bms_chip *the_chip;
@@ -144,7 +149,6 @@
 module_param(last_charge_increase, int, 0644);
 
 static int last_rbatt = -EINVAL;
-static int last_ocv_uv = -EINVAL;
 static int last_soc = -EINVAL;
 static int last_real_fcc_mah = -EINVAL;
 static int last_real_fcc_batt_temp = -EINVAL;
@@ -163,7 +167,6 @@
 };
 
 module_param_cb(last_rbatt, &bms_param_ops, &last_rbatt, 0644);
-module_param_cb(last_ocv_uv, &bms_param_ops, &last_ocv_uv, 0644);
 module_param_cb(last_soc, &bms_param_ops, &last_soc, 0644);
 
 /*
@@ -957,16 +960,28 @@
 		adjust_pon_ocv_raw(chip, raw);
 		convert_vbatt_raw_to_uv(chip, usb_chg,
 			raw->last_good_ocv_raw, &raw->last_good_ocv_uv);
-		last_ocv_uv = raw->last_good_ocv_uv;
+		chip->last_ocv_uv = raw->last_good_ocv_uv;
 	} else if (chip->prev_last_good_ocv_raw != raw->last_good_ocv_raw) {
 		chip->prev_last_good_ocv_raw = raw->last_good_ocv_raw;
 		convert_vbatt_raw_to_uv(chip, usb_chg,
 			raw->last_good_ocv_raw, &raw->last_good_ocv_uv);
-		last_ocv_uv = raw->last_good_ocv_uv;
+		chip->last_ocv_uv = raw->last_good_ocv_uv;
 	} else {
-		raw->last_good_ocv_uv = last_ocv_uv;
+		raw->last_good_ocv_uv = chip->last_ocv_uv;
 	}
 
+	/* fake a high OCV if we are just done charging */
+	if (chip->ocv_reading_at_100 != raw->last_good_ocv_raw) {
+		chip->ocv_reading_at_100 = 0;
+		chip->cc_reading_at_100 = 0;
+	} else {
+		/*
+		 * force 100% ocv by selecting the highest voltage the
+		 * battery could ever reach
+		 */
+		raw->last_good_ocv_uv = chip->max_voltage_uv;
+		chip->last_ocv_uv = chip->max_voltage_uv;
+	}
 	pr_debug("0p625 = %duV\n", chip->xoadc_v0625);
 	pr_debug("1p25 = %duV\n", chip->xoadc_v125);
 	pr_debug("last_good_ocv_raw= 0x%x, last_good_ocv_uv= %duV\n",
@@ -1120,7 +1135,7 @@
 
 	cc_voltage_uv = cc;
 	cc_voltage_uv -= chip->cc_reading_at_100;
-	pr_debug("cc = %d. after subtracting %d cc = %lld\n",
+	pr_debug("cc = %d. after subtracting 0x%x cc = %lld\n",
 					cc, chip->cc_reading_at_100,
 					cc_voltage_uv);
 	cc_voltage_uv = cc_to_microvolt(chip, cc_voltage_uv);
@@ -1156,25 +1171,7 @@
 {
 	int  ocv, pc;
 
-	/* calculate remainging charge */
-	ocv = 0;
-	if (chip->ocv_reading_at_100 != raw->last_good_ocv_raw) {
-		chip->ocv_reading_at_100 = 0;
-		chip->cc_reading_at_100 = 0;
-		ocv = raw->last_good_ocv_uv;
-	} else {
-		/*
-		 * force 100% ocv by selecting the highest voltage the
-		 * battery could every reach
-		 */
-		ocv = chip->max_voltage_uv;
-	}
-
-	if (ocv == 0) {
-		ocv = last_ocv_uv;
-		pr_debug("ocv not available using last_ocv_uv=%d\n", ocv);
-	}
-
+	ocv = raw->last_good_ocv_uv;
 	pc = calculate_pc(chip, ocv, batt_temp, chargecycles);
 	pr_debug("ocv = %d pc = %d\n", ocv, pc);
 	return (fcc_uah * pc) / 100;
@@ -1189,7 +1186,6 @@
 						int *cc_uah,
 						int *rbatt)
 {
-	unsigned long flags;
 	int soc_rbatt;
 
 	*fcc_uah = calculate_fcc_uah(chip, batt_temp, chargecycles);
@@ -1197,7 +1193,6 @@
 					*fcc_uah, batt_temp, chargecycles);
 
 
-	spin_lock_irqsave(&chip->bms_100_lock, flags);
 	/* calculate remainging charge */
 	*remaining_charge_uah = calculate_remaining_charge_uah(chip, raw,
 					*fcc_uah, batt_temp, chargecycles);
@@ -1205,11 +1200,10 @@
 
 	/* calculate cc micro_volt_hour */
 	calculate_cc_uah(chip, raw->cc, cc_uah);
-	pr_debug("cc_uah = %duAh raw->cc = %x cc = %lld after subtracting %d\n",
+	pr_debug("cc_uah = %duAh raw->cc = %x cc = %lld after subtracting %x\n",
 				*cc_uah, raw->cc,
 				(int64_t)raw->cc - chip->cc_reading_at_100,
 				chip->cc_reading_at_100);
-	spin_unlock_irqrestore(&chip->bms_100_lock, flags);
 
 	soc_rbatt = ((*remaining_charge_uah - *cc_uah) * 100) / *fcc_uah;
 	if (soc_rbatt < 0)
@@ -1245,6 +1239,108 @@
 			real_fcc_uah, remaining_charge_uah, cc_uah, fcc_uah);
 	return real_fcc_uah;
 }
+
+static int bound_soc(int soc)
+{
+	soc = max(0, soc);
+	soc = min(100, soc);
+	return soc;
+}
+
+static int last_soc_est = -EINVAL;
+static int adjust_soc(struct pm8921_bms_chip *chip, int soc, int batt_temp,
+		int rbatt , int fcc_uah, int uuc_uah, int cc_uah)
+{
+	int ibat_ua = 0, vbat_uv = 0;
+	int ocv_est_uv = 0, soc_est = 0, pc_est = 0, pc = 0;
+	int delta_ocv_uv = 0;
+	int n = 0;
+	int rc_new_uah = 0;
+	int pc_new = 0;
+	int soc_new = 0;
+	int m = 0;
+
+	pm8921_bms_get_simultaneous_battery_voltage_and_current(&ibat_ua,
+		&vbat_uv);
+
+	if (ibat_ua < 0)
+		goto out;
+	ocv_est_uv = vbat_uv + (ibat_ua * rbatt)/1000;
+	pc_est = calculate_pc(chip, ocv_est_uv, batt_temp, last_chargecycles);
+	soc_est = div_s64((s64)fcc_uah * pc_est - uuc_uah*100,
+						(s64)fcc_uah - uuc_uah);
+	soc_est = bound_soc(soc_est);
+
+	/*
+	 * do not adjust if soc_est is between 45 and 25 OR soc_est is
+	 * same as what bms calculated
+	 */
+	if (is_between(45, 25, soc_est) || soc_est == soc)
+		goto out;
+
+	if (last_soc_est == -EINVAL)
+		last_soc_est = soc;
+
+	n = min(200, max(1 , soc + soc_est + last_soc_est));
+	/* remember the last soc_est in last_soc_est */
+	last_soc_est = soc_est;
+
+	pc = calculate_pc(chip, chip->last_ocv_uv,
+				batt_temp, last_chargecycles);
+	if (pc > 0) {
+		pc_new = calculate_pc(chip, chip->last_ocv_uv - (++m * 1000),
+						batt_temp, last_chargecycles);
+		while (pc_new == pc) {
+			/* start taking 10mV steps */
+			m = m + 10;
+			pc_new = calculate_pc(chip,
+						chip->last_ocv_uv - (m * 1000),
+						batt_temp, last_chargecycles);
+		}
+	} else {
+		/*
+		 * pc is already at the lowest point,
+		 * assume 1 millivolt translates to 1% pc
+		 */
+		pc = 1;
+		pc_new = 0;
+		m = 1;
+	}
+
+	delta_ocv_uv = div_s64((soc - soc_est) * (s64)m * 1000,
+							n * (pc - pc_new));
+	chip->last_ocv_uv -= delta_ocv_uv;
+
+	if (chip->last_ocv_uv >= chip->max_voltage_uv)
+		chip->last_ocv_uv = chip->max_voltage_uv;
+
+	/* calculate the soc based on this new ocv */
+	pc_new = calculate_pc(chip, chip->last_ocv_uv,
+						batt_temp, last_chargecycles);
+	rc_new_uah = (fcc_uah * pc_new) / 100;
+	soc_new = (rc_new_uah - cc_uah - uuc_uah)*100 / (fcc_uah - uuc_uah);
+	soc_new = bound_soc(soc_new);
+
+	/*
+	 * if soc_new is ZERO force it higher so that phone doesnt report soc=0
+	 * soc = 0 should happen only when soc_est == 0
+	 */
+	if (soc_new == 0 && soc_est != 0)
+		soc_new = 1;
+
+	soc = soc_new;
+
+out:
+	pr_debug("ibat_ua = %d, vbat_uv = %d, ocv_est_uv = %d, pc_est = %d, "
+		"soc_est = %d, n = %d, delta_ocv_uv = %d, last_ocv_uv = %d, "
+		"pc_new = %d, soc_new = %d\n",
+		ibat_ua, vbat_uv, ocv_est_uv, pc_est,
+		soc_est, n, delta_ocv_uv, chip->last_ocv_uv,
+		pc_new, soc_new);
+
+	return soc;
+}
+
 /*
  * Remaining Usable Charge = remaining_charge (charge at ocv instance)
  *				- coloumb counter charge
@@ -1257,7 +1353,6 @@
 {
 	int remaining_usable_charge_uah, fcc_uah, unusable_charge_uah;
 	int remaining_charge_uah, soc;
-	int update_userspace = 1;
 	int cc_uah;
 	int rbatt;
 
@@ -1302,30 +1397,31 @@
 		pr_err("for bad rem_usb_chg last_ocv_uv = %d"
 				"chargecycles = %d, batt_temp = %d"
 				"fcc = %d soc =%d\n",
-				last_ocv_uv, chargecycles, batt_temp,
+				chip->last_ocv_uv, chargecycles, batt_temp,
 				fcc_uah, soc);
-		update_userspace = 0;
 		soc = 0;
 	}
 
-	if (last_soc == -EINVAL || soc <= last_soc) {
-		last_soc = update_userspace ? soc : last_soc;
-		return soc;
-	}
+	soc = adjust_soc(chip, soc, batt_temp, rbatt,
+					fcc_uah, unusable_charge_uah, cc_uah);
 
-	/*
-	 * soc > last_soc
-	 * the device must be charging for reporting a higher soc, if not ignore
-	 * this soc and continue reporting the last_soc
-	 */
-	if (the_chip->start_percent != -EINVAL) {
+	if (last_soc == -EINVAL || soc <= last_soc) {
 		last_soc = soc;
 	} else {
-		pr_debug("soc = %d reporting last_soc = %d\n", soc, last_soc);
-		soc = last_soc;
+		/*
+		 * soc > last_soc
+		 * the device must be charging for reporting a higher soc, if
+		 * not ignore this soc and continue reporting the last_soc
+		 */
+		if (the_chip->start_percent != -EINVAL)
+			last_soc = soc;
+		else
+			pr_debug("soc = %d reporting last_soc = %d\n", soc,
+								last_soc);
 	}
 
-	return soc;
+	pr_debug("Reported SOC = %u%%\n", last_soc);
+	return last_soc;
 }
 #define MIN_DELTA_625_UV	1000
 static void calib_hkadc(struct pm8921_bms_chip *chip)
@@ -1452,6 +1548,7 @@
 	int batt_temp, rc;
 	struct pm8xxx_adc_chan_result result;
 	struct pm8921_soc_params raw;
+	int soc;
 
 	if (!the_chip) {
 		pr_err("called before initialization\n");
@@ -1468,10 +1565,13 @@
 						result.measurement);
 	batt_temp = (int)result.physical;
 
+	mutex_lock(&the_chip->last_ocv_uv_mutex);
 	read_soc_params_raw(the_chip, &raw);
 
-	return calculate_state_of_charge(the_chip, &raw,
+	soc = calculate_state_of_charge(the_chip, &raw,
 					batt_temp, last_chargecycles);
+	mutex_unlock(&the_chip->last_ocv_uv_mutex);
+	return soc;
 }
 EXPORT_SYMBOL_GPL(pm8921_bms_get_percent_charge);
 
@@ -1501,6 +1601,8 @@
 						result.measurement);
 	batt_temp = (int)result.physical;
 
+	mutex_lock(&the_chip->last_ocv_uv_mutex);
+
 	read_soc_params_raw(the_chip, &raw);
 
 	calculate_soc_params(the_chip, &raw, batt_temp, last_chargecycles,
@@ -1509,6 +1611,8 @@
 						&remaining_charge_uah,
 						&cc_uah,
 						&rbatt);
+	mutex_unlock(&the_chip->last_ocv_uv_mutex);
+
 	return rbatt;
 }
 EXPORT_SYMBOL_GPL(pm8921_bms_get_rbatt);
@@ -1556,10 +1660,13 @@
 						result.measurement);
 	batt_temp = (int)result.physical;
 
+	mutex_lock(&the_chip->last_ocv_uv_mutex);
 	read_soc_params_raw(the_chip, &raw);
 
 	the_chip->start_percent = calculate_state_of_charge(the_chip, &raw,
 					batt_temp, last_chargecycles);
+	mutex_unlock(&the_chip->last_ocv_uv_mutex);
+
 	bms_start_percent = the_chip->start_percent;
 	bms_start_ocv_uv = raw.last_good_ocv_uv;
 	calculate_cc_uah(the_chip, raw.cc, &bms_start_cc_uah);
@@ -1590,13 +1697,16 @@
 						result.measurement);
 	batt_temp = (int)result.physical;
 
+	mutex_lock(&the_chip->last_ocv_uv_mutex);
+
 	read_soc_params_raw(the_chip, &raw);
 
 	calculate_cc_uah(the_chip, raw.cc, &bms_end_cc_uah);
 
+	bms_end_ocv_uv = raw.last_good_ocv_uv;
+
 	if (is_battery_full
 		&& the_chip->start_percent <= MIN_START_PERCENT_FOR_LEARNING) {
-		unsigned long flags;
 		int fcc_uah, new_fcc_uah, delta_fcc_uah;
 
 		new_fcc_uah = calculate_real_fcc_uah(the_chip, &raw,
@@ -1627,20 +1737,24 @@
 		last_real_fcc_batt_temp = batt_temp;
 		readjust_fcc_table();
 
-		spin_lock_irqsave(&the_chip->bms_100_lock, flags);
+	}
+
+	if (is_battery_full) {
 		the_chip->ocv_reading_at_100 = raw.last_good_ocv_raw;
 		the_chip->cc_reading_at_100 = raw.cc;
-		spin_unlock_irqrestore(&the_chip->bms_100_lock, flags);
-		pr_debug("EOC ocv_reading = 0x%x cc = %d\n",
+
+		the_chip->last_ocv_uv = the_chip->max_voltage_uv;
+		raw.last_good_ocv_uv = the_chip->max_voltage_uv;
+		pr_debug("EOC ocv_reading = 0x%x cc = 0x%x\n",
 				the_chip->ocv_reading_at_100,
 				the_chip->cc_reading_at_100);
 	}
 
 	the_chip->end_percent = calculate_state_of_charge(the_chip, &raw,
 					batt_temp, last_chargecycles);
+	mutex_unlock(&the_chip->last_ocv_uv_mutex);
 
 	bms_end_percent = the_chip->end_percent;
-	bms_end_ocv_uv = raw.last_good_ocv_uv;
 
 	if (the_chip->end_percent > the_chip->start_percent) {
 		last_charge_increase +=
@@ -1804,6 +1918,8 @@
 					chip->batt_temp_channel, rc);
 	}
 	chip->batt_temp_suspend = (int)result.physical;
+
+	mutex_lock(&chip->last_ocv_uv_mutex);
 	read_soc_params_raw(chip, &raw);
 
 	fcc_uah = calculate_fcc_uah(chip,
@@ -1818,12 +1934,14 @@
 
 	/* calculate cc micro_volt_hour */
 	calculate_cc_uah(chip, raw.cc, &cc_uah);
-	pr_debug("cc_uah = %duAh raw->cc = %x cc = %lld after subtracting %d\n",
+	pr_debug("cc_uah = %duAh raw->cc = %x cc = %lld after subtracting %x\n",
 				cc_uah, raw.cc,
 				(int64_t)raw.cc - chip->cc_reading_at_100,
 				chip->cc_reading_at_100);
 	chip->soc_rbatt_suspend = ((remaining_charge_uah - cc_uah) * 100)
 						/ fcc_uah;
+	mutex_unlock(&chip->last_ocv_uv_mutex);
+
 	return 0;
 }
 
@@ -1911,9 +2029,9 @@
 			pr_err("failed to read adc based ocv_uv rc = %d\n", rc);
 			ocv_uv = DEFAULT_OCV_MICROVOLTS;
 		}
-		last_ocv_uv = ocv_uv;
 	}
-	pr_debug("ocv_uv = %d last_ocv_uv = %d\n", ocv_uv, last_ocv_uv);
+	chip->last_ocv_uv = ocv_uv;
+	pr_debug("ocv_uv = %d last_ocv_uv = %d\n", ocv_uv, chip->last_ocv_uv);
 }
 
 static int64_t read_battery_id(struct pm8921_bms_chip *chip)
@@ -2314,8 +2432,9 @@
 		pr_err("Cannot allocate pm_bms_chip\n");
 		return -ENOMEM;
 	}
+
 	mutex_init(&chip->bms_output_lock);
-	spin_lock_init(&chip->bms_100_lock);
+	mutex_init(&chip->last_ocv_uv_mutex);
 	chip->dev = &pdev->dev;
 	chip->r_sense = pdata->r_sense;
 	chip->i_test = pdata->i_test;
@@ -2387,7 +2506,7 @@
 	get_battery_uvolts(chip, &vbatt);
 	pr_info("OK battery_capacity_at_boot=%d volt = %d ocv = %d\n",
 				pm8921_bms_get_percent_charge(),
-				vbatt, last_ocv_uv);
+				vbatt, chip->last_ocv_uv);
 	return 0;
 
 free_irqs:
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index eea4fa1..8e9d753 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -2211,7 +2211,7 @@
 	reg_loop = pm_chg_get_regulation_loop(chip);
 	pr_debug("reg_loop=0x%x usb_ma = %d\n", reg_loop, usb_ma);
 
-	if (reg_loop & VIN_ACTIVE_BIT) {
+	if ((reg_loop & VIN_ACTIVE_BIT) && (usb_ma > USB_WALL_THRESHOLD_MA)) {
 		decrease_usb_ma_value(&usb_ma);
 		usb_target_ma = usb_ma;
 		/* end AICL here */
diff --git a/drivers/power/smb349.c b/drivers/power/smb349.c
index 148f188..4c07285 100644
--- a/drivers/power/smb349.c
+++ b/drivers/power/smb349.c
@@ -415,7 +415,7 @@
 		debugfs_remove_recursive(smb349_chg->dent);
 }
 
-static int __devinit smb349_hwinit(struct smb349_struct *smb349_chg)
+static int smb349_hwinit(struct smb349_struct *smb349_chg)
 {
 	int ret;
 
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index cc008ab..24da4d1 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -1978,6 +1978,9 @@
 				slc1 = ctrl->sched.chc1[coeff1];
 			}
 		}
+		/* Leave some slots for messaging space */
+		if (opensl1[1] == 0 && opensl1[0] == 0)
+			return -EXFULL;
 		if (opensl1[1] > opensl1[0]) {
 			int temp = opensl1[0];
 			opensl1[0] = opensl1[1];
@@ -2180,6 +2183,9 @@
 				slc1 = ctrl->sched.chc1[coeff1];
 			}
 		}
+		/* Leave some slots for messaging space */
+		if (opensl3[1] == 0 && opensl3[0] == 0)
+			return -EXFULL;
 		/* swap 1st and 2nd bucket if 2nd bucket has more open slots */
 		if (opensl3[1] > opensl3[0]) {
 			int temp = opensl3[0];
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index e2d77e9..69e0546 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -1155,6 +1155,22 @@
 	return xfrs_grped;
 }
 
+static inline void write_force_cs(struct msm_spi *dd, bool set_flag)
+{
+	u32 spi_ioc;
+	u32 spi_ioc_orig;
+
+	spi_ioc = readl_relaxed(dd->base + SPI_IO_CONTROL);
+	spi_ioc_orig = spi_ioc;
+	if (set_flag)
+		spi_ioc |= SPI_IO_C_FORCE_CS;
+	else
+		spi_ioc &= ~SPI_IO_C_FORCE_CS;
+
+	if (spi_ioc != spi_ioc_orig)
+		writel_relaxed(spi_ioc, dd->base + SPI_IO_CONTROL);
+}
+
 static void msm_spi_process_message(struct msm_spi *dd)
 {
 	int xfrs_grped = 0;
@@ -1178,11 +1194,10 @@
 	}
 
 	if (dd->qup_ver) {
+		write_force_cs(dd, 0);
 		list_for_each_entry(dd->cur_transfer,
 				&dd->cur_msg->transfers,
 				transfer_list) {
-			u32 spi_ioc;
-			u32 spi_ioc_orig;
 			struct spi_transfer *t = dd->cur_transfer;
 			struct spi_transfer *nxt;
 
@@ -1191,18 +1206,10 @@
 						struct spi_transfer,
 						transfer_list);
 
-				spi_ioc = readl_relaxed(dd->base +
-							SPI_IO_CONTROL);
-				spi_ioc_orig = spi_ioc;
 				if (t->cs_change == nxt->cs_change)
-					spi_ioc |= SPI_IO_C_FORCE_CS;
+					write_force_cs(dd, 1);
 				else
-					spi_ioc &= ~SPI_IO_C_FORCE_CS;
-
-				if (spi_ioc != spi_ioc_orig) {
-					writel_relaxed(spi_ioc,
-						dd->base + SPI_IO_CONTROL);
-				}
+					write_force_cs(dd, 0);
 			}
 
 			dd->cur_msg_len = dd->cur_transfer->len;
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index fc665ed..5b0b279 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -367,7 +367,7 @@
  * test scripts.
  * writing 0 disables the internal loopback mode. Default is disabled.
  */
-static void __init msm_serial_debugfs_init(struct msm_hs_port *msm_uport,
+static void __devinit msm_serial_debugfs_init(struct msm_hs_port *msm_uport,
 					   int id)
 {
 	char node_name[15];
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
index 0598c7b..02b2cc3 100644
--- a/drivers/usb/gadget/f_mbim.c
+++ b/drivers/usb/gadget/f_mbim.c
@@ -100,8 +100,6 @@
 	u32			ntb_input_size;
 	u16			ntb_max_datagrams;
 
-	pid_t			user_pid;
-
 	atomic_t		error;
 };
 
@@ -619,6 +617,59 @@
 	atomic_set(&mbim->online, 0);
 }
 
+static void mbim_reset_function_queue(struct f_mbim *dev)
+{
+	struct ctrl_pkt	*cpkt = NULL;
+
+	pr_debug("Queue empty packet for QBI");
+
+	spin_lock(&dev->lock);
+	if (!dev->is_open) {
+		pr_err("%s: mbim file handler %p is not open", __func__, dev);
+		spin_unlock(&dev->lock);
+		return;
+	}
+
+	cpkt = mbim_alloc_ctrl_pkt(0, GFP_ATOMIC);
+	if (!cpkt) {
+		pr_err("%s: Unable to allocate reset function pkt\n", __func__);
+		spin_unlock(&dev->lock);
+		return;
+	}
+
+	list_add_tail(&cpkt->list, &dev->cpkt_req_q);
+	spin_unlock(&dev->lock);
+
+	pr_debug("%s: Wake up read queue", __func__);
+	wake_up(&dev->read_wq);
+}
+
+static void fmbim_reset_cmd_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_mbim		*dev = req->context;
+
+	mbim_reset_function_queue(dev);
+}
+
+static void mbim_clear_queues(struct f_mbim *mbim)
+{
+	struct ctrl_pkt	*cpkt = NULL;
+	struct list_head *act, *tmp;
+
+	spin_lock(&mbim->lock);
+	list_for_each_safe(act, tmp, &mbim->cpkt_req_q) {
+		cpkt = list_entry(act, struct ctrl_pkt, list);
+		list_del(&cpkt->list);
+		mbim_free_ctrl_pkt(cpkt);
+	}
+	list_for_each_safe(act, tmp, &mbim->cpkt_resp_q) {
+		cpkt = list_entry(act, struct ctrl_pkt, list);
+		list_del(&cpkt->list);
+		mbim_free_ctrl_pkt(cpkt);
+	}
+	spin_unlock(&mbim->lock);
+}
+
 /*
  * Context: mbim->lock held
  */
@@ -741,6 +792,9 @@
 		mbim->not_port.notify_state = NCM_NOTIFY_NONE;
 		atomic_set(&mbim->not_port.notify_count, 0);
 		pr_info("ESHUTDOWN/ECONNRESET, connection gone");
+		spin_unlock(&mbim->lock);
+		mbim_clear_queues(mbim);
+		mbim_reset_function_queue(mbim);
 		break;
 	default:
 		pr_err("Unknown event %02x --> %d\n",
@@ -880,21 +934,8 @@
 
 		pr_info("USB_CDC_RESET_FUNCTION");
 		value = 0;
-		if (!_mbim_dev->user_pid) {
-			pr_err("QBI pid is not set");
-			break;
-		}
-
-		if (!_mbim_dev->is_open) {
-			pr_err("QBI is not up yet");
-			break;
-		}
-
-		send_sig_info(SIGUSR1, SEND_SIG_NOINFO,
-			find_task_by_vpid(_mbim_dev->user_pid));
-
-		pr_info("Sent signal to QBI pid %d",
-			_mbim_dev->user_pid);
+		req->complete = fmbim_reset_cmd_complete;
+		req->context = mbim;
 		break;
 
 	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
@@ -1200,12 +1241,8 @@
 	pr_info("SET DEVICE OFFLINE");
 	atomic_set(&mbim->online, 0);
 
-	if (_mbim_dev && _mbim_dev->user_pid && _mbim_dev->is_open) {
-		send_sig_info(SIGUSR1, SEND_SIG_NOINFO,
-			find_task_by_vpid(_mbim_dev->user_pid));
-		pr_info("Sending reset signal to QBI pid %d",
-			_mbim_dev->user_pid);
-	}
+	mbim_clear_queues(mbim);
+	mbim_reset_function_queue(mbim);
 
 	mbim_bam_disconnect(mbim);
 
@@ -1599,9 +1636,6 @@
 	if (!atomic_read(&_mbim_dev->online))
 		pr_err("USB cable not connected\n");
 
-	pr_info("Set QBI pid %d\n", pid_nr(task_pid(current)));
-	_mbim_dev->user_pid = pid_nr(task_pid(current));
-
 	fp->private_data = _mbim_dev;
 
 	atomic_set(&_mbim_dev->error, 0);
@@ -1627,8 +1661,6 @@
 	mbim_notify(mbim);
 	spin_unlock(&mbim->lock);
 
-	mbim->user_pid = 0;
-
 	mbim_unlock(&_mbim_dev->open_excl);
 
 	return 0;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index b428bd2..f319eb5 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -45,6 +45,7 @@
 #include <mach/clk.h>
 #include <mach/msm_xo.h>
 #include <mach/msm_bus.h>
+#include <mach/rpm-regulator.h>
 
 #define MSM_USB_BASE	(motg->regs)
 #define DRIVER_NAME	"msm_otg"
@@ -61,6 +62,7 @@
 #define USB_PHY_1P8_HPM_LOAD	50000	/* uA */
 #define USB_PHY_1P8_LPM_LOAD	4000	/* uA */
 
+#define USB_PHY_VDD_DIG_VOL_NONE	0 /*uV */
 #define USB_PHY_VDD_DIG_VOL_MIN	1045000 /* uV */
 #define USB_PHY_VDD_DIG_VOL_MAX	1320000 /* uV */
 
@@ -104,53 +106,25 @@
 #endif
 }
 
-static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
-{
-	int ret = 0;
+enum usb_vdd_value {
+	VDD_NONE = 0,
+	VDD_MIN,
+	VDD_MAX,
+	VDD_VAL_MAX,
+};
 
-	if (init) {
-		hsusb_vddcx = devm_regulator_get(motg->otg.dev, "HSUSB_VDDCX");
-		if (IS_ERR(hsusb_vddcx)) {
-			dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
-			return PTR_ERR(hsusb_vddcx);
-		}
-
-		ret = regulator_set_voltage(hsusb_vddcx,
-				USB_PHY_VDD_DIG_VOL_MIN,
-				USB_PHY_VDD_DIG_VOL_MAX);
-		if (ret) {
-			dev_err(motg->otg.dev, "unable to set the voltage "
-					"for hsusb vddcx\n");
-			return ret;
-		}
-
-		ret = regulator_enable(hsusb_vddcx);
-		if (ret) {
-			regulator_set_voltage(hsusb_vddcx, 0,
-			USB_PHY_VDD_DIG_VOL_MIN);
-			dev_err(motg->otg.dev, "unable to enable the hsusb vddcx\n");
-			return ret;
-		}
-
-	} else {
-
-		ret = regulator_disable(hsusb_vddcx);
-		if (ret) {
-			dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
-			return ret;
-		}
-
-		ret = regulator_set_voltage(hsusb_vddcx, 0,
-			USB_PHY_VDD_DIG_VOL_MIN);
-		if (ret) {
-			dev_err(motg->otg.dev, "unable to set the voltage"
-					"for hsusb vddcx\n");
-			return ret;
-		}
-	}
-
-	return ret;
-}
+static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
+		{  /* VDD_CX CORNER Voting */
+			[VDD_NONE]	= RPM_VREG_CORNER_NONE,
+			[VDD_MIN]	= RPM_VREG_CORNER_NOMINAL,
+			[VDD_MAX]	= RPM_VREG_CORNER_HIGH,
+		},
+		{ /* VDD_CX Voltage Voting */
+			[VDD_NONE]	= USB_PHY_VDD_DIG_VOL_NONE,
+			[VDD_MIN]	= USB_PHY_VDD_DIG_VOL_MIN,
+			[VDD_MAX]	= USB_PHY_VDD_DIG_VOL_MAX,
+		},
+};
 
 static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
 {
@@ -194,19 +168,15 @@
 	return rc;
 }
 
-#ifdef CONFIG_PM_SLEEP
-#define USB_PHY_SUSP_DIG_VOL  500000
 static int msm_hsusb_config_vddcx(int high)
 {
-	int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
+	struct msm_otg *motg = the_msm_otg;
+	enum usb_vdd_type vdd_type = motg->vdd_type;
+	int max_vol = vdd_val[vdd_type][VDD_MAX];
 	int min_vol;
 	int ret;
 
-	if (high)
-		min_vol = USB_PHY_VDD_DIG_VOL_MIN;
-	else
-		min_vol = USB_PHY_SUSP_DIG_VOL;
-
+	min_vol = vdd_val[vdd_type][!!high];
 	ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
 	if (ret) {
 		pr_err("%s: unable to set the voltage for regulator "
@@ -218,12 +188,6 @@
 
 	return ret;
 }
-#else
-static int msm_hsusb_config_vddcx(int high)
-{
-	return 0;
-}
-#endif
 
 static int msm_hsusb_ldo_enable(struct msm_otg *motg, int on)
 {
@@ -565,6 +529,8 @@
 		ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
 		ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL);
 	} else if (pdata->otg_control == OTG_PMIC_CONTROL) {
+		ulpi_write(otg, OTG_COMP_DISABLE,
+			ULPI_SET(ULPI_PWR_CLK_MNG_REG));
 		/* Enable PMIC pull-up */
 		pm8xxx_usb_id_pullup(1);
 	}
@@ -804,15 +770,6 @@
 		ulpi_write(otg, 0x08, 0x09);
 	}
 
-	/*
-	 * Turn off the OTG comparators, if depends on PMIC for
-	 * VBUS and ID notifications.
-	 */
-	if ((motg->caps & ALLOW_PHY_COMP_DISABLE) && !host_bus_suspend) {
-		ulpi_write(otg, OTG_COMP_DISABLE,
-			ULPI_SET(ULPI_PWR_CLK_MNG_REG));
-		motg->lpm_flags |= PHY_OTG_COMP_DISABLED;
-	}
 
 	/* Set the PHCD bit, only if it is not set by the controller.
 	 * PHY may take some time or even fail to enter into low power
@@ -986,12 +943,6 @@
 	}
 
 skip_phy_resume:
-	/* Turn on the OTG comparators on resume */
-	if (motg->lpm_flags & PHY_OTG_COMP_DISABLED) {
-		ulpi_write(otg, OTG_COMP_DISABLE,
-			ULPI_CLR(ULPI_PWR_CLK_MNG_REG));
-		motg->lpm_flags &= ~PHY_OTG_COMP_DISABLED;
-	}
 	if (device_may_wakeup(otg->dev)) {
 		disable_irq_wake(motg->irq);
 		if (motg->pdata->pmic_id_irq)
@@ -1134,6 +1085,10 @@
 	if (on) {
 		dev_dbg(otg->dev, "host on\n");
 
+		if (pdata->otg_control == OTG_PHY_CONTROL)
+			ulpi_write(otg, OTG_COMP_DISABLE,
+				ULPI_SET(ULPI_PWR_CLK_MNG_REG));
+
 		/*
 		 * Some boards have a switch cotrolled by gpio
 		 * to enable/disable internal HUB. Enable internal
@@ -1151,6 +1106,10 @@
 
 		if (pdata->setup_gpio)
 			pdata->setup_gpio(OTG_STATE_UNDEFINED);
+
+		if (pdata->otg_control == OTG_PHY_CONTROL)
+			ulpi_write(otg, OTG_COMP_DISABLE,
+				ULPI_CLR(ULPI_PWR_CLK_MNG_REG));
 	}
 }
 
@@ -3321,22 +3280,33 @@
 
 	clk_prepare_enable(motg->pclk);
 
-	ret = msm_hsusb_init_vddcx(motg, 1);
-	if (ret) {
-		dev_err(&pdev->dev, "hsusb vddcx init failed\n");
-		goto devote_xo_handle;
+	motg->vdd_type = VDDCX_CORNER;
+	hsusb_vddcx = devm_regulator_get(motg->otg.dev, "hsusb_vdd_dig");
+	if (IS_ERR(hsusb_vddcx)) {
+		hsusb_vddcx = devm_regulator_get(motg->otg.dev, "HSUSB_VDDCX");
+		if (IS_ERR(hsusb_vddcx)) {
+			dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
+			goto devote_xo_handle;
+		}
+		motg->vdd_type = VDDCX;
 	}
 
 	ret = msm_hsusb_config_vddcx(1);
 	if (ret) {
 		dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
-		goto free_init_vddcx;
+		goto devote_xo_handle;
+	}
+
+	ret = regulator_enable(hsusb_vddcx);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable the hsusb vddcx\n");
+		goto free_config_vddcx;
 	}
 
 	ret = msm_hsusb_ldo_init(motg, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
-		goto free_init_vddcx;
+		goto free_hsusb_vddcx;
 	}
 
 	if (pdata->mhl_enable) {
@@ -3427,8 +3397,7 @@
 			(!(motg->pdata->mode == USB_OTG) ||
 			 motg->pdata->pmic_id_irq))
 			motg->caps = ALLOW_PHY_POWER_COLLAPSE |
-				ALLOW_PHY_RETENTION |
-				ALLOW_PHY_COMP_DISABLE;
+				ALLOW_PHY_RETENTION;
 
 		if (motg->pdata->otg_control == OTG_PHY_CONTROL)
 			motg->caps = ALLOW_PHY_RETENTION;
@@ -3460,8 +3429,12 @@
 	msm_hsusb_ldo_enable(motg, 0);
 free_ldo_init:
 	msm_hsusb_ldo_init(motg, 0);
-free_init_vddcx:
-	msm_hsusb_init_vddcx(motg, 0);
+free_hsusb_vddcx:
+	regulator_disable(hsusb_vddcx);
+free_config_vddcx:
+	regulator_set_voltage(hsusb_vddcx,
+		vdd_val[motg->vdd_type][VDD_NONE],
+		vdd_val[motg->vdd_type][VDD_MAX]);
 devote_xo_handle:
 	clk_disable_unprepare(motg->pclk);
 	msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
@@ -3535,7 +3508,10 @@
 	msm_xo_put(motg->xo_handle);
 	msm_hsusb_ldo_enable(motg, 0);
 	msm_hsusb_ldo_init(motg, 0);
-	msm_hsusb_init_vddcx(motg, 0);
+	regulator_disable(hsusb_vddcx);
+	regulator_set_voltage(hsusb_vddcx,
+		vdd_val[motg->vdd_type][VDD_NONE],
+		vdd_val[motg->vdd_type][VDD_MAX]);
 
 	iounmap(motg->regs);
 	pm_runtime_set_suspended(&pdev->dev);
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index 578e339..b8d1df8 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -802,9 +802,18 @@
 	  Support for HDMI CEC Feature
 	  Choose to enable CEC
 
-config FB_MSM_HDMI_MHL
+config FB_MSM_HDMI_MHL_9244
 	depends on FB_MSM_HDMI_MSM_PANEL
-	bool 'HDMI to MHL support'
+	bool 'SI_MHL 9244 support'
+	default n
+	---help---
+	  Support the HDMI to MHL conversion.
+	  MHL (Mobile High-Definition Link) technology
+	  uses USB connector to output HDMI content
+
+config FB_MSM_HDMI_MHL_8334
+	depends on FB_MSM_HDMI_MSM_PANEL
+	bool 'SI_MHL 8334 support '
 	default n
 	---help---
 	  Support the HDMI to MHL conversion.
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index 5a72ad4..b2ecb08 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -171,6 +171,11 @@
 
 obj-$(CONFIG_FB_MSM_TVOUT) += tvout_msm.o
 
+ccflags-y := -I$(src)/mhl
+obj-$(CONFIG_FB_MSM_HDMI_MHL_8334) += mhl-8334.o
+mhl-8334-objs  += mhl/mhl_8334.o
+mhl-8334-objs  += mhl/mhl_i2c_utils.o
+
 obj-$(CONFIG_FB_MSM_EXTMDDI_SVGA) += mddi_ext_lcd.o
 
 obj-$(CONFIG_FB_MSM_WRITEBACK_MSM_PANEL) += mdp4_wfd_writeback_panel.o
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index e749a44..2ca9296 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -177,6 +177,9 @@
 	case MDP_BLOCK_OVERLAY_1:
 		base = 0x18000;
 		break;
+	case MDP_BLOCK_OVERLAY_2:
+		base = (mdp_rev >= MDP_REV_44) ? 0x88000 : 0;
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index d765744..860209f 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -238,6 +238,9 @@
 #define MDP4_OP_SCALEY_EN	BIT(1)
 #define MDP4_OP_SCALEX_EN	BIT(0)
 
+#define MDP4_REV40_UP_SCALING_MAX (8)
+#define MDP4_REV41_OR_LATER_UP_SCALING_MAX (20)
+
 #define MDP4_PIPE_PER_MIXER	2
 
 #define MDP4_MAX_PLANE		4
@@ -755,7 +758,7 @@
 int mdp4_csc_enable(struct mdp_csc_cfg_data *config);
 int mdp4_pcc_cfg(struct mdp_pcc_cfg_data *cfg_ptr);
 int mdp4_argc_cfg(struct mdp_pgc_lut_data *pgc_ptr);
-
+int mdp4_qseed_cfg(struct mdp_qseed_cfg_data *cfg);
 u32  mdp4_allocate_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
 void mdp4_init_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
 void mdp4_free_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index b40d88a..7cc73de 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -99,7 +99,7 @@
 static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
 static int new_perf_level;
 static struct ion_client *display_iclient;
-static struct mdp4_iommu_pipe_info mdp_iommu[MDP4_MIXER_MAX][OVERLAY_PIPE_RGB3];
+static struct mdp4_iommu_pipe_info mdp_iommu[MDP4_MIXER_MAX][OVERLAY_PIPE_MAX];
 
 int mdp4_overlay_iommu_map_buf(int mem_id,
 	struct mdp4_overlay_pipe *pipe, unsigned int plane,
@@ -160,7 +160,7 @@
 	if (!display_iclient)
 		return;
 
-	for (j = 0; j < OVERLAY_PIPE_RGB3; j++) {
+	for (j = 0; j < OVERLAY_PIPE_MAX; j++) {
 		iom_pipe_info = &mdp_iommu[pipe->mixer_num][j];
 		for (i = 0; i < MDP4_MAX_PLANE; i++) {
 			if (iom_pipe_info->prev_ihdl[i]) {
@@ -497,8 +497,13 @@
 	pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
 
 	if (pipe->dst_h && pipe->src_h != pipe->dst_h) {
-		if (pipe->dst_h > pipe->src_h * 8)	/* too much */
+		u32 upscale_max;
+		upscale_max = (mdp_rev >= MDP_REV_41) ?
+			MDP4_REV41_OR_LATER_UP_SCALING_MAX :
+			MDP4_REV40_UP_SCALING_MAX;
+		if (pipe->dst_h > pipe->src_h * upscale_max)
 			return;
+
 		pipe->op_mode |= MDP4_OP_SCALEY_EN;
 
 		if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
@@ -520,10 +525,14 @@
 	}
 
 	if (pipe->dst_w && pipe->src_w != pipe->dst_w) {
-		if (pipe->dst_w > pipe->src_w * 8)	/* too much */
+		u32 upscale_max;
+		upscale_max = (mdp_rev >= MDP_REV_41) ?
+			MDP4_REV41_OR_LATER_UP_SCALING_MAX :
+			MDP4_REV40_UP_SCALING_MAX;
+
+		if (pipe->dst_w > pipe->src_w * upscale_max)
 			return;
 		pipe->op_mode |= MDP4_OP_SCALEX_EN;
-
 		if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
 			if (pipe->flags & MDP_BACKEND_COMPOSITION &&
 				pipe->alpha_enable && pipe->dst_w > pipe->src_w)
@@ -1895,6 +1904,11 @@
 	struct mdp4_iommu_pipe_info *iom_pipe_info;
 	int ret, ptype;
 
+	u32 upscale_max;
+	upscale_max = (mdp_rev >= MDP_REV_41) ?
+		MDP4_REV41_OR_LATER_UP_SCALING_MAX :
+		MDP4_REV40_UP_SCALING_MAX;
+
 	if (mfd == NULL) {
 		pr_err("%s: mfd == NULL, -ENODEV\n", __func__);
 		return -ENODEV;
@@ -1919,8 +1933,7 @@
 		return -EINVAL;
 	}
 
-
-	if (req->dst_rect.h > (req->src_rect.h * 8)) {	/* too much */
+	if (req->dst_rect.h > (req->src_rect.h * upscale_max)) {
 		mdp4_stat.err_scale++;
 		pr_err("%s: scale up, too much (h)!\n", __func__);
 		return -ERANGE;
@@ -1932,7 +1945,7 @@
 		return -ERANGE;
 	}
 
-	if (req->dst_rect.w > (req->src_rect.w * 8)) {	/* too much */
+	if (req->dst_rect.w > (req->src_rect.w * upscale_max)) {
 		mdp4_stat.err_scale++;
 		pr_err("%s: scale up, too much (w)!\n", __func__);
 		return -ERANGE;
@@ -2671,6 +2684,11 @@
 
 	pipe = mdp4_overlay_ndx2pipe(req->id);
 
+	if (!pipe) {
+		mdp4_stat.err_play++;
+		return -ENODEV;
+	}
+
 	if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
 		return -EINTR;
 
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index 5e0b0c7..b9760bf 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -259,14 +259,8 @@
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
 
 	if (dtv_pipe != NULL) {
-		mdp4_mixer_stage_down(dtv_pipe);
-		/*
-		 * wait4vsync to make sure pipes are
-		 * dis-engaged from mixer1
-		 * before turn off timing generator
-		 */
-		mdp4_overlay_dtv_wait4vsync();
 		mdp4_dtv_stop(mfd);
+		mdp4_mixer_stage_down(dtv_pipe);
 		mdp4_overlay_pipe_free(dtv_pipe);
 		mdp4_iommu_unmap(dtv_pipe);
 		dtv_pipe = NULL;
@@ -453,6 +447,12 @@
 	if (mfd->ov_start)
 		return;
 
+	if (!dtv_pipe) {
+		pr_debug("%s: no mixer1 base layer pipe allocated!\n",
+			 __func__);
+		return;
+	}
+
 	if (dtv_pipe->blt_addr) {
 		mdp4_dtv_blt_ov_update(dtv_pipe);
 		dtv_pipe->ov_cnt++;
@@ -481,6 +481,12 @@
 		return;
 	if (!(data & 0x1) || (pipe == NULL))
 		return;
+	if (!dtv_pipe) {
+		pr_debug("%s: no mixer1 base layer pipe allocated!\n",
+			 __func__);
+		return;
+	}
+
 	wait_for_completion_timeout(&dtv_pipe->comp,
 			msecs_to_jiffies(VSYNC_PERIOD*2));
 	mdp_disable_irq(MDP_OVERLAY1_TERM);
@@ -521,11 +527,15 @@
 
 void mdp4_dma_e_done_dtv()
 {
+	if (!dtv_pipe)
+		return;
+
 	complete(&dtv_pipe->comp);
 }
 
 void mdp4_external_vsync_dtv()
 {
+
 	complete_all(&dtv_comp);
 }
 
@@ -534,6 +544,8 @@
  */
 void mdp4_overlay1_done_dtv()
 {
+	if (!dtv_pipe)
+		return;
 	if (dtv_pipe->blt_addr) {
 		mdp4_dtv_blt_dmae_update(dtv_pipe);
 		dtv_pipe->dmae_cnt++;
@@ -593,6 +605,11 @@
 {
 	unsigned long flag;
 
+	if (!dtv_pipe) {
+		pr_debug("%s: no mixer1 base layer pipe allocated!\n",
+			 __func__);
+		return;
+	}
 	/* enable irq */
 	spin_lock_irqsave(&mdp_spin_lock, flag);
 	mdp_enable_irq(MDP_DMA_E_TERM);
@@ -616,6 +633,12 @@
 		return;
 	}
 
+	if (!dtv_pipe) {
+		pr_debug("%s: no mixer1 base layer pipe allocated!\n",
+			 __func__);
+		return;
+	}
+
 	spin_lock_irqsave(&mdp_spin_lock, flag);
 	if (enable && dtv_pipe->blt_addr == 0) {
 		dtv_pipe->blt_addr = mfd->ov1_wb_buf->phys_addr;
@@ -656,7 +679,11 @@
 	struct mdp4_overlay_pipe *pipe;
 	if (!mfd->panel_power_on)
 		return;
-
+	if (!dtv_pipe) {
+		pr_debug("%s: no mixer1 base layer pipe allocated!\n",
+			 __func__);
+		return;
+	}
 	mutex_lock(&mfd->dma->ov_mutex);
 	pipe = dtv_pipe;
 	if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 9f8b5c6..b2657cf 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -2413,6 +2413,9 @@
 	case MDP_BLOCK_OVERLAY_1:
 		base = 0x1A000;
 		break;
+	case MDP_BLOCK_OVERLAY_2:
+		base = (mdp_rev >= MDP_REV_44) ? 0x8A000 : 0x0;
+		break;
 	case MDP_BLOCK_VG_1:
 		base = 0x24000;
 		break;
@@ -2468,6 +2471,11 @@
 		output = config->csc_data.flags;
 		mask = 0x07;
 		break;
+	case MDP_BLOCK_OVERLAY_2:
+		base = 0x88200;
+		output = config->csc_data.flags;
+		mask = 0x07;
+		break;
 	default:
 		pr_err("%s - CSC block does not exist on MDP_BLOCK = %d\n",
 						__func__, config->block);
@@ -2779,13 +2787,11 @@
 
 #define MDP_PCC_OFFSET 0xA000
 #define MDP_DMA_GC_OFFSET 0x8800
-#define MDP_LM_0_GC_OFFSET 0x4800
-#define MDP_LM_1_GC_OFFSET 0x4880
-
+#define MDP_LM_GC_OFFSET 0x4800
 
 #define MDP_DMA_P_OP_MODE_OFFSET 0x70
 #define MDP_DMA_S_OP_MODE_OFFSET 0x28
-#define MDP_LM_OP_MODE_OFFSET 0x10
+#define MDP_LM_OP_MODE_OFFSET 0x14
 
 #define DMA_PCC_R2_OFFSET 0x100
 
@@ -2886,6 +2892,10 @@
 		valid = (mdp_rev >= MDP_REV_42) ? 1 : 0;
 		break;
 
+	case MDP_BLOCK_OVERLAY_2:
+		valid = (mdp_rev >= MDP_REV_44) ? 1 : 0;
+		break;
+
 	default:
 		break;
 	}
@@ -3021,11 +3031,8 @@
 
 	case MDP_BLOCK_OVERLAY_0:
 	case MDP_BLOCK_OVERLAY_1:
-		offset = (uint32_t *)(blockbase +
-				(MDP_BLOCK_OVERLAY_0 == pgc_ptr->block ?
-				 MDP_LM_0_GC_OFFSET
-				 : MDP_LM_1_GC_OFFSET));
-
+	case MDP_BLOCK_OVERLAY_2:
+		offset = (uint32_t *)(blockbase + MDP_LM_GC_OFFSET);
 		pgc_enable_offset = (uint32_t *)(blockbase
 				+ MDP_LM_OP_MODE_OFFSET);
 		lshift_bits = 2;
@@ -3205,3 +3212,90 @@
 error:
 	return ret;
 }
+
+#define QSEED_TABLE_1_COUNT	2
+#define QSEED_TABLE_2_COUNT	1024
+
+static uint32_t mdp4_pp_block2qseed(uint32_t block)
+{
+	uint32_t valid = 0;
+	switch (block) {
+	case MDP_BLOCK_VG_1:
+	case MDP_BLOCK_VG_2:
+		valid = 0x1;
+		break;
+	default:
+		break;
+	}
+	return valid;
+}
+
+static int mdp4_qseed_write_cfg(struct mdp_qseed_cfg_data *cfg)
+{
+	int i, ret = 0;
+	uint32_t base = (uint32_t) (MDP_BASE + mdp_block2base(cfg->block));
+	uint32_t *values;
+
+	if ((cfg->table_num != 1) && (cfg->table_num != 2)) {
+		ret = -ENOTTY;
+		goto error;
+	}
+
+	if (((cfg->table_num == 1) && (cfg->len != QSEED_TABLE_1_COUNT)) ||
+		((cfg->table_num == 2) && (cfg->len != QSEED_TABLE_2_COUNT))) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	values = kmalloc(cfg->len * sizeof(uint32_t), GFP_KERNEL);
+	if (!values) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	ret = copy_from_user(values, cfg->data, sizeof(uint32_t) * cfg->len);
+
+	base += (cfg->table_num == 1) ? MDP4_QSEED_TABLE1_OFF :
+						MDP4_QSEED_TABLE2_OFF;
+	for (i = 0; i < cfg->len; i++) {
+		MDP_OUTP(base , values[i]);
+		base += sizeof(uint32_t);
+	}
+
+	kfree(values);
+error:
+	return ret;
+}
+
+int mdp4_qseed_cfg(struct mdp_qseed_cfg_data *cfg)
+{
+	int ret = 0;
+
+	if (!mdp4_pp_block2qseed(cfg->block)) {
+		ret = -ENOTTY;
+		goto error;
+	}
+
+	if (cfg->table_num != 1) {
+		ret = -ENOTTY;
+		pr_info("%s: Only QSEED table1 supported.\n", __func__);
+		goto error;
+	}
+
+	switch ((cfg->ops & 0x6) >> 1) {
+	case 0x1:
+		pr_info("%s: QSEED read not supported\n", __func__);
+		ret = -ENOTTY;
+		break;
+	case 0x2:
+		ret = mdp4_qseed_write_cfg(cfg);
+		if (ret)
+			goto error;
+		break;
+	default:
+		break;
+	}
+
+error:
+	return ret;
+}
diff --git a/drivers/video/msm/mhl/mhl_8334.c b/drivers/video/msm/mhl/mhl_8334.c
new file mode 100644
index 0000000..43280a5
--- /dev/null
+++ b/drivers/video/msm/mhl/mhl_8334.c
@@ -0,0 +1,849 @@
+/* Copyright (c) 2012, 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/bitops.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <mach/msm_hdmi_audio.h>
+#include <mach/clk.h>
+#include <mach/msm_iomap.h>
+#include <mach/socinfo.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
+#include "msm_fb.h"
+#include "external_common.h"
+#include "mhl_8334.h"
+#include "mhl_i2c_utils.h"
+
+#define DEBUG
+
+
+static struct i2c_device_id mhl_sii_i2c_id[] = {
+	{ MHL_DRIVER_NAME, 0 },
+	{ }
+};
+
+struct mhl_msm_state_t *mhl_msm_state;
+spinlock_t mhl_state_lock;
+
+static int mhl_i2c_probe(struct i2c_client *client,\
+	const struct i2c_device_id *id);
+static int mhl_i2c_remove(struct i2c_client *client);
+static void force_usb_switch_open(void);
+static void release_usb_switch_open(void);
+static void switch_mode(enum mhl_st_type to_mode);
+static irqreturn_t mhl_tx_isr(int irq, void *dev_id);
+
+static struct i2c_driver mhl_sii_i2c_driver = {
+	.driver = {
+		.name = MHL_DRIVER_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = mhl_i2c_probe,
+	/*.remove =  __exit_p(mhl_i2c_remove),*/
+	.remove =  mhl_i2c_remove,
+	.id_table = mhl_sii_i2c_id,
+};
+
+bool mhl_is_connected(void)
+{
+	return true;
+}
+
+static void cbus_reset(void)
+{
+	uint8_t i;
+
+	/*
+	 * REG_SRST
+	 */
+	mhl_i2c_reg_modify(TX_PAGE_3, 0x0000, BIT3, BIT3);
+	msleep(20);
+	mhl_i2c_reg_modify(TX_PAGE_3, 0x0000, BIT3, 0x00);
+	/*
+	 * REG_INTR1 and REG_INTR4
+	 */
+	mhl_i2c_reg_write(TX_PAGE_L0, 0x0075, BIT6 | BIT5);
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0022,
+		BIT0 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6);
+	/* REG5 */
+	if (mhl_msm_state->chip_rev_id < 1)
+		mhl_i2c_reg_write(TX_PAGE_3, 0x0024, BIT3 | BIT4);
+	else
+		/*REG5 Mask disabled due to auto FIFO reset ??*/
+		mhl_i2c_reg_write(TX_PAGE_3, 0x0024, 0x00);
+
+	/* Unmask CBUS1 Intrs */
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0009,
+		BIT2 | BIT3 | BIT4 | BIT5 | BIT6);
+
+	/* Unmask CBUS2 Intrs */
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x001F, BIT2 | BIT3);
+
+	for (i = 0; i < 4; i++) {
+		/*
+		 * Enable WRITE_STAT interrupt for writes to
+		 * all 4 MSC Status registers.
+		 */
+		mhl_i2c_reg_write(TX_PAGE_CBUS, (0xE0 + i), 0xFF);
+
+		/*
+		 * Enable SET_INT interrupt for writes to
+		 * all 4 MSC Interrupt registers.
+		 */
+		mhl_i2c_reg_write(TX_PAGE_CBUS, (0xF0 + i), 0xFF);
+	}
+}
+
+static void init_cbus_regs(void)
+{
+	uint8_t		regval;
+
+	/* Increase DDC translation layer timer*/
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0007, 0xF2);
+	/* Drive High Time */
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0036, 0x03);
+	/* Use programmed timing */
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0039, 0x30);
+	/* CBUS Drive Strength */
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0040, 0x03);
+	/*
+	 * Write initial default settings
+	 * to devcap regs: default settings
+	 */
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_DEV_STATE,
+		DEVCAP_VAL_DEV_STATE);
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_MHL_VERSION,
+		DEVCAP_VAL_MHL_VERSION);
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_DEV_CAT,
+		DEVCAP_VAL_DEV_CAT);
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_ADOPTER_ID_H,
+		DEVCAP_VAL_ADOPTER_ID_H);
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_ADOPTER_ID_L,
+		DEVCAP_VAL_ADOPTER_ID_L);
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_VID_LINK_MODE,
+		DEVCAP_VAL_VID_LINK_MODE);
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_AUD_LINK_MODE,
+		DEVCAP_VAL_AUD_LINK_MODE);
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_VIDEO_TYPE,
+		DEVCAP_VAL_VIDEO_TYPE);
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_LOG_DEV_MAP,
+		DEVCAP_VAL_LOG_DEV_MAP);
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_BANDWIDTH,
+		DEVCAP_VAL_BANDWIDTH);
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_FEATURE_FLAG,
+		DEVCAP_VAL_FEATURE_FLAG);
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_DEVICE_ID_H,
+		DEVCAP_VAL_DEVICE_ID_H);
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_DEVICE_ID_L,
+		DEVCAP_VAL_DEVICE_ID_L);
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_SCRATCHPAD_SIZE,
+		DEVCAP_VAL_SCRATCHPAD_SIZE);
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_INT_STAT_SIZE,
+		DEVCAP_VAL_INT_STAT_SIZE);
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_RESERVED,
+		DEVCAP_VAL_RESERVED);
+
+	/* Make bits 2,3 (initiator timeout) to 1,1
+	 * for register CBUS_LINK_CONTROL_2
+	 * REG_CBUS_LINK_CONTROL_2
+	 */
+	regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x0031);
+	regval = (regval | 0x0C);
+	/* REG_CBUS_LINK_CONTROL_2 */
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0031, regval);
+	 /* REG_MSC_TIMEOUT_LIMIT */
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0022, 0x0F);
+	/* REG_CBUS_LINK_CONTROL_1 */
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0030, 0x01);
+	/* disallow vendor specific commands */
+	mhl_i2c_reg_modify(TX_PAGE_CBUS, 0x002E, BIT4, BIT4);
+}
+
+/*
+ * Configure the initial reg settings
+ */
+static void mhl_init_reg_settings(void)
+{
+
+	/*
+	 * ============================================
+	 * POWER UP
+	 * ============================================
+	 */
+
+	/* Power up 1.2V core */
+	mhl_i2c_reg_write(TX_PAGE_L1, 0x003D, 0x3F);
+	/* Enable Tx PLL Clock */
+	mhl_i2c_reg_write(TX_PAGE_2, 0x0011, 0x01);
+	/* Enable Tx Clock Path and Equalizer */
+	mhl_i2c_reg_write(TX_PAGE_2, 0x0012, 0x11);
+	/* Tx Source Termination ON */
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0030, 0x10);
+	/* Enable 1X MHL Clock output */
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0035, 0xAC);
+	/* Tx Differential Driver Config */
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0031, 0x3C);
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0033, 0xD9);
+	/* PLL Bandwidth Control */
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0037, 0x02);
+	/*
+	 * ============================================
+	 * Analog PLL Control
+	 * ============================================
+	 */
+	/* Enable Rx PLL clock */
+	mhl_i2c_reg_write(TX_PAGE_L0, 0x0080, 0x00);
+	mhl_i2c_reg_write(TX_PAGE_L0, 0x00F8, 0x0C);
+	mhl_i2c_reg_write(TX_PAGE_L0, 0x0085, 0x02);
+	mhl_i2c_reg_write(TX_PAGE_2, 0x0000, 0x00);
+	mhl_i2c_reg_write(TX_PAGE_2, 0x0013, 0x60);
+	/* PLL Cal ref sel */
+	mhl_i2c_reg_write(TX_PAGE_2, 0x0017, 0x03);
+	/* VCO Cal */
+	mhl_i2c_reg_write(TX_PAGE_2, 0x001A, 0x20);
+	/* Auto EQ */
+	mhl_i2c_reg_write(TX_PAGE_2, 0x0022, 0xE0);
+	mhl_i2c_reg_write(TX_PAGE_2, 0x0023, 0xC0);
+	mhl_i2c_reg_write(TX_PAGE_2, 0x0024, 0xA0);
+	mhl_i2c_reg_write(TX_PAGE_2, 0x0025, 0x80);
+	mhl_i2c_reg_write(TX_PAGE_2, 0x0026, 0x60);
+	mhl_i2c_reg_write(TX_PAGE_2, 0x0027, 0x40);
+	mhl_i2c_reg_write(TX_PAGE_2, 0x0028, 0x20);
+	mhl_i2c_reg_write(TX_PAGE_2, 0x0029, 0x00);
+	/* Rx PLL Bandwidth 4MHz */
+	mhl_i2c_reg_write(TX_PAGE_2, 0x0031, 0x0A);
+	/* Rx PLL Bandwidth value from I2C */
+	mhl_i2c_reg_write(TX_PAGE_2, 0x0045, 0x06);
+	mhl_i2c_reg_write(TX_PAGE_2, 0x004B, 0x06);
+	/* Manual zone control */
+	mhl_i2c_reg_write(TX_PAGE_2, 0x004C, 0xE0);
+	/* PLL Mode value */
+	mhl_i2c_reg_write(TX_PAGE_2, 0x004D, 0x00);
+	mhl_i2c_reg_write(TX_PAGE_L0, 0x0008, 0x35);
+	/*
+	 * Discovery Control and Status regs
+	 * Setting De-glitch time to 50 ms (default)
+	 * Switch Control Disabled
+	 */
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0011, 0xAD);
+	/* 1.8V CBUS VTH */
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0014, 0x55);
+	/* RGND and single Discovery attempt */
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0015, 0x11);
+	/* Ignore VBUS */
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0017, 0x82);
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0018, 0x24);
+	/* Pull-up resistance off for IDLE state */
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0013, 0x84);
+	/* Enable CBUS Discovery */
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0010, 0x27);
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0016, 0x20);
+	/* MHL CBUS Discovery - immediate comm.  */
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0012, 0x86);
+	/* Do not force HPD to 0 during wake-up from D3 */
+	if (mhl_msm_state->cur_state != POWER_STATE_D3) {
+		mhl_i2c_reg_modify(TX_PAGE_3, 0x0020,
+			       BIT5 | BIT4, BIT4);
+	}
+	/* Enable Auto Soft RESET */
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0000, 0x084);
+	/* HDMI Transcode mode enable */
+	mhl_i2c_reg_write(TX_PAGE_L0, 0x000D, 0x1C);
+
+	cbus_reset();
+	init_cbus_regs();
+}
+
+static int mhl_chip_init(void)
+{
+	/* Read the chip rev ID */
+	mhl_msm_state->chip_rev_id = mhl_i2c_reg_read(TX_PAGE_L0, 0x04);
+	pr_debug("MHL: chip rev ID read=[%x]\n", mhl_msm_state->chip_rev_id);
+
+	/* Reset the TX chip */
+	mhl_msm_state->mhl_data->reset_pin(0);
+	msleep(20);
+	mhl_msm_state->mhl_data->reset_pin(1);
+	/* MHL spec requires a 100 ms wait here.  */
+	msleep(100);
+
+	mhl_init_reg_settings();
+
+	/*
+	 * Power down the chip to the
+	 * D3 - a low power standby mode
+	 * cable impedance measurement logic is operational
+	 */
+	switch_mode(POWER_STATE_D3);
+	return 0;
+}
+
+/*
+ * I2C probe
+ */
+static int mhl_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	int ret;
+	mhl_msm_state->mhl_data = kzalloc(sizeof(struct msm_mhl_platform_data),
+		GFP_KERNEL);
+	if (!(mhl_msm_state->mhl_data)) {
+		ret = -ENOMEM;
+		goto probe_exit;
+	}
+	pr_debug("Inside probe\n");
+	mhl_msm_state->i2c_client = client;
+
+	spin_lock_init(&mhl_state_lock);
+
+	i2c_set_clientdata(client, mhl_msm_state);
+	mhl_msm_state->mhl_data = client->dev.platform_data;
+
+	/* Init GPIO stuff here */
+	ret = mhl_msm_state->mhl_data->gpio_setup(1);
+	if (ret == -1) {
+		pr_err("MHL: mhl_gpio_init has failed\n");
+		ret = -ENODEV;
+		goto probe_exit;
+	}
+	return 0;
+
+probe_exit:
+	if (mhl_msm_state->mhl_data) {
+		/* free the gpios */
+		mhl_msm_state->mhl_data->gpio_setup(0);
+		kfree(mhl_msm_state->mhl_data);
+		mhl_msm_state->mhl_data = NULL;
+	}
+	return ret;
+}
+
+static int mhl_i2c_remove(struct i2c_client *client)
+{
+	pr_debug("inside i2c remove\n");
+	mhl_msm_state->mhl_data->gpio_setup(0);
+	kfree(mhl_msm_state->mhl_data);
+	return 0;
+}
+
+static int __init mhl_msm_init(void)
+{
+	int32_t     ret;
+
+	mhl_msm_state = kzalloc(sizeof(struct mhl_msm_state_t), GFP_KERNEL);
+	if (!mhl_msm_state) {
+		pr_err("mhl_msm_init FAILED: out of memory\n");
+		ret = -ENOMEM;
+		goto init_exit;
+	}
+
+	mhl_msm_state->i2c_client = NULL;
+	ret = i2c_add_driver(&mhl_sii_i2c_driver);
+	if (ret) {
+		pr_err("MHL: I2C driver add failed: %d\n", ret);
+		ret = -ENODEV;
+		goto init_exit;
+	} else {
+		if (mhl_msm_state->i2c_client == NULL) {
+			pr_err("JSR: I2C driver add failed\n");
+			ret = -ENODEV;
+			goto init_exit;
+		}
+		pr_debug("MHL: I2C driver added\n");
+	}
+
+	/* Request IRQ stuff here */
+	pr_debug("MHL: mhl_msm_state->mhl_data->irq=[%d]\n",
+		mhl_msm_state->mhl_data->irq);
+	ret = request_threaded_irq(mhl_msm_state->mhl_data->irq, NULL,
+				   &mhl_tx_isr,
+				 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+				 "mhl_tx_isr", mhl_msm_state);
+	if (ret != 0) {
+		pr_err("request_threaded_irq failed, status: %d\n",
+			ret);
+		ret = -EACCES; /* Error code???? */
+		goto init_exit;
+	}
+
+	mhl_msm_state->cur_state = POWER_STATE_D0_MHL;
+
+	/* MHL SII 8334 chip specific init */
+	mhl_chip_init();
+	return 0;
+
+init_exit:
+	pr_err("Exiting from the init with err\n");
+	i2c_del_driver(&mhl_sii_i2c_driver);
+	if (!mhl_msm_state) {
+		kfree(mhl_msm_state);
+		mhl_msm_state = NULL;
+	 }
+	 return ret;
+}
+
+static void switch_mode(enum mhl_st_type to_mode)
+{
+	unsigned long flags;
+
+	switch (to_mode) {
+	case POWER_STATE_D0_NO_MHL:
+		break;
+	case POWER_STATE_D0_MHL:
+		mhl_init_reg_settings();
+
+		/* REG_DISC_CTRL1 */
+		mhl_i2c_reg_modify(TX_PAGE_3, 0x0010, BIT1, 0);
+
+		/*
+		 * TPI_DEVICE_POWER_STATE_CTRL_REG
+		 * TX_POWER_STATE_MASK = BIT1 | BIT0
+		 */
+		mhl_i2c_reg_modify(TX_PAGE_TPI, 0x001E, BIT1 | BIT0, 0x00);
+		break;
+	case POWER_STATE_D3:
+		if (mhl_msm_state->cur_state != POWER_STATE_D3) {
+			/* Force HPD to 0 when not in MHL mode.  */
+			mhl_i2c_reg_modify(TX_PAGE_3, 0x0020,
+				BIT5 | BIT4, BIT4);
+
+			/*
+			 * Change TMDS termination to high impedance
+			 * on disconnection.
+			 */
+			mhl_i2c_reg_write(TX_PAGE_3, 0x0030, 0xD0);
+			mhl_i2c_reg_modify(TX_PAGE_L1, 0x003D,
+				BIT1 | BIT0, BIT0);
+			spin_lock_irqsave(&mhl_state_lock, flags);
+			mhl_msm_state->cur_state = POWER_STATE_D3;
+			spin_unlock_irqrestore(&mhl_state_lock, flags);
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static void mhl_drive_hpd(uint8_t to_state)
+{
+	pr_debug("%s: To state=[0x%x]\n", __func__, to_state);
+	if (to_state == HPD_UP) {
+		/*
+		 * Drive HPD to UP state
+		 *
+		 * The below two reg configs combined
+		 * enable TMDS output.
+		 */
+
+		/* Enable TMDS on TMDS_CCTRL */
+		mhl_i2c_reg_modify(TX_PAGE_L0, 0x0080, BIT4, BIT4);
+
+		/*
+		 * Set HPD_OUT_OVR_EN = HPD State
+		 * EDID read and Un-force HPD (from low)
+		 * propogate to src let HPD float by clearing
+		 * HPD OUT OVRRD EN
+		 */
+		mhl_i2c_reg_modify(TX_PAGE_3, 0x0020, BIT4, 0x00);
+	} else {
+		/*
+		 * Drive HPD to DOWN state
+		 * Disable TMDS Output on REG_TMDS_CCTRL
+		 * Enable/Disable TMDS output (MHL TMDS output only)
+		 */
+		mhl_i2c_reg_modify(TX_PAGE_L0, 0x0080, BIT4, 0x00);
+	}
+	return;
+}
+
+static void mhl_msm_connection(void)
+{
+	uint8_t val;
+	unsigned long flags;
+
+	pr_err("%s: cur state = [0x%x]\n", __func__, mhl_msm_state->cur_state);
+
+	if (mhl_msm_state->cur_state == POWER_STATE_D0_MHL) {
+		/* Already in D0 - MHL power state */
+		return;
+	}
+	spin_lock_irqsave(&mhl_state_lock, flags);
+	mhl_msm_state->cur_state = POWER_STATE_D0_MHL;
+	spin_unlock_irqrestore(&mhl_state_lock, flags);
+
+	mhl_i2c_reg_write(TX_PAGE_3, 0x30, 0x10);
+
+	mhl_i2c_reg_write(TX_PAGE_CBUS, 0x07, 0xF2);
+
+	/*
+	 * Keep the discovery enabled. Need RGND interrupt
+	 * Possibly chip disables discovery after MHL_EST??
+	 * Need to re-enable here
+	 */
+	val = mhl_i2c_reg_read(TX_PAGE_3, 0x10);
+	mhl_i2c_reg_write(TX_PAGE_3, 0x10, val | BIT(0));
+
+	return;
+}
+
+static void mhl_msm_disconnection(void)
+{
+	uint8_t reg;
+
+	/* Clear interrupts - REG INTR4 */
+	reg = mhl_i2c_reg_read(TX_PAGE_3, 0x0021);
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0021, reg);
+	/*
+	 * MHL TX CTL1
+	 * Disabling Tx termination
+	 */
+	mhl_i2c_reg_write(TX_PAGE_3, 0x30, 0xD0);
+	/*
+	 * MSC REQUESTOR ABORT REASON
+	 * Clear CBUS_HPD status
+	 */
+	mhl_i2c_reg_modify(TX_PAGE_CBUS, 0x000D, BIT6, 0x00);
+	/* Change HPD line to drive it low */
+	mhl_drive_hpd(HPD_DOWN);
+	/* switch power state to D3 */
+	switch_mode(POWER_STATE_D3);
+	return;
+}
+
+/*
+ * If hardware detected a change in impedence and raised an INTR
+ * We check the range of this impedence to infer if the connected
+ * device is MHL or USB and take appropriate actions.
+ */
+static void mhl_msm_read_rgnd_int(void)
+{
+	uint8_t rgnd_imp;
+
+	/*
+	 * DISC STATUS REG 2
+	 * 1:0 RGND
+	 * 00  - open (USB)
+	 * 01  - 2 kOHM (USB)
+	 * 10  - 1 kOHM ***(MHL)**** It's range 800 - 1200 OHM from MHL spec
+	 * 11  - short (USB)
+	 */
+	rgnd_imp = mhl_i2c_reg_read(TX_PAGE_3, 0x001C);
+	pr_debug("Imp Range read = %02X\n", (int)rgnd_imp);
+
+
+	if (0x02 == rgnd_imp) {
+		pr_debug("MHL: MHL DEVICE!!!\n");
+		/*
+		 * Handling the MHL event in driver
+		 */
+		mhl_i2c_reg_modify(TX_PAGE_3, 0x0018, BIT0, BIT0);
+	} else {
+		pr_debug("MHL: NON-MHL DEVICE!!!\n");
+		mhl_i2c_reg_modify(TX_PAGE_3, 0x0018, BIT3, BIT3);
+	}
+}
+
+static void force_usb_switch_open(void)
+{
+	/*DISABLE_DISCOVERY*/
+	mhl_i2c_reg_modify(TX_PAGE_3, 0x0010, BIT0, 0);
+	/* Force USB ID switch to open*/
+	mhl_i2c_reg_modify(TX_PAGE_3, 0x0015, BIT6, BIT6);
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0012, 0x86);
+	/* Force HPD to 0 when not in Mobile HD mode. */
+	mhl_i2c_reg_modify(TX_PAGE_3, 0x0020, BIT5 | BIT4, BIT4);
+}
+
+static void release_usb_switch_open(void)
+{
+	msleep(50);
+	mhl_i2c_reg_modify(TX_PAGE_3, 0x0015, BIT6, 0x00);
+	mhl_i2c_reg_modify(TX_PAGE_3, 0x0010, BIT0, BIT0);
+}
+
+static void int_4_isr(void)
+{
+	uint8_t status;
+
+	/* INTR_STATUS4 */
+	status = mhl_i2c_reg_read(TX_PAGE_3, 0x0021);
+
+	/*
+	 * When I2C is inoperational (D3) and
+	 * a previous interrupt brought us here,
+	 * do nothing.
+	 */
+	pr_debug("MHL: MRR Interrupt status is = %02X\n", (int) status);
+	if (0xFF != status) {
+		if ((status & BIT0) && (mhl_msm_state->chip_rev_id < 1)) {
+			uint8_t tmds_cstat;
+			uint8_t mhl_fifo_status;
+
+			/* TMDS CSTAT */
+			tmds_cstat = mhl_i2c_reg_read(TX_PAGE_3, 0x0040);
+
+			pr_debug("TMDS CSTAT: 0x%02x\n", tmds_cstat);
+
+			if (tmds_cstat & 0x02) {
+				mhl_fifo_status = mhl_i2c_reg_read(TX_PAGE_3,
+					0x0023);
+				pr_debug("MHL FIFO status: 0x%02x\n",
+					mhl_fifo_status);
+				if (mhl_fifo_status & 0x0C) {
+					mhl_i2c_reg_write(TX_PAGE_3, 0x0023,
+						0x0C);
+
+					pr_debug("Apply MHL FIFO Reset\n");
+					mhl_i2c_reg_write(TX_PAGE_3, 0x0000,
+						0x94);
+					mhl_i2c_reg_write(TX_PAGE_3, 0x0000,
+						0x84);
+				}
+			}
+		}
+
+		if (status & BIT1)
+			pr_err("MHL: INT4 BIT1 is set\n");
+
+		/* MHL_EST interrupt */
+		if (status & BIT2) {
+			pr_err("MHL: Calling mhl_msm_connection() from ISR\n");
+			mhl_msm_connection();
+			pr_err("MHL Connect  Drv: INT4 Status = %02X\n",
+				(int) status);
+		} else if (status & BIT3) {
+			pr_err("MHL: uUSB-A type device detected.\n");
+			mhl_i2c_reg_write(TX_PAGE_3, 0x001C, 0x80);
+			switch_mode(POWER_STATE_D3);
+		}
+
+		if (status & BIT5) {
+			mhl_msm_disconnection();
+			pr_err("MHL Disconnect Drv: INT4 Status = %02X\n",
+				(int)status);
+		}
+
+		if ((mhl_msm_state->cur_state != POWER_STATE_D0_MHL) &&\
+			(status & BIT6)) {
+			/* RGND READY Intr */
+			switch_mode(POWER_STATE_D0_MHL);
+			mhl_msm_read_rgnd_int();
+		}
+
+		/* Can't succeed at these in D3 */
+		if (mhl_msm_state->cur_state != POWER_STATE_D3) {
+			/* CBUS Lockout interrupt? */
+			/*
+			 * Hardware detection mechanism figures that
+			 * CBUS line is latched and raises this intr
+			 * where we force usb switch open and release
+			 */
+			if (status & BIT4) {
+				force_usb_switch_open();
+				release_usb_switch_open();
+			}
+		}
+	}
+	pr_debug("MHL END  Drv: INT4 Status = %02X\n", (int) status);
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0021, status);
+
+	return;
+}
+
+static void int_5_isr(void)
+{
+	uint8_t intr_5_stat;
+
+	/*
+	 * Clear INT 5 ??
+	 * Probably need to revisit this later
+	 * INTR5 is related to FIFO underflow/overflow reset
+	 * which is handled in 8334 by auto FIFO reset
+	 */
+	intr_5_stat = mhl_i2c_reg_read(TX_PAGE_3, 0x0023);
+	mhl_i2c_reg_write(TX_PAGE_3, 0x0023, intr_5_stat);
+}
+
+
+static void int_1_isr(void)
+{
+	/* This ISR mainly handles the HPD status changes */
+	uint8_t intr_1_stat;
+	uint8_t cbus_stat;
+
+	/* INTR STATUS 1 */
+	intr_1_stat = mhl_i2c_reg_read(TX_PAGE_L0, 0x0071);
+
+	if (intr_1_stat) {
+		/* Clear interrupts */
+		mhl_i2c_reg_write(TX_PAGE_L0, 0x0071, intr_1_stat);
+		if (BIT6 & intr_1_stat) {
+			/*
+			 * HPD status change event is pending
+			 * Read CBUS HPD status for this info
+			 */
+
+			/* MSC REQ ABRT REASON */
+			cbus_stat = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x0D);
+			if (BIT6 & cbus_stat)
+				mhl_drive_hpd(HPD_UP);
+		}
+	}
+	return;
+}
+
+/*
+ * RCP, RAP messages - mandatory for compliance
+ *
+ */
+static void mhl_cbus_isr(void)
+{
+	uint8_t regval;
+	int req_done = FALSE;
+	uint8_t sub_cmd;
+	uint8_t cmd_data;
+	int msc_msg_recved = FALSE;
+	int rc = -1;
+
+	regval  = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x08);
+	if (regval == 0xff)
+		return;
+
+	/* clear all interrupts that were raised even if we did not process */
+	if (regval)
+		mhl_i2c_reg_write(TX_PAGE_CBUS, 0x08, regval);
+
+	pr_err("%s: CBUS_INT = %02x\n", __func__, regval);
+
+	/* MSC_MSG (RCP/RAP) */
+	if (regval & BIT(3)) {
+		sub_cmd = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x18);
+		cmd_data = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x19);
+		msc_msg_recved = TRUE;
+	}
+
+	/* MSC_REQ_DONE */
+	if (regval & BIT(4))
+		req_done = TRUE;
+
+	/* Now look for interrupts on CBUS_MSC_INT2 */
+	regval  = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x1E);
+
+	/* clear all interrupts that were raised */
+	/* even if we did not process */
+	if (regval)
+		mhl_i2c_reg_write(TX_PAGE_CBUS, 0x1E, regval);
+
+	pr_err("%s: CBUS_MSC_INT2 = %02x\n", __func__, regval);
+
+	/* received SET_INT */
+	if (regval & BIT(2)) {
+		uint8_t intr;
+		intr = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xA0);
+		pr_debug("%s: MHL_INT_0 = %02x\n", __func__, intr);
+		intr = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xA1);
+		pr_debug("%s: MHL_INT_1 = %02x\n", __func__, intr);
+		mhl_i2c_reg_write(TX_PAGE_CBUS, 0xA0, 0xFF);
+		mhl_i2c_reg_write(TX_PAGE_CBUS, 0xA1, 0xFF);
+		mhl_i2c_reg_write(TX_PAGE_CBUS, 0xA2, 0xFF);
+		mhl_i2c_reg_write(TX_PAGE_CBUS, 0xA3, 0xFF);
+	}
+
+	/* received WRITE_STAT */
+	if (regval & BIT(3)) {
+		uint8_t stat;
+		stat = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xB0);
+		pr_err("%s: MHL_STATUS_0 = %02x\n", __func__, stat);
+		stat = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xB1);
+		pr_err("%s: MHL_STATUS_1 = %02x\n", __func__, stat);
+
+		mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB0, 0xFF);
+		mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB1, 0xFF);
+		mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB2, 0xFF);
+		mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB3, 0xFF);
+	}
+
+	/* received MSC_MSG */
+	if (msc_msg_recved) {
+		/*mhl msc recv msc msg*/
+		if (rc)
+			pr_err("MHL: mhl msc recv msc msg failed(%d)!\n", rc);
+	}
+
+	return;
+}
+
+static irqreturn_t mhl_tx_isr(int irq, void *dev_id)
+{
+	/*
+	 * Check discovery interrupt
+	 * if not yet connected
+	 */
+	pr_debug("MHL: Current POWER state is [0x%x]\n",
+		mhl_msm_state->cur_state);
+	/*
+	 * Check RGND, MHL_EST, CBUS_LOCKOUT, SCDT
+	 * interrupts. In D3, we get only RGND
+	 */
+	int_4_isr();
+
+	pr_debug("MHL: Current POWER state is [0x%x]\n",
+		mhl_msm_state->cur_state);
+	if (mhl_msm_state->cur_state == POWER_STATE_D0_MHL) {
+		/*
+		 * If int_4_isr() didn't move the tx to D3
+		 * on disconnect, continue to check other
+		 * interrupt sources.
+		 */
+		int_5_isr();
+
+		/*
+		 * Check for any peer messages for DCAP_CHG etc
+		 * Dispatch to have the CBUS module working only
+		 * once connected.
+		 */
+		mhl_cbus_isr();
+		int_1_isr();
+	}
+	return IRQ_HANDLED;
+}
+
+static void __exit mhl_msm_exit(void)
+{
+	pr_warn("MHL: Exiting, Bye\n");
+	/*
+	 * Delete driver if i2c client structure is NULL
+	 */
+	i2c_del_driver(&mhl_sii_i2c_driver);
+	if (!mhl_msm_state) {
+		kfree(mhl_msm_state);
+		mhl_msm_state = NULL;
+	 }
+}
+
+module_init(mhl_msm_init);
+module_exit(mhl_msm_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MHL SII 8334 TX driver");
diff --git a/drivers/video/msm/mhl/mhl_8334.h b/drivers/video/msm/mhl/mhl_8334.h
new file mode 100644
index 0000000..c1d9030
--- /dev/null
+++ b/drivers/video/msm/mhl/mhl_8334.h
@@ -0,0 +1,74 @@
+/* Copyright (c) 2012, 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 __MHL_MSM_H__
+#define __MHL_MSM_H__
+
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <mach/board.h>
+
+#include "mhl_devcap.h"
+#include "mhl_defs.h"
+
+#define GPIO_MHL_RESET       15
+#define GPIO_MHL_INT         4
+
+#define MHL_DEVICE_NAME "sii8334"
+#define MHL_DRIVER_NAME "sii8334"
+
+#define HPD_UP               1
+#define HPD_DOWN             0
+
+struct mhl_msm_state_t {
+	struct i2c_client *i2c_client;
+	struct i2c_driver *i2c_driver;
+	uint8_t      cur_state;
+	uint8_t chip_rev_id;
+	struct msm_mhl_platform_data *mhl_data;
+};
+
+enum {
+	TX_PAGE_TPI          = 0x00,
+	TX_PAGE_L0           = 0x01,
+	TX_PAGE_L1           = 0x02,
+	TX_PAGE_2            = 0x03,
+	TX_PAGE_3            = 0x04,
+	TX_PAGE_CBUS         = 0x05,
+	TX_PAGE_DDC_EDID     = 0x06,
+	TX_PAGE_DDC_SEGM     = 0x07,
+};
+
+enum mhl_st_type {
+	POWER_STATE_D0_NO_MHL = 0,
+	POWER_STATE_D0_MHL    = 2,
+	POWER_STATE_D3        = 3,
+};
+
+enum {
+	DEV_PAGE_TPI_0      = (0x72),
+	DEV_PAGE_TX_L0_0    = (0x72),
+	DEV_PAGE_TPI_1      = (0x76),
+	DEV_PAGE_TX_L0_1    = (0x76),
+	DEV_PAGE_TX_L1_0    = (0x7A),
+	DEV_PAGE_TX_L1_1    = (0x7E),
+	DEV_PAGE_TX_2_0     = (0x92),
+	DEV_PAGE_TX_2_1     = (0x96),
+	DEV_PAGE_TX_3_0	    = (0x9A),
+	DEV_PAGE_TX_3_1	    = (0x9E),
+	DEV_PAGE_CBUS       = (0xC8),
+	DEV_PAGE_DDC_EDID   = (0xA0),
+	DEV_PAGE_DDC_SEGM   = (0x60),
+};
+
+#endif /* __MHL_MSM_H__ */
diff --git a/drivers/video/msm/mhl/mhl_defs.h b/drivers/video/msm/mhl/mhl_defs.h
new file mode 100644
index 0000000..094874e
--- /dev/null
+++ b/drivers/video/msm/mhl/mhl_defs.h
@@ -0,0 +1,222 @@
+/* Copyright (c) 2012, 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 __MHL_SPEC_DEFS_H__
+#define __MHL_SPEC_DEFS_H__
+
+enum DevCapOffset_e {
+	DEVCAP_OFFSET_DEV_STATE         = 0x00,
+	DEVCAP_OFFSET_MHL_VERSION	= 0x01,
+	DEVCAP_OFFSET_DEV_CAT           = 0x02,
+	DEVCAP_OFFSET_ADOPTER_ID_H      = 0x03,
+	DEVCAP_OFFSET_ADOPTER_ID_L      = 0x04,
+	DEVCAP_OFFSET_VID_LINK_MODE     = 0x05,
+	DEVCAP_OFFSET_AUD_LINK_MODE     = 0x06,
+	DEVCAP_OFFSET_VIDEO_TYPE        = 0x07,
+	DEVCAP_OFFSET_LOG_DEV_MAP       = 0x08,
+	DEVCAP_OFFSET_BANDWIDTH         = 0x09,
+	DEVCAP_OFFSET_FEATURE_FLAG      = 0x0A,
+	DEVCAP_OFFSET_DEVICE_ID_H       = 0x0B,
+	DEVCAP_OFFSET_DEVICE_ID_L       = 0x0C,
+	DEVCAP_OFFSET_SCRATCHPAD_SIZE   = 0x0D,
+	DEVCAP_OFFSET_INT_STAT_SIZE     = 0x0E,
+	DEVCAP_OFFSET_RESERVED          = 0x0F,
+	/* this one must be last */
+	DEVCAP_SIZE
+};
+
+#ifndef __MHL_MSM_8334_REGS_H__
+#define __MHL_MSM_8334_REGS_H__
+
+#define BIT0                    0x01
+#define BIT1                    0x02
+#define BIT2                    0x04
+#define BIT3                    0x08
+#define BIT4                    0x10
+#define BIT5                    0x20
+#define BIT6                    0x40
+#define BIT7                    0x80
+
+#define LOW                     0
+#define HIGH                    1
+
+#define MAX_PAGES               8
+#endif
+
+
+/* Version that this chip supports*/
+/* bits 4..7 */
+#define	MHL_VER_MAJOR           (0x01 << 4)
+/* bits 0..3 */
+#define	MHL_VER_MINOR		0x01
+#define MHL_VERSION		(MHL_VER_MAJOR | MHL_VER_MINOR)
+
+/*Device Category*/
+#define	MHL_DEV_CATEGORY_OFFSET		DEVCAP_OFFSET_DEV_CAT
+#define	MHL_DEV_CATEGORY_POW_BIT	(BIT4)
+
+#define	MHL_DEV_CAT_SOURCE		0x02
+
+/*Video Link Mode*/
+#define	MHL_DEV_VID_LINK_SUPPRGB444		0x01
+#define	MHL_DEV_VID_LINK_SUPPYCBCR444		0x02
+#define	MHL_DEV_VID_LINK_SUPPYCBCR422		0x04
+#define	MHL_DEV_VID_LINK_SUPP_PPIXEL		0x08
+#define	MHL_DEV_VID_LINK_SUPP_ISLANDS		0x10
+
+/*Audio Link Mode Support*/
+#define	MHL_DEV_AUD_LINK_2CH				0x01
+#define	MHL_DEV_AUD_LINK_8CH				0x02
+
+
+/*Feature Flag in the devcap*/
+#define	MHL_DEV_FEATURE_FLAG_OFFSET		DEVCAP_OFFSET_FEATURE_FLAG
+/* Dongles have freedom to not support RCP */
+#define	MHL_FEATURE_RCP_SUPPORT				BIT0
+/* Dongles have freedom to not support RAP */
+#define	MHL_FEATURE_RAP_SUPPORT				BIT1
+/* Dongles have freedom to not support SCRATCHPAD */
+#define	MHL_FEATURE_SP_SUPPORT				BIT2
+
+/*Logical Dev Map*/
+#define	MHL_DEV_LD_DISPLAY					(0x01 << 0)
+#define	MHL_DEV_LD_VIDEO					(0x01 << 1)
+#define	MHL_DEV_LD_AUDIO					(0x01 << 2)
+#define	MHL_DEV_LD_MEDIA					(0x01 << 3)
+#define	MHL_DEV_LD_TUNER					(0x01 << 4)
+#define	MHL_DEV_LD_RECORD					(0x01 << 5)
+#define	MHL_DEV_LD_SPEAKER					(0x01 << 6)
+#define	MHL_DEV_LD_GUI						(0x01 << 7)
+
+/*Bandwidth*/
+/* 225 MHz */
+#define	MHL_BANDWIDTH_LIMIT					22
+
+
+#define MHL_STATUS_REG_CONNECTED_RDY        0x30
+#define MHL_STATUS_REG_LINK_MODE            0x31
+
+#define	MHL_STATUS_DCAP_RDY					BIT0
+
+#define MHL_STATUS_CLK_MODE_MASK            0x07
+#define MHL_STATUS_CLK_MODE_PACKED_PIXEL    0x02
+#define MHL_STATUS_CLK_MODE_NORMAL          0x03
+#define MHL_STATUS_PATH_EN_MASK             0x08
+#define MHL_STATUS_PATH_ENABLED             0x08
+#define MHL_STATUS_PATH_DISABLED            0x00
+#define MHL_STATUS_MUTED_MASK               0x10
+
+#define MHL_RCHANGE_INT                     0x20
+#define MHL_DCHANGE_INT                     0x21
+
+#define	MHL_INT_DCAP_CHG					BIT0
+#define MHL_INT_DSCR_CHG                    BIT1
+#define MHL_INT_REQ_WRT                     BIT2
+#define MHL_INT_GRT_WRT                     BIT3
+
+/* On INTR_1 the EDID_CHG is located at BIT 0*/
+#define	MHL_INT_EDID_CHG					BIT1
+
+/* This contains one nibble each - max offset */
+#define		MHL_INT_AND_STATUS_SIZE			0x33
+#define		MHL_SCRATCHPAD_SIZE			16
+/* manually define highest number */
+#define		MHL_MAX_BUFFER_SIZE			MHL_SCRATCHPAD_SIZE
+
+
+
+enum {
+	/* RCP sub-command  */
+	MHL_MSC_MSG_RCP             = 0x10,
+	/* RCP Acknowledge sub-command  */
+	MHL_MSC_MSG_RCPK            = 0x11,
+	/* RCP Error sub-command  */
+	MHL_MSC_MSG_RCPE            = 0x12,
+	/* Mode Change Warning sub-command  */
+	MHL_MSC_MSG_RAP             = 0x20,
+	/* MCW Acknowledge sub-command  */
+	MHL_MSC_MSG_RAPK            = 0x21,
+};
+
+#define	RCPE_NO_ERROR				0x00
+#define	RCPE_INEEFECTIVE_KEY_CODE	0x01
+#define	RCPE_BUSY					0x02
+/* MHL spec related defines*/
+enum {
+	/* Command or Data byte acknowledge */
+	MHL_ACK						= 0x33,
+	/* Command or Data byte not acknowledge */
+	MHL_NACK					= 0x34,
+	/* Transaction abort */
+	MHL_ABORT					= 0x35,
+	/* 0xE0 - Write one status register strip top bit */
+	MHL_WRITE_STAT				= 0x60 | 0x80,
+	/* Write one interrupt register */
+	MHL_SET_INT					= 0x60,
+	/* Read one register */
+	MHL_READ_DEVCAP				= 0x61,
+	/* Read CBUS revision level from follower */
+	MHL_GET_STATE				= 0x62,
+	/* Read vendor ID value from follower. */
+	MHL_GET_VENDOR_ID			= 0x63,
+	/* Set Hot Plug Detect in follower */
+	MHL_SET_HPD					= 0x64,
+	/* Clear Hot Plug Detect in follower */
+	MHL_CLR_HPD					= 0x65,
+	/* Set Capture ID for downstream device. */
+	MHL_SET_CAP_ID				= 0x66,
+	/* Get Capture ID from downstream device. */
+	MHL_GET_CAP_ID				= 0x67,
+	/* VS command to send RCP sub-commands */
+	MHL_MSC_MSG					= 0x68,
+	/* Get Vendor-Specific command error code. */
+	MHL_GET_SC1_ERRORCODE		= 0x69,
+	/* Get DDC channel command error code. */
+	MHL_GET_DDC_ERRORCODE		= 0x6A,
+	/* Get MSC command error code. */
+	MHL_GET_MSC_ERRORCODE		= 0x6B,
+	/* Write 1-16 bytes to responder's scratchpad. */
+	MHL_WRITE_BURST				= 0x6C,
+	/* Get channel 3 command error code. */
+	MHL_GET_SC3_ERRORCODE		= 0x6D,
+};
+
+/* Turn content streaming ON. */
+#define	MHL_RAP_CONTENT_ON		0x10
+/* Turn content streaming OFF. */
+#define	MHL_RAP_CONTENT_OFF		0x11
+
+/*
+ *
+ * MHL Timings applicable to this driver.
+ *
+ */
+/* 100 - 1000 milliseconds. Per MHL 1.0 Specs */
+#define	T_SRC_VBUS_CBUS_TO_STABLE	(200)
+/* 20 milliseconds. Per MHL 1.0 Specs */
+#define	T_SRC_WAKE_PULSE_WIDTH_1	(20)
+/* 60 milliseconds. Per MHL 1.0 Specs */
+#define	T_SRC_WAKE_PULSE_WIDTH_2	(60)
+
+/* 100 - 1000 milliseconds. Per MHL 1.0 Specs */
+#define	T_SRC_WAKE_TO_DISCOVER		(500)
+
+#define T_SRC_VBUS_CBUS_T0_STABLE	(500)
+
+/* Allow RSEN to stay low this much before reacting.*/
+#define	T_SRC_RSEN_DEGLITCH			(100)
+
+/* Wait this much after connection before reacting to RSEN (300-500ms)*/
+/* Per specs between 300 to 500 ms*/
+#define	T_SRC_RXSENSE_CHK			(400)
+
+#endif /* __MHL_SPEC_DEFS_H__ */
diff --git a/drivers/video/msm/mhl/mhl_devcap.h b/drivers/video/msm/mhl/mhl_devcap.h
new file mode 100644
index 0000000..6d01daf
--- /dev/null
+++ b/drivers/video/msm/mhl/mhl_devcap.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2012, 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 __MHL_DEVCAP_H__
+#define __MHL_DEVCAP_H__
+
+#define SILICON_IMAGE_ADOPTER_ID 322
+#define TRANSCODER_DEVICE_ID 0x8334
+
+#define MHL_DEV_LD_AUDIO (0x01 << 2)
+#define MHL_DEV_LD_VIDEO (0x01 << 1)
+#define MHL_DEV_LD_MEDIA (0x01 << 3)
+#define MHL_DEV_LD_GUI (0x01 << 7)
+#define	MHL_LOGICAL_DEVICE_MAP		(MHL_DEV_LD_AUDIO |\
+	MHL_DEV_LD_VIDEO | MHL_DEV_LD_MEDIA | MHL_DEV_LD_GUI)
+
+#define DEVCAP_VAL_DEV_STATE       0
+#define DEVCAP_VAL_MHL_VERSION     MHL_VERSION
+#define DEVCAP_VAL_DEV_CAT         (MHL_DEV_CAT_SOURCE |\
+	MHL_DEV_CATEGORY_POW_BIT)
+#define DEVCAP_VAL_ADOPTER_ID_H    (uint8_t)(SILICON_IMAGE_ADOPTER_ID >>   8)
+#define DEVCAP_VAL_ADOPTER_ID_L    (uint8_t)(SILICON_IMAGE_ADOPTER_ID & 0xFF)
+#define DEVCAP_VAL_VID_LINK_MODE   MHL_DEV_VID_LINK_SUPPRGB444
+#define DEVCAP_VAL_AUD_LINK_MODE   MHL_DEV_AUD_LINK_2CH
+#define DEVCAP_VAL_VIDEO_TYPE      0
+#define DEVCAP_VAL_LOG_DEV_MAP     MHL_LOGICAL_DEVICE_MAP
+#define DEVCAP_VAL_BANDWIDTH       0
+#define DEVCAP_VAL_FEATURE_FLAG    (MHL_FEATURE_RCP_SUPPORT |\
+	MHL_FEATURE_RAP_SUPPORT | MHL_FEATURE_SP_SUPPORT)
+#define DEVCAP_VAL_DEVICE_ID_H     (uint8_t)(TRANSCODER_DEVICE_ID >>   8)
+#define DEVCAP_VAL_DEVICE_ID_L     (uint8_t)(TRANSCODER_DEVICE_ID & 0xFF)
+#define DEVCAP_VAL_SCRATCHPAD_SIZE MHL_SCRATCHPAD_SIZE
+#define DEVCAP_VAL_INT_STAT_SIZE   MHL_INT_AND_STATUS_SIZE
+#define DEVCAP_VAL_RESERVED        0
+
+#endif /* __MHL_DEVCAP_H__ */
diff --git a/drivers/video/msm/mhl/mhl_i2c_utils.c b/drivers/video/msm/mhl/mhl_i2c_utils.c
new file mode 100644
index 0000000..596af2e
--- /dev/null
+++ b/drivers/video/msm/mhl/mhl_i2c_utils.c
@@ -0,0 +1,107 @@
+/* Copyright (c) 2012, 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/i2c.h>
+
+#include "mhl_i2c_utils.h"
+#include "mhl_8334.h"
+
+#define DEBUG
+
+uint8_t slave_addrs[MAX_PAGES] = {
+	DEV_PAGE_TPI_0    ,
+	DEV_PAGE_TX_L0_0  ,
+	DEV_PAGE_TX_L1_0  ,
+	DEV_PAGE_TX_2_0   ,
+	DEV_PAGE_TX_3_0   ,
+	DEV_PAGE_CBUS     ,
+	DEV_PAGE_DDC_EDID ,
+	DEV_PAGE_DDC_SEGM ,
+};
+
+int mhl_i2c_reg_read(uint8_t slave_addr_index, uint8_t reg_offset)
+{
+	struct i2c_msg msgs[2];
+	uint8_t buffer = 0;
+	int ret = -1;
+
+	pr_debug("MRR: Reading from slave_addr_index=[%x] and offset=[%x]\n",
+		slave_addr_index, reg_offset);
+	pr_debug("MRR: Addr slave_addr_index=[%x]\n",
+		slave_addrs[slave_addr_index]);
+
+	/* Slave addr */
+	msgs[0].addr = slave_addrs[slave_addr_index] >> 1;
+	msgs[1].addr = slave_addrs[slave_addr_index] >> 1;
+
+	/* Write Command */
+	msgs[0].flags = 0;
+	msgs[1].flags = I2C_M_RD;
+
+	/* Register offset for the next transaction */
+	msgs[0].buf = &reg_offset;
+	msgs[1].buf = &buffer;
+
+	/* Offset is 1 Byte long */
+	msgs[0].len = 1;
+	msgs[1].len = 1;
+
+	ret = i2c_transfer(mhl_msm_state->i2c_client->adapter, msgs, 2);
+	if (ret < 1) {
+		pr_err("I2C READ FAILED=[%d]\n", ret);
+		return -EACCES;
+	}
+	pr_err("Buffer is [%x]\n", buffer);
+	return buffer;
+}
+
+
+int mhl_i2c_reg_write(uint8_t slave_addr_index, uint8_t reg_offset,
+	uint8_t value)
+{
+	return mhl_i2c_reg_write_cmds(slave_addr_index, reg_offset, &value, 1);
+}
+
+int mhl_i2c_reg_write_cmds(uint8_t slave_addr_index, uint8_t reg_offset,
+	uint8_t *value, uint16_t count)
+{
+	struct i2c_msg msgs[1];
+	uint8_t data[2];
+	int status = -EACCES;
+
+	msgs[0].addr = slave_addrs[slave_addr_index] >> 1;
+	msgs[0].flags = 0;
+	msgs[0].len = 2;
+	msgs[0].buf = data;
+	data[0] = reg_offset;
+	data[1] = *value;
+
+	status = i2c_transfer(mhl_msm_state->i2c_client->adapter, msgs, 1);
+	if (status < 1) {
+		pr_err("I2C WRITE FAILED=[%d]\n", status);
+		return -EACCES;
+	}
+
+	return status;
+}
+
+void mhl_i2c_reg_modify(uint8_t slave_addr_index, uint8_t reg_offset,
+	uint8_t mask, uint8_t val)
+{
+	uint8_t temp;
+
+	temp = mhl_i2c_reg_read(slave_addr_index, reg_offset);
+	temp &= (~mask);
+	temp |= (mask & val);
+	mhl_i2c_reg_write(slave_addr_index, reg_offset, temp);
+}
+
diff --git a/drivers/video/msm/mhl/mhl_i2c_utils.h b/drivers/video/msm/mhl/mhl_i2c_utils.h
new file mode 100644
index 0000000..76498d4
--- /dev/null
+++ b/drivers/video/msm/mhl/mhl_i2c_utils.h
@@ -0,0 +1,39 @@
+/* Copyright (c) 2012, 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 __MHL_I2C_UTILS_H__
+#define __MHL_I2C_UTILS_H__
+
+#include <linux/i2c.h>
+#include <linux/types.h>
+
+#include "mhl_defs.h"
+
+/*
+ * I2C command to the adapter to append
+ * the buffer from next msg to this one.
+ */
+#define I2C_M_APPND_NXT_WR          0x0002
+
+extern uint8_t slave_addrs[MAX_PAGES];
+extern struct mhl_msm_state_t *mhl_msm_state;
+
+int mhl_i2c_reg_read(uint8_t slave_addr_index, uint8_t reg_offset);
+int mhl_i2c_reg_write(uint8_t slave_addr_index, uint8_t reg_offset,
+	uint8_t value);
+int mhl_i2c_reg_write_cmds(uint8_t slave_addr_index, uint8_t reg_offset,
+	uint8_t *value, uint16_t count);
+void mhl_i2c_reg_modify(uint8_t slave_addr_index, uint8_t reg_offset,
+	uint8_t mask, uint8_t val);
+
+#endif /* __MHL_I2C_UTILS_H__ */
diff --git a/drivers/video/msm/mhl_api.h b/drivers/video/msm/mhl_api.h
index 627f802..a4364ea 100644
--- a/drivers/video/msm/mhl_api.h
+++ b/drivers/video/msm/mhl_api.h
@@ -14,7 +14,7 @@
 #ifndef __MHL_API_H__
 #define __MHL_API_H__
 
-#ifdef CONFIG_FB_MSM_HDMI_MHL
+#ifdef CONFIG_FB_MSM_HDMI_MHL_8334
 bool mhl_is_connected(void);
 #else
 static bool mhl_is_connected(void)
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 76653ec..c6b0440 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -3070,6 +3070,10 @@
 			break;
 		}
 		break;
+	case mdp_op_qseed_cfg:
+		ret = mdp4_qseed_cfg((struct mdp_qseed_cfg_data *)
+						&pp_ptr->data.qseed_cfg_data);
+		break;
 #endif
 	default:
 		pr_warn("Unsupported request to MDP_PP IOCTL.\n");
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
index b4161dd..a8ccebf 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
@@ -60,7 +60,7 @@
 #define DDL_ENC_MIN_DPB_BUFFERS           2
 #define DDL_ENC_MAX_DPB_BUFFERS           4
 
-#define DDL_FW_AUX_HOST_CMD_SPACE_SIZE         (DDL_KILO_BYTE(8))
+#define DDL_FW_AUX_HOST_CMD_SPACE_SIZE         (DDL_KILO_BYTE(4))
 #define DDL_FW_INST_GLOBAL_CONTEXT_SPACE_SIZE  (DDL_KILO_BYTE(800))
 #define DDL_FW_H264DEC_CONTEXT_SPACE_SIZE      (DDL_KILO_BYTE(800))
 #define DDL_FW_H264ENC_CONTEXT_SPACE_SIZE      (DDL_KILO_BYTE(20))
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
index b720800..62f0976 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -1000,7 +1000,8 @@
 			(decoder->frame_size.scan_lines ==
 			decoder->client_frame_size.scan_lines) &&
 			(decoder->frame_size.stride ==
-			decoder->client_frame_size.stride))
+			decoder->client_frame_size.stride) &&
+			decoder->progressive_only)
 				need_reconfig = false;
 	}
 	return need_reconfig;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
index 6aa7451..126698c 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
@@ -348,7 +348,7 @@
 
 void ddl_fw_release(void)
 {
-
+	res_trk_close_secure_session();
 }
 
 void ddl_set_core_start_time(const char *func_name, u32 index)
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index 90c98d7..e94a302 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -673,6 +673,15 @@
 	return 0;
 }
 
+int res_trk_check_for_sec_session(void)
+{
+	int rc;
+	mutex_lock(&resource_context.secure_lock);
+	rc = resource_context.secure_session;
+	mutex_unlock(&resource_context.secure_lock);
+	return rc;
+}
+
 int res_trk_get_mem_type(void)
 {
 	int mem_type = -1;
@@ -783,43 +792,37 @@
 	return 0;
 }
 
-int res_trk_check_for_sec_session()
-{
-	int rc;
-	mutex_lock(&resource_context.secure_lock);
-	rc = (resource_context.secure_session) ? -EBUSY : 0;
-	mutex_unlock(&resource_context.secure_lock);
-	return rc;
-}
-
 void res_trk_secure_unset(void)
 {
 	mutex_lock(&resource_context.secure_lock);
-	resource_context.secure_session = 0;
+	resource_context.secure_session--;
 	mutex_unlock(&resource_context.secure_lock);
 }
 
 void res_trk_secure_set(void)
 {
 	mutex_lock(&resource_context.secure_lock);
-	resource_context.secure_session = 1;
+	resource_context.secure_session++;
 	mutex_unlock(&resource_context.secure_lock);
 }
 
 int res_trk_open_secure_session()
 {
 	int rc;
-	mutex_lock(&resource_context.secure_lock);
 
-	rc = res_trk_enable_iommu_clocks();
-	if (rc) {
-		pr_err("IOMMU clock enabled failed while open");
-		goto error_open;
+	if (res_trk_check_for_sec_session() == 1) {
+		mutex_lock(&resource_context.secure_lock);
+		pr_err("Securing...\n");
+		rc = res_trk_enable_iommu_clocks();
+		if (rc) {
+			pr_err("IOMMU clock enabled failed while open");
+			goto error_open;
+		}
+		msm_ion_secure_heap(ION_HEAP(resource_context.memtype));
+		msm_ion_secure_heap(ION_HEAP(resource_context.cmd_mem_type));
+		res_trk_disable_iommu_clocks();
+		mutex_unlock(&resource_context.secure_lock);
 	}
-	msm_ion_secure_heap(ION_HEAP(resource_context.memtype));
-	msm_ion_secure_heap(ION_HEAP(resource_context.cmd_mem_type));
-	res_trk_disable_iommu_clocks();
-	mutex_unlock(&resource_context.secure_lock);
 	return 0;
 error_open:
 	mutex_unlock(&resource_context.secure_lock);
@@ -829,17 +832,19 @@
 int res_trk_close_secure_session()
 {
 	int rc;
-	mutex_lock(&resource_context.secure_lock);
-	rc = res_trk_enable_iommu_clocks();
-	if (rc) {
-		pr_err("IOMMU clock enabled failed while close");
-		goto error_close;
+	if (res_trk_check_for_sec_session() == 1) {
+		pr_err("Unsecuring....\n");
+		mutex_lock(&resource_context.secure_lock);
+		rc = res_trk_enable_iommu_clocks();
+		if (rc) {
+			pr_err("IOMMU clock enabled failed while close");
+			goto error_close;
+		}
+		msm_ion_unsecure_heap(ION_HEAP(resource_context.memtype));
+		msm_ion_unsecure_heap(ION_HEAP(resource_context.cmd_mem_type));
+		res_trk_disable_iommu_clocks();
+		mutex_unlock(&resource_context.secure_lock);
 	}
-	msm_ion_unsecure_heap(ION_HEAP(resource_context.memtype));
-	msm_ion_unsecure_heap(ION_HEAP(resource_context.cmd_mem_type));
-	res_trk_disable_iommu_clocks();
-	resource_context.secure_session = 0;
-	mutex_unlock(&resource_context.secure_lock);
 	return 0;
 error_close:
 	mutex_unlock(&resource_context.secure_lock);
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index 61deb8d..420fc19 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -869,7 +869,7 @@
 		client_ctx->h264_mv_ion_handle = ion_import_fd(
 					client_ctx->user_ion_client,
 					vcd_h264_mv_buffer->pmem_fd);
-		if (!client_ctx->h264_mv_ion_handle) {
+		if (IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
 			ERR("%s(): get_ION_handle failed\n", __func__);
 			goto import_ion_error;
 		}
@@ -916,12 +916,16 @@
 	else
 		return true;
 ion_map_error:
-	if (vcd_h264_mv_buffer->kernel_virtual_addr)
+	if (vcd_h264_mv_buffer->kernel_virtual_addr) {
 		ion_unmap_kernel(client_ctx->user_ion_client,
 				client_ctx->h264_mv_ion_handle);
-	if (client_ctx->h264_mv_ion_handle)
+		vcd_h264_mv_buffer->kernel_virtual_addr = NULL;
+	}
+	if (!IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
 		ion_free(client_ctx->user_ion_client,
 			client_ctx->h264_mv_ion_handle);
+		 client_ctx->h264_mv_ion_handle = NULL;
+	}
 import_ion_error:
 	return false;
 }
@@ -990,7 +994,7 @@
 	vcd_status = vcd_set_property(client_ctx->vcd_handle,
 				      &vcd_property_hdr, &h264_mv_buffer_size);
 
-	if (client_ctx->h264_mv_ion_handle != NULL) {
+	if (!IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
 		ion_unmap_kernel(client_ctx->user_ion_client,
 					client_ctx->h264_mv_ion_handle);
 		ion_unmap_iommu(client_ctx->user_ion_client,
@@ -999,6 +1003,7 @@
 				VIDEO_MAIN_POOL);
 		ion_free(client_ctx->user_ion_client,
 					client_ctx->h264_mv_ion_handle);
+		 client_ctx->h264_mv_ion_handle = NULL;
 	}
 
 	if (vcd_status)
@@ -2034,29 +2039,38 @@
 	return true;
 }
 
-struct video_client_ctx *vid_dec_open_client(void)
+int vid_dec_open_client(struct video_client_ctx **vid_clnt_ctx, int flags)
 {
+	int rc = 0;
 	s32 client_index;
-	struct video_client_ctx *client_ctx;
-	u32 vcd_status = VCD_ERR_FAIL;
+	struct video_client_ctx *client_ctx = NULL;
 	u8 client_count;
 
+	if (!vid_clnt_ctx) {
+		ERR("Invalid input\n");
+		return -EINVAL;
+	}
+	*vid_clnt_ctx = NULL;
 	client_count = vcd_get_num_of_clients();
 	if (client_count == VIDC_MAX_NUM_CLIENTS) {
 		ERR("ERROR : vid_dec_open() max number of clients"
 			"limit reached\n");
+		rc = -ENOMEM;
 		goto client_failure;
 	}
 
 	DBG(" Virtual Address of ioremap is %p\n", vid_dec_device_p->virt_base);
 	if (!vid_dec_device_p->num_clients) {
-		if (!vidc_load_firmware())
+		if (!vidc_load_firmware()) {
+			rc = -ENOMEM;
 			goto client_failure;
+		}
 	}
 
 	client_index = vid_dec_get_empty_client_index();
-	if (client_index < 0) {
-		ERR("%s() : No free clients client_index < 0\n", __func__);
+	if (client_index == -1) {
+		ERR("%s() : No free clients client_index == -1\n", __func__);
+		rc = -ENOMEM;
 		goto client_failure;
 	}
 	client_ctx = &vid_dec_device_p->vdec_clients[client_index];
@@ -2074,72 +2088,75 @@
 		client_ctx->user_ion_client = vcd_get_ion_client();
 		if (!client_ctx->user_ion_client) {
 			ERR("vcd_open ion client get failed");
+			rc = -ENOMEM;
 			goto client_failure;
 		}
 	}
-	vcd_status = vcd_open(vid_dec_device_p->device_handle, true,
-				  vid_dec_vcd_cb, client_ctx);
-	if (!vcd_status) {
+	rc = vcd_open(vid_dec_device_p->device_handle, true,
+				  vid_dec_vcd_cb, client_ctx, flags);
+	if (!rc) {
 		wait_for_completion(&client_ctx->event);
 		if (client_ctx->event_status) {
 			ERR("callback for vcd_open returned error: %u",
 				client_ctx->event_status);
+			rc = -ENODEV;
 			goto client_failure;
 		}
 	} else {
-		ERR("vcd_open returned error: %u", vcd_status);
+		ERR("vcd_open returned error: %u", rc);
 		goto client_failure;
 	}
 	client_ctx->seq_header_set = false;
-	return client_ctx;
+	*vid_clnt_ctx = client_ctx;
 client_failure:
-	return NULL;
+	return rc;
 }
 
 static int vid_dec_open_secure(struct inode *inode, struct file *file)
 {
+	int rc = 0;
+	struct video_client_ctx *client_ctx;
 	mutex_lock(&vid_dec_device_p->lock);
-	if (res_trk_check_for_sec_session() || vcd_get_num_of_clients()) {
-		ERR("Secure session present return failure\n");
-		mutex_unlock(&vid_dec_device_p->lock);
-		return -ENODEV;
-	}
-	res_trk_secure_set();
-	file->private_data = vid_dec_open_client();
-	if (!file->private_data) {
+	rc = vid_dec_open_client(&client_ctx, VCD_CP_SESSION);
+	if (rc)
+		goto error;
+	if (!client_ctx) {
+		rc = -ENOMEM;
 		goto error;
 	}
 
+	file->private_data = client_ctx;
 	if (res_trk_open_secure_session()) {
 		ERR("Secure session operation failure\n");
+		rc = -EACCES;
 		goto error;
 	}
 	mutex_unlock(&vid_dec_device_p->lock);
 	return 0;
-
 error:
-	res_trk_secure_unset();
 	mutex_unlock(&vid_dec_device_p->lock);
-	return -ENODEV;
-
+	return rc;
 }
 
 static int vid_dec_open(struct inode *inode, struct file *file)
 {
+	int rc = 0;
+	struct video_client_ctx *client_ctx;
 	INFO("msm_vidc_dec: Inside %s()", __func__);
 	mutex_lock(&vid_dec_device_p->lock);
-	if (res_trk_check_for_sec_session()) {
-		ERR("Secure session present return failure\n");
+	rc = vid_dec_open_client(&client_ctx, 0);
+	if (rc) {
 		mutex_unlock(&vid_dec_device_p->lock);
-		return -ENODEV;
+		return rc;
 	}
-	file->private_data = vid_dec_open_client();
-	if (!file->private_data) {
+	if (!client_ctx) {
 		mutex_unlock(&vid_dec_device_p->lock);
-		return -ENODEV;
+		return -ENOMEM;
 	}
+
+	file->private_data = client_ctx;
 	mutex_unlock(&vid_dec_device_p->lock);
-	return 0;
+	return rc;
 }
 
 static int vid_dec_release_secure(struct inode *inode, struct file *file)
@@ -2149,7 +2166,6 @@
 	INFO("msm_vidc_dec: Inside %s()", __func__);
 	vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT);
 	vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_INPUT);
-	res_trk_close_secure_session();
 	vid_dec_close_client(client_ctx);
 	vidc_release_firmware();
 #ifndef USE_RES_TRACKER
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index 93b1848..d93d07e 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -521,7 +521,7 @@
 {
 	s32 client_index;
 	struct video_client_ctx *client_ctx;
-	u32 vcd_status = VCD_ERR_FAIL;
+	int rc = 0;
 	u8 client_count = 0;
 
 	INFO("\n msm_vidc_enc: Inside %s()", __func__);
@@ -530,10 +530,9 @@
 
 	stop_cmd = 0;
 	client_count = vcd_get_num_of_clients();
-	if (client_count == VIDC_MAX_NUM_CLIENTS ||
-		res_trk_check_for_sec_session()) {
+	if (client_count == VIDC_MAX_NUM_CLIENTS) {
 		ERR("ERROR : vid_enc_open() max number of clients"
-		    "limit reached or secure session is open\n");
+		    "limit reached\n");
 		mutex_unlock(&vid_enc_device_p->lock);
 		return -ENODEV;
 	}
@@ -568,11 +567,11 @@
 			return -EFAULT;
 		}
 	}
-	vcd_status = vcd_open(vid_enc_device_p->device_handle, false,
-		vid_enc_vcd_cb, client_ctx);
+	rc = vcd_open(vid_enc_device_p->device_handle, false,
+		vid_enc_vcd_cb, client_ctx, 0);
 	client_ctx->stop_msg = 0;
 
-	if (!vcd_status) {
+	if (!rc) {
 		wait_for_completion(&client_ctx->event);
 		if (client_ctx->event_status) {
 			ERR("callback for vcd_open returned error: %u",
@@ -581,13 +580,13 @@
 			return -EFAULT;
 		}
 	} else {
-		ERR("vcd_open returned error: %u", vcd_status);
+		ERR("vcd_open returned error: %u", rc);
 		mutex_unlock(&vid_enc_device_p->lock);
-		return -EFAULT;
+		return rc;
 	}
 	file->private_data = client_ctx;
 	mutex_unlock(&vid_enc_device_p->lock);
-	return 0;
+	return rc;
 }
 
 static int vid_enc_release(struct inode *inode, struct file *file)
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index dda81ed..6fdb1c6 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -285,14 +285,14 @@
 
 	if (unlikely(rc)) {
 		ERR("%s() :request_irq failed\n", __func__);
-		goto error_vidc_platfom_register;
+		goto error_vidc_request_irq;
 	}
 	res_trk_init(vidc_device_p->device, vidc_device_p->irq);
 	vidc_timer_wq = create_singlethread_workqueue("vidc_timer_wq");
 	if (!vidc_timer_wq) {
 		ERR("%s: create workque failed\n", __func__);
 		rc = -ENOMEM;
-		goto error_vidc_platfom_register;
+		goto error_vidc_create_workqueue;
 	}
 	DBG("Disabling IRQ in %s()\n", __func__);
 	disable_irq_nosync(vidc_device_p->irq);
@@ -315,6 +315,10 @@
 #endif
 	return 0;
 
+error_vidc_create_workqueue:
+	free_irq(vidc_device_p->irq, vidc_device_p->device);
+error_vidc_request_irq:
+	platform_driver_unregister(&msm_vidc_720p_platform_driver);
 error_vidc_platfom_register:
 	cdev_del(&(vidc_device_p->cdev));
 error_vidc_cdev_add:
@@ -417,16 +421,21 @@
 			buf_addr_table[i].client_data);
 			buf_addr_table[i].client_data = NULL;
 		}
-		if (buf_addr_table[i].buff_ion_handle) {
-			ion_unmap_kernel(client_ctx->user_ion_client,
-					buf_addr_table[i].buff_ion_handle);
-			ion_unmap_iommu(client_ctx->user_ion_client,
-					buf_addr_table[i].buff_ion_handle,
-					VIDEO_DOMAIN,
-					VIDEO_MAIN_POOL);
-			ion_free(client_ctx->user_ion_client,
-					buf_addr_table[i].buff_ion_handle);
-			buf_addr_table[i].buff_ion_handle = NULL;
+		if (!IS_ERR_OR_NULL(buf_addr_table[i].buff_ion_handle)) {
+			if (!IS_ERR_OR_NULL(client_ctx->user_ion_client)) {
+				ion_unmap_kernel(client_ctx->user_ion_client,
+						buf_addr_table[i].
+						buff_ion_handle);
+				ion_unmap_iommu(client_ctx->user_ion_client,
+						buf_addr_table[i].
+						buff_ion_handle,
+						VIDEO_DOMAIN,
+						VIDEO_MAIN_POOL);
+				ion_free(client_ctx->user_ion_client,
+						buf_addr_table[i].
+						buff_ion_handle);
+				buf_addr_table[i].buff_ion_handle = NULL;
+			}
 		}
 	}
 	if (client_ctx->vcd_h264_mv_buffer.client_data) {
@@ -434,16 +443,18 @@
 		client_ctx->vcd_h264_mv_buffer.client_data);
 		client_ctx->vcd_h264_mv_buffer.client_data = NULL;
 	}
-	if (client_ctx->h264_mv_ion_handle) {
-		ion_unmap_kernel(client_ctx->user_ion_client,
-				client_ctx->h264_mv_ion_handle);
-		ion_unmap_iommu(client_ctx->user_ion_client,
-				client_ctx->h264_mv_ion_handle,
-				VIDEO_DOMAIN,
-				VIDEO_MAIN_POOL);
-		ion_free(client_ctx->user_ion_client,
-				client_ctx->h264_mv_ion_handle);
-		client_ctx->h264_mv_ion_handle = NULL;
+	if (!IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
+		if (!IS_ERR_OR_NULL(client_ctx->user_ion_client)) {
+			ion_unmap_kernel(client_ctx->user_ion_client,
+					client_ctx->h264_mv_ion_handle);
+			ion_unmap_iommu(client_ctx->user_ion_client,
+					client_ctx->h264_mv_ion_handle,
+					VIDEO_DOMAIN,
+					VIDEO_MAIN_POOL);
+			ion_free(client_ctx->user_ion_client,
+					client_ctx->h264_mv_ion_handle);
+			client_ctx->h264_mv_ion_handle = NULL;
+		}
 	}
 bail_out_cleanup:
 	return;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_api.c b/drivers/video/msm/vidc/common/vcd/vcd_api.c
index e0ef3af..7aadc2b 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_api.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_api.c
@@ -74,25 +74,106 @@
 }
 EXPORT_SYMBOL(vcd_term);
 
+struct client_security_info {
+	int secure_enc;
+	int secure_dec;
+	int non_secure_enc;
+	int non_secure_dec;
+};
+
+static int vcd_get_clients_security_info(struct client_security_info *sec_info)
+{
+	struct vcd_drv_ctxt *drv_ctxt;
+	struct vcd_clnt_ctxt *cctxt;
+	int count = 0;
+	if (!sec_info) {
+		VCD_MSG_ERROR("Invalid argument\n");
+		return -EINVAL;
+	}
+	memset(sec_info, 0 , sizeof(*sec_info));
+	drv_ctxt = vcd_get_drv_context();
+	mutex_lock(&drv_ctxt->dev_mutex);
+	cctxt = drv_ctxt->dev_ctxt.cctxt_list_head;
+	while (cctxt) {
+		if (cctxt->secure && cctxt->decoding)
+			sec_info->secure_dec++;
+		else if (cctxt->secure && !cctxt->decoding)
+			sec_info->secure_enc++;
+		else if (!cctxt->secure && cctxt->decoding)
+			sec_info->non_secure_dec++;
+		else
+			sec_info->non_secure_enc++;
+		count++;
+		cctxt = cctxt->next;
+	}
+	mutex_unlock(&drv_ctxt->dev_mutex);
+	return count;
+}
+
+static int is_session_invalid(u32 decoding, u32 flags)
+{
+	int is_secure;
+	struct client_security_info sec_info;
+	int client_count = 0;
+	int secure_session_running = 0;
+	is_secure = (flags & VCD_CP_SESSION) ? 1 : 0;
+	client_count = vcd_get_clients_security_info(&sec_info);
+	secure_session_running = (sec_info.secure_enc > 0) ||
+			(sec_info.secure_dec > 0);
+	if (!decoding && is_secure) {
+		if ((sec_info.secure_dec == 1))
+			VCD_MSG_LOW("SE-SD: SUCCESS\n");
+		else {
+			VCD_MSG_LOW("SE is permitted only with SD: FAILURE\n");
+			return -EACCES;
+		}
+	} else if (!decoding && !is_secure) {
+		if (secure_session_running) {
+			VCD_MSG_LOW("SD-NSE: FAILURE\n");
+			VCD_MSG_LOW("SE-NSE: FAILURE\n");
+			return -EACCES;
+		}
+	} else if (decoding && is_secure) {
+		if (client_count > 0) {
+			VCD_MSG_LOW("S/NS-SD: FAILURE\n");
+			if (sec_info.secure_enc > 0 ||
+				sec_info.non_secure_enc > 0) {
+				return -EAGAIN;
+			}
+			return -EACCES;
+		}
+	} else {
+		if (sec_info.secure_dec > 0) {
+			VCD_MSG_LOW("SD-NSD: FAILURE\n");
+			return -EACCES;
+		}
+	}
+	return 0;
+}
+
 u32 vcd_open(s32 driver_handle, u32 decoding,
 	void (*callback) (u32 event, u32 status, void *info, size_t sz,
 		       void *handle, void *const client_data),
-	void *client_data)
+	void *client_data, int flags)
 {
-	u32 rc = VCD_S_SUCCESS;
+	u32 rc = 0;
 	struct vcd_drv_ctxt *drv_ctxt;
-
+	struct vcd_clnt_ctxt *cctxt;
+	int is_secure = (flags & VCD_CP_SESSION) ? 1 : 0;
 	VCD_MSG_MED("vcd_open:");
 
 	if (!callback) {
 		VCD_MSG_ERROR("Bad parameters");
-
-		return VCD_ERR_ILLEGAL_PARM;
+		return -EINVAL;
 	}
-	if (res_trk_check_for_sec_session() && vcd_get_num_of_clients()) {
-		VCD_MSG_ERROR("Secure session in progress");
-		return VCD_ERR_BAD_STATE;
+	rc = is_session_invalid(decoding, flags);
+	if (rc) {
+		VCD_MSG_ERROR("Invalid Session: is_decoder: %d, secure: %d\n",
+				decoding, flags);
+		return rc;
 	}
+	if (is_secure)
+		res_trk_secure_set();
 	drv_ctxt = vcd_get_drv_context();
 	mutex_lock(&drv_ctxt->dev_mutex);
 
@@ -100,17 +181,22 @@
 		rc = drv_ctxt->dev_state.state_table->ev_hdlr.
 		    open(drv_ctxt, driver_handle, decoding, callback,
 			    client_data);
+		if (rc) {
+			rc = -ENODEV;
+		}
 	} else {
 		VCD_MSG_ERROR("Unsupported API in device state %d",
 			      drv_ctxt->dev_state.state);
-
-		rc = VCD_ERR_BAD_STATE;
+		rc = -EPERM;
 	}
+	if (!rc) {
+		cctxt = drv_ctxt->dev_ctxt.cctxt_list_head;
+		cctxt->secure = is_secure;
+	} else if (is_secure)
+		res_trk_secure_unset();
 
 	mutex_unlock(&drv_ctxt->dev_mutex);
-
 	return rc;
-
 }
 EXPORT_SYMBOL(vcd_open);
 
@@ -120,7 +206,7 @@
 	    (struct vcd_clnt_ctxt *)handle;
 	struct vcd_drv_ctxt *drv_ctxt;
 	u32 rc;
-
+	int is_secure = 0;
 	VCD_MSG_MED("vcd_close:");
 
 	if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
@@ -129,6 +215,7 @@
 		return VCD_ERR_BAD_HANDLE;
 	}
 
+	is_secure = cctxt->secure;
 	drv_ctxt = vcd_get_drv_context();
 	mutex_lock(&drv_ctxt->dev_mutex);
 	if (drv_ctxt->dev_state.state_table->ev_hdlr.close) {
@@ -141,6 +228,8 @@
 		rc = VCD_ERR_BAD_STATE;
 	}
 	mutex_unlock(&drv_ctxt->dev_mutex);
+	if (is_secure)
+		res_trk_secure_unset();
 	return rc;
 
 }
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 86e9ff6..0d5ba9c 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -342,6 +342,7 @@
 static u32 vcd_flush_in_eos(struct vcd_clnt_ctxt *cctxt,
 	u32 mode)
 {
+	u32 rc = VCD_S_SUCCESS;
 	VCD_MSG_LOW("vcd_flush_in_eos:");
 
 	if (mode > VCD_FLUSH_ALL || !mode) {
@@ -351,10 +352,18 @@
 	}
 
 	VCD_MSG_MED("Flush mode requested %d", mode);
+	if (!(cctxt->status.frame_submitted) &&
+		(!cctxt->decoding)) {
+		rc = vcd_flush_buffers(cctxt, mode);
+		if (!VCD_FAILED(rc)) {
+			VCD_MSG_HIGH("All buffers are flushed");
+			cctxt->status.mask |= (mode & VCD_FLUSH_ALL);
+			vcd_send_flush_done(cctxt, VCD_S_SUCCESS);
+		}
+	} else
+		cctxt->status.mask |= (mode & VCD_FLUSH_ALL);
 
-	cctxt->status.mask |= (mode & VCD_FLUSH_ALL);
-
-	return VCD_S_SUCCESS;
+	return rc;
 }
 
 static u32 vcd_flush_in_invalid(struct vcd_clnt_ctxt *cctxt,
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index b8438e1..e33c8cd 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -210,6 +210,7 @@
 	struct vcd_clnt_ctxt *next;
 	u32 meta_mode;
 	int perf_set_by_client;
+	int secure;
 };
 
 #define VCD_BUFFERPOOL_INUSE_DECREMENT(val) \
diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h
new file mode 100644
index 0000000..0104abc
--- /dev/null
+++ b/include/linux/iopoll.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012 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 _LINUX_IOPOLL_H
+#define _LINUX_IOPOLL_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#include <asm-generic/errno.h>
+#include <asm/io.h>
+
+/**
+ * readl_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @sleep_us: Maximum time to sleep between reads in uS (0 tight-loops)
+ * @timeout_us: Timeout in uS, 0 means never timeout
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @addr is stored in @val. Must not
+ * be called from atomic context if sleep_us or timeout_us are used.
+ */
+#define readl_poll_timeout(addr, val, cond, sleep_us, timeout_us) \
+({ \
+	unsigned long timeout = jiffies + usecs_to_jiffies(timeout_us); \
+	might_sleep_if(timeout_us); \
+	for (;;) { \
+		(val) = readl(addr); \
+		if ((cond) || (timeout_us && time_after(jiffies, timeout))) \
+			break; \
+		if (sleep_us) \
+			usleep_range(1, sleep_us); \
+	} \
+	(cond) ? 0 : -ETIMEDOUT; \
+})
+
+/**
+ * readl_poll - Periodically poll an address until a condition is met
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @sleep_us: Maximum time to sleep between reads in uS (0 tight-loops)
+ *
+ * Must not be called from atomic context if sleep_us is used.
+ */
+#define readl_poll(addr, val, cond, sleep_us) \
+	readl_poll_timeout(addr, val, cond, sleep_us, 0)
+
+/**
+ * readl_tight_poll_timeout - Tight-loop on an address until a condition is met or a timeout occurs
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @timeout_us: Timeout in uS, 0 means never timeout
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @addr is stored in @val. Must not
+ * be called from atomic context if timeout_us is used.
+ */
+#define readl_tight_poll_timeout(addr, val, cond, timeout_us) \
+	readl_poll_timeout(addr, val, cond, 0, timeout_us)
+
+/**
+ * readl_tight_poll - Tight-loop on an address until a condition is met
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ *
+ * May be called from atomic context.
+ */
+#define readl_tight_poll(addr, val, cond) \
+	readl_poll_timeout(addr, val, cond, 0, 0)
+
+#endif /* _LINUX_IOPOLL_H */
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index 0df513b..bdd6b2a 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -36,6 +36,7 @@
 
 /* Look up a kernel symbol and return it in a text buffer. */
 extern int sprint_symbol(char *buffer, unsigned long address);
+extern int sprint_symbol_no_offset(char *buffer, unsigned long address);
 extern int sprint_backtrace(char *buffer, unsigned long address);
 
 /* Look up a kernel symbol and print it to the kernel messages. */
@@ -80,6 +81,12 @@
 	return 0;
 }
 
+static inline int sprint_symbol_no_offset(char *buffer, unsigned long addr)
+{
+	*buffer = '\0';
+	return 0;
+}
+
 static inline int sprint_backtrace(char *buffer, unsigned long addr)
 {
 	*buffer = '\0';
diff --git a/include/linux/mfd/pm8xxx/pm8xxx-adc.h b/include/linux/mfd/pm8xxx/pm8xxx-adc.h
index d2b1cfc..84f8e03 100644
--- a/include/linux/mfd/pm8xxx/pm8xxx-adc.h
+++ b/include/linux/mfd/pm8xxx/pm8xxx-adc.h
@@ -51,6 +51,10 @@
 	CHANNEL_MPP_1,
 	CHANNEL_MPP_2,
 	CHANNEL_BATT_THERM,
+	/* PM8018 ADC Arbiter uses a single channel on AMUX8
+	 * to read either Batt_id or Batt_therm.
+	 */
+	CHANNEL_BATT_ID_THERM = CHANNEL_BATT_THERM,
 	CHANNEL_BATT_ID,
 	CHANNEL_USBIN,
 	CHANNEL_DIE_TEMP,
diff --git a/include/linux/mfd/wcd9xxx/wcd9304_registers.h b/include/linux/mfd/wcd9xxx/wcd9304_registers.h
index 65e4728..70902bc 100644
--- a/include/linux/mfd/wcd9xxx/wcd9304_registers.h
+++ b/include/linux/mfd/wcd9xxx/wcd9304_registers.h
@@ -517,7 +517,7 @@
 #define SITAR_A_CDC_CLK_TX_I2S_CTL			(0x306)
 #define SITAR_A_CDC_CLK_TX_I2S_CTL__POR			(0x00000003)
 #define SITAR_A_CDC_CLK_OTHR_RESET_CTL			(0x307)
-#define SITAR_A_CDC_CLK_OTHR_RESET_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_CLK_OTHR_RESET_CTL__POR			(0x00000010)
 #define SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL			(0x308)
 #define SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR			(0x00000000)
 #define SITAR_A_CDC_CLK_OTHR_CTL			(0x30A)
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 84c8bfe..a0af4b5 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -328,6 +328,7 @@
 	MDP_BLOCK_DMA_P,
 	MDP_BLOCK_DMA_S,
 	MDP_BLOCK_DMA_E,
+	MDP_BLOCK_OVERLAY_2,
 	MDP_BLOCK_MAX,
 };
 
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e7cc68e..1dae562 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1031,6 +1031,55 @@
  *	%NL80211_CMD_SET_BEACON to provide extra IEs (e.g., WPS/P2P IE) into
  *	(Re)Association Response frames when the driver (or firmware) replies to
  *	(Re)Association Request frames.
+ * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration
+ *      of the station, see &enum nl80211_sta_wme_attr.
+ * @NL80211_ATTR_SUPPORT_AP_UAPSD: the device supports uapsd when working
+ *      as AP.
+ *
+ * @NL80211_ATTR_ROAM_SUPPORT: Indicates whether the firmware is capable of
+ *      roaming to another AP in the same ESS if the signal lever is low.
+ *
+ * @NL80211_ATTR_PMKSA_CANDIDATE: Nested attribute containing the PMKSA caching
+ *      candidate information, see &enum nl80211_pmksa_candidate_attr.
+ *
+ * @NL80211_ATTR_TX_NO_CCK_RATE: Indicates whether to use CCK rate or not
+ *      for management frames transmission. In order to avoid p2p probe/action
+ *      frames are being transmitted at CCK rate in 2GHz band, the user space
+ *      applications use this attribute.
+ *      This attribute is used with %NL80211_CMD_TRIGGER_SCAN and
+ *      %NL80211_CMD_FRAME commands.
+ *
+ * @NL80211_ATTR_TDLS_ACTION: Low level TDLS action code (e.g. link setup
+ *      request, link setup confirm, link teardown, etc.). Values are
+ *      described in the TDLS (802.11z) specification.
+ * @NL80211_ATTR_TDLS_DIALOG_TOKEN: Non-zero token for uniquely identifying a
+ *      TDLS conversation between two devices.
+ * @NL80211_ATTR_TDLS_OPERATION: High level TDLS operation; see
+ *      &enum nl80211_tdls_operation, represented as a u8.
+ * @NL80211_ATTR_TDLS_SUPPORT: A flag indicating the device can operate
+ *      as a TDLS peer sta.
+ * @NL80211_ATTR_TDLS_EXTERNAL_SETUP: The TDLS discovery/setup and teardown
+ *      procedures should be performed by sending TDLS packets via
+ *      %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
+ *      used for asking the driver to perform a TDLS operation.
+ *
+ * @NL80211_ATTR_DEVICE_AP_SME: This u32 attribute may be listed for devices
+ *      that have AP support to indicate that they have the AP SME integrated
+ *      with support for the features listed in this attribute, see
+ *      &enum nl80211_ap_sme_features.
+ *
+ * @NL80211_ATTR_DONT_WAIT_FOR_ACK: Used with %NL80211_CMD_FRAME, this tells
+ *      the driver to not wait for an acknowledgement. Note that due to this,
+ *      it will also not give a status callback nor return a cookie. This is
+ *      mostly useful for probe responses to save airtime.
+ *
+ * @NL80211_ATTR_FEATURE_FLAGS: This u32 attribute contains flags from
+ *      &enum nl80211_feature_flags and is advertised in wiphy information.
+ * @NL80211_ATTR_PROBE_RESP_OFFLOAD: Indicates that the HW responds to probe
+ *
+ *      requests while operating in AP-mode.
+ *      This attribute holds a bitmap of the supported protocols for
+ *      offloading (see &enum nl80211_probe_resp_offload_support_attr).
  *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -1254,6 +1303,19 @@
 
 	NL80211_ATTR_TX_NO_CCK_RATE,
 
+	NL80211_ATTR_TDLS_ACTION,
+	NL80211_ATTR_TDLS_DIALOG_TOKEN,
+	NL80211_ATTR_TDLS_OPERATION,
+	NL80211_ATTR_TDLS_SUPPORT,
+	NL80211_ATTR_TDLS_EXTERNAL_SETUP,
+	NL80211_ATTR_DEVICE_AP_SME,
+
+	NL80211_ATTR_DONT_WAIT_FOR_ACK,
+
+	NL80211_ATTR_FEATURE_FLAGS,
+
+	NL80211_ATTR_PROBE_RESP_OFFLOAD,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -2436,4 +2498,35 @@
 	NL80211_HIDDEN_SSID_ZERO_CONTENTS
 };
 
+/*
+ * enum nl80211_ap_sme_features - device-integrated AP features
+ * Reserved for future use, no bits are defined in
+ * NL80211_ATTR_DEVICE_AP_SME yet.
+enum nl80211_ap_sme_features {
+};
+ */
+
+/**
+ * enum nl80211_probe_resp_offload_support_attr - optional supported
+ *     protocols for probe-response offloading by the driver/FW.
+ *     To be used with the %NL80211_ATTR_PROBE_RESP_OFFLOAD attribute.
+ *     Each enum value represents a bit in the bitmap of supported
+ *     protocols. Typically a subset of probe-requests belonging to a
+ *     supported protocol will be excluded from offload and uploaded
+ *     to the host.
+ *
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS: Support for WPS ver. 1
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2: Support for WPS ver. 2
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P: Support for P2P
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U: Support for 802.11u
+ */
+
+enum nl80211_probe_resp_offload_support_attr {
+	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS =        1<<0,
+	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 =       1<<1,
+	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P =        1<<2,
+	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U =     1<<3,
+};
+
+
 #endif /* __LINUX_NL80211_H */
diff --git a/include/linux/qpnp/gpio.h b/include/linux/qpnp/gpio.h
index 0447a08..a31b7f3 100644
--- a/include/linux/qpnp/gpio.h
+++ b/include/linux/qpnp/gpio.h
@@ -69,10 +69,6 @@
  *			can be paired (shorted) with each other. Some gpio pin
  *			can act as alternate functions. This parameter should
  *			be of type QPNP_GPIO_FUNC_*
- * @inv_int_pol:	Invert polarity before feeding the line to the interrupt
- *			module in pmic. This feature will almost be never used
- *			since the pm8xxx interrupt block can detect both edges
- *			and both levels.
  * @master_en:		1 = Enable features within the GPIO block based on
  *			configurations.
  *			0 = Completely disable the GPIO block and let the pin
@@ -86,7 +82,6 @@
 	int		vin_sel;
 	int		out_strength;
 	int		src_select;
-	int		inv_int_pol;
 	int		master_en;
 };
 
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index a731774..4c0ae07 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -149,6 +149,17 @@
 };
 
 /**
+ * Used different VDDCX voltage voting mechnism
+ * VDDCX_CORNER       Vote for VDDCX Corner voltage
+ * VDDCX              Vote for VDDCX Absolute voltage
+ */
+enum usb_vdd_type {
+	VDDCX_CORNER = 0,
+	VDDCX,
+	VDD_TYPE_MAX,
+};
+
+/**
  * SPS Pipes direction.
  *
  * USB_TO_PEER_PERIPHERAL	USB (as Producer) to other
@@ -327,21 +338,16 @@
 	 * voltage regulator(VDDCX).
 	 */
 #define ALLOW_PHY_RETENTION		BIT(1)
-	  /*
-	   * Disable the OTG comparators to save more power
-	   * if depends on PMIC for VBUS and ID interrupts.
-	   */
-#define ALLOW_PHY_COMP_DISABLE		BIT(2)
 	unsigned long lpm_flags;
 #define PHY_PWR_COLLAPSED		BIT(0)
 #define PHY_RETENTIONED			BIT(1)
-#define PHY_OTG_COMP_DISABLED		BIT(2)
 	struct pm_qos_request_list pm_qos_req_dma;
 	int reset_counter;
 	unsigned long b_last_se0_sess;
 	unsigned long tmouts;
 	u8 active_tmout;
 	struct hrtimer timer;
+	enum usb_vdd_type vdd_type;
 };
 
 struct msm_hsic_host_platform_data {
diff --git a/include/media/gpio-ir-recv.h b/include/media/gpio-ir-recv.h
index 61a7fbb..3eab611 100644
--- a/include/media/gpio-ir-recv.h
+++ b/include/media/gpio-ir-recv.h
@@ -16,6 +16,7 @@
 struct gpio_ir_recv_platform_data {
 	unsigned int gpio_nr;
 	bool active_low;
+	bool can_wakeup;
 };
 
 #endif /* __GPIO_IR_RECV_H__ */
diff --git a/include/media/msm/vcd_api.h b/include/media/msm/vcd_api.h
index 20d3ef9..32a1759 100644
--- a/include/media/msm/vcd_api.h
+++ b/include/media/msm/vcd_api.h
@@ -116,11 +116,14 @@
 	void (*timer_stop) (void *timer_handle);
 };
 
+/*Flags passed to vcd_open*/
+#define VCD_CP_SESSION 0x00000001
+
 u32 vcd_init(struct vcd_init_config *config, s32 *driver_handle);
 u32 vcd_term(s32 driver_handle);
 u32 vcd_open(s32 driver_handle, u32 decoding,
 	void (*callback) (u32 event, u32 status, void *info, size_t sz,
-	void *handle, void *const client_data), void *client_data);
+	void *handle, void *const client_data), void *client_data, int flags);
 u32 vcd_close(void *handle);
 u32 vcd_encode_start(void *handle);
 u32 vcd_encode_frame(void *handle, struct vcd_frame_data *input_frame);
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 31977ed..7aae5e1 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -148,50 +148,44 @@
 #define MSM_CAM_IOCTL_PUT_ST_FRAME \
 	_IOW(MSM_CAM_IOCTL_MAGIC, 39, struct msm_camera_st_frame *)
 
-#define MSM_CAM_IOCTL_GET_CONFIG_INFO \
-	_IOR(MSM_CAM_IOCTL_MAGIC, 40, struct msm_cam_config_dev_info *)
-
 #define MSM_CAM_IOCTL_V4L2_EVT_NOTIFY \
-	_IOR(MSM_CAM_IOCTL_MAGIC, 41, struct v4l2_event *)
+	_IOR(MSM_CAM_IOCTL_MAGIC, 40, struct v4l2_event *)
 
 #define MSM_CAM_IOCTL_SET_MEM_MAP_INFO \
-	_IOR(MSM_CAM_IOCTL_MAGIC, 42, struct msm_mem_map_info *)
+	_IOR(MSM_CAM_IOCTL_MAGIC, 41, struct msm_mem_map_info *)
 
 #define MSM_CAM_IOCTL_ACTUATOR_IO_CFG \
-	_IOW(MSM_CAM_IOCTL_MAGIC, 43, struct msm_actuator_cfg_data *)
+	_IOW(MSM_CAM_IOCTL_MAGIC, 42, struct msm_actuator_cfg_data *)
 
 #define MSM_CAM_IOCTL_MCTL_POST_PROC \
-	_IOW(MSM_CAM_IOCTL_MAGIC, 44, struct msm_mctl_post_proc_cmd *)
+	_IOW(MSM_CAM_IOCTL_MAGIC, 43, struct msm_mctl_post_proc_cmd *)
 
 #define MSM_CAM_IOCTL_RESERVE_FREE_FRAME \
-	_IOW(MSM_CAM_IOCTL_MAGIC, 45, struct msm_cam_evt_divert_frame *)
+	_IOW(MSM_CAM_IOCTL_MAGIC, 44, struct msm_cam_evt_divert_frame *)
 
 #define MSM_CAM_IOCTL_RELEASE_FREE_FRAME \
-	_IOR(MSM_CAM_IOCTL_MAGIC, 46, struct msm_cam_evt_divert_frame *)
+	_IOR(MSM_CAM_IOCTL_MAGIC, 45, struct msm_cam_evt_divert_frame *)
 
 #define MSM_CAM_IOCTL_PICT_PP_DIVERT_DONE \
-	_IOR(MSM_CAM_IOCTL_MAGIC, 47, struct msm_pp_frame *)
+	_IOR(MSM_CAM_IOCTL_MAGIC, 46, struct msm_pp_frame *)
 
 #define MSM_CAM_IOCTL_SENSOR_V4l2_S_CTRL \
-	_IOR(MSM_CAM_IOCTL_MAGIC, 48, struct v4l2_control)
+	_IOR(MSM_CAM_IOCTL_MAGIC, 47, struct v4l2_control)
 
 #define MSM_CAM_IOCTL_SENSOR_V4l2_QUERY_CTRL \
-	_IOR(MSM_CAM_IOCTL_MAGIC, 49, struct v4l2_queryctrl)
+	_IOR(MSM_CAM_IOCTL_MAGIC, 48, struct v4l2_queryctrl)
 
 #define MSM_CAM_IOCTL_GET_KERNEL_SYSTEM_TIME \
-	_IOW(MSM_CAM_IOCTL_MAGIC, 50, struct timeval *)
+	_IOW(MSM_CAM_IOCTL_MAGIC, 49, struct timeval *)
 
 #define MSM_CAM_IOCTL_SET_VFE_OUTPUT_TYPE \
-	_IOW(MSM_CAM_IOCTL_MAGIC, 51, uint32_t *)
-
-#define MSM_CAM_IOCTL_GET_MCTL_INFO \
-	_IOR(MSM_CAM_IOCTL_MAGIC, 52, struct msm_mctl_node_info *)
+	_IOW(MSM_CAM_IOCTL_MAGIC, 50, uint32_t *)
 
 #define MSM_CAM_IOCTL_MCTL_DIVERT_DONE \
-	_IOR(MSM_CAM_IOCTL_MAGIC, 53, struct msm_cam_evt_divert_frame *)
+	_IOR(MSM_CAM_IOCTL_MAGIC, 51, struct msm_cam_evt_divert_frame *)
 
 #define MSM_CAM_IOCTL_GET_ACTUATOR_INFO \
-	_IOW(MSM_CAM_IOCTL_MAGIC, 54, struct msm_actuator_cfg_data *)
+	_IOW(MSM_CAM_IOCTL_MAGIC, 52, struct msm_actuator_cfg_data *)
 
 struct msm_mctl_pp_cmd {
 	int32_t  id;
@@ -260,6 +254,8 @@
 	uint32_t timeout_ms;
 	int resp_fd; /* FIXME: to be used by the kernel, pass-through for now */
 	int vnode_id;  /* video dev id. Can we overload resp_fd? */
+	int queue_idx;
+	uint32_t evt_id;
 	uint32_t stream_type; /* used to pass value to qcamera server */
 	int config_ident; /*used as identifier for config node*/
 };
@@ -270,6 +266,7 @@
 	unsigned int len;	/* size in, number of bytes out */
 	uint32_t frame_id;
 	void *data;
+	struct timespec timestamp;
 };
 
 struct msm_pp_frame_sp {
@@ -1362,4 +1359,23 @@
 #define QCAMERA_DEVICE_GROUP_ID 1
 #define QCAMERA_VNODE_GROUP_ID 2
 
+#define MSM_CAM_V4L2_IOCTL_GET_CAMERA_INFO \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct msm_camera_v4l2_ioctl_t *)
+
+#define MSM_CAM_V4L2_IOCTL_GET_CONFIG_INFO \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 2, struct msm_camera_v4l2_ioctl_t *)
+
+#define MSM_CAM_V4L2_IOCTL_GET_MCTL_INFO \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 3, struct msm_camera_v4l2_ioctl_t *)
+
+#define MSM_CAM_V4L2_IOCTL_CTRL_CMD_DONE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct msm_camera_v4l2_ioctl_t *)
+
+#define MSM_CAM_V4L2_IOCTL_GET_EVENT_PAYLOAD \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct msm_camera_v4l2_ioctl_t *)
+
+struct msm_camera_v4l2_ioctl_t {
+	void __user *ioctl_ptr;
+};
+
 #endif /* __LINUX_MSM_CAMERA_H */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 2b5824c..5053bd8 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -629,7 +629,7 @@
 			if (conn->state == BT_CONNECTED) {
 				timeo = msecs_to_jiffies(conn->disc_timeout);
 				if (!conn->out)
-					timeo *= 20;
+					timeo *= 4;
 			} else
 				timeo = msecs_to_jiffies(10);
 		} else
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 4898ea2..53c7196 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1584,6 +1584,21 @@
  * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing
  *	auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH.
  * @WIPHY_FLAG_SUPPORTS_SCHED_SCAN: The device supports scheduled scans.
+ * @WIPHY_FLAG_SUPPORTS_FW_ROAM: The device supports roaming feature in the
+ *     firmware.
+ * @WIPHY_FLAG_AP_UAPSD: The device supports uapsd on AP.
+ * @WIPHY_FLAG_SUPPORTS_TDLS: The device supports TDLS (802.11z) operation.
+ * @WIPHY_FLAG_TDLS_EXTERNAL_SETUP: The device does not handle TDLS (802.11z)
+ *     link setup/discovery operations internally. Setup, discovery and
+ *     teardown packets should be sent through the @NL80211_CMD_TDLS_MGMT
+ *     command. When this flag is not set, @NL80211_CMD_TDLS_OPER should be
+ *     used for asking the driver/firmware to perform a TDLS operation.
+ * @WIPHY_FLAG_HAVE_AP_SME: device integrates AP SME
+ * @WIPHY_FLAG_REPORTS_OBSS: the device will report beacons from other BSSes
+ *      when there are virtual interfaces in AP mode by calling
+ *      cfg80211_report_obss_beacon().
+ * @WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD: When operating as an AP, the device
+ *      responds to probe-requests in hardware.
  */
 enum wiphy_flags {
 	WIPHY_FLAG_CUSTOM_REGULATORY		= BIT(0),
@@ -1598,6 +1613,13 @@
 	WIPHY_FLAG_MESH_AUTH			= BIT(10),
 	WIPHY_FLAG_SUPPORTS_SCHED_SCAN		= BIT(11),
 	WIPHY_FLAG_ENFORCE_COMBINATIONS		= BIT(12),
+	WIPHY_FLAG_SUPPORTS_FW_ROAM             = BIT(13),
+	WIPHY_FLAG_AP_UAPSD                     = BIT(14),
+	WIPHY_FLAG_SUPPORTS_TDLS                = BIT(15),
+	WIPHY_FLAG_TDLS_EXTERNAL_SETUP          = BIT(16),
+	WIPHY_FLAG_HAVE_AP_SME                  = BIT(17),
+	WIPHY_FLAG_REPORTS_OBSS                 = BIT(18),
+	WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD        = BIT(19),
 };
 
 /**
@@ -1788,6 +1810,7 @@
  *	may request, if implemented.
  *
  * @wowlan: WoWLAN support information
+ * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.
  */
 struct wiphy {
 	/* assign these fields before you register the wiphy */
@@ -1811,6 +1834,8 @@
 
 	u32 flags;
 
+	u32 ap_sme_capa;
+
 	enum cfg80211_signal_type signal_type;
 
 	int bss_priv_size;
@@ -1838,6 +1863,13 @@
 	u32 available_antennas_tx;
 	u32 available_antennas_rx;
 
+	/*
+	* Bitmap of supported protocols for probe response offloading
+	* see &enum nl80211_probe_resp_offload_support_attr. Only valid
+	* when the wiphy flag @WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD is set.
+	*/
+	u32 probe_resp_offload;
+
 	/* If multiple wiphys are registered and you're handed e.g.
 	 * a regular netdev with assigned ieee80211_ptr, you won't
 	 * know whether it points to a wiphy your driver has registered
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index f71d743..782ee8d 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -992,6 +992,7 @@
 		struct asm_qcelp13_read_cfg qcelp13;
 		struct asm_sbc_read_cfg     sbc;
 		struct asm_amrwb_read_cfg   amrwb;
+		struct asm_multi_channel_pcm_fmt_blk      mpcm;
 	} __attribute__((packed)) cfg;
 };
 
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index c3d4bd5..aec4171 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -238,6 +238,9 @@
 int q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
 			uint32_t rate, uint32_t channels);
 
+int q6asm_enc_cfg_blk_multi_ch_pcm(struct audio_client *ac,
+			uint32_t rate, uint32_t channels);
+
 int q6asm_enable_sbrps(struct audio_client *ac,
 			uint32_t sbr_ps);
 
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 8d52423..f51b006 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -815,6 +815,7 @@
 	struct mutex mutex;
 	struct mutex dapm_mutex;
 	struct mutex dsp_mutex;
+	spinlock_t dsp_spinlock;
 
 	bool instantiated;
 
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 079f1d3..2169fee 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -343,7 +343,7 @@
 
 /* Look up a kernel symbol and return it in a text buffer. */
 static int __sprint_symbol(char *buffer, unsigned long address,
-			   int symbol_offset)
+			   int symbol_offset, int add_offset)
 {
 	char *modname;
 	const char *name;
@@ -358,13 +358,13 @@
 	if (name != buffer)
 		strcpy(buffer, name);
 	len = strlen(buffer);
-	buffer += len;
 	offset -= symbol_offset;
 
+	if (add_offset)
+		len += sprintf(buffer + len, "+%#lx/%#lx", offset, size);
+
 	if (modname)
-		len += sprintf(buffer, "+%#lx/%#lx [%s]", offset, size, modname);
-	else
-		len += sprintf(buffer, "+%#lx/%#lx", offset, size);
+		len += sprintf(buffer + len, " [%s]", modname);
 
 	return len;
 }
@@ -382,12 +382,28 @@
  */
 int sprint_symbol(char *buffer, unsigned long address)
 {
-	return __sprint_symbol(buffer, address, 0);
+	return __sprint_symbol(buffer, address, 0, 1);
 }
-
 EXPORT_SYMBOL_GPL(sprint_symbol);
 
 /**
+ * sprint_symbol_no_offset - Look up a kernel symbol and return it in a text buffer
+ * @buffer: buffer to be stored
+ * @address: address to lookup
+ *
+ * This function looks up a kernel symbol with @address and stores its name
+ * and module name to @buffer if possible. If no symbol was found, just saves
+ * its @address as is.
+ *
+ * This function returns the number of bytes stored in @buffer.
+ */
+int sprint_symbol_no_offset(char *buffer, unsigned long address)
+{
+	return __sprint_symbol(buffer, address, 0, 0);
+}
+EXPORT_SYMBOL_GPL(sprint_symbol_no_offset);
+
+/**
  * sprint_backtrace - Look up a backtrace symbol and return it in a text buffer
  * @buffer: buffer to be stored
  * @address: address to lookup
@@ -403,7 +419,7 @@
  */
 int sprint_backtrace(char *buffer, unsigned long address)
 {
-	return __sprint_symbol(buffer, address, -1);
+	return __sprint_symbol(buffer, address, -1, 1);
 }
 
 /* Look up a kernel symbol and print it to the kernel messages. */
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
index 4755b98..fb4e88d 100644
--- a/lib/spinlock_debug.c
+++ b/lib/spinlock_debug.c
@@ -61,7 +61,7 @@
 	printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n",
 		msg, raw_smp_processor_id(),
 		current->comm, task_pid_nr(current));
-	printk(KERN_EMERG " lock: %p, .magic: %08x, .owner: %s/%d, "
+	printk(KERN_EMERG " lock: %ps, .magic: %08x, .owner: %s/%d, "
 			".owner_cpu: %d\n",
 		lock, lock->magic,
 		owner ? owner->comm : "<none>",
@@ -114,7 +114,7 @@
 		if (print_once) {
 			print_once = 0;
 			printk(KERN_EMERG "BUG: spinlock lockup on CPU#%d, "
-					"%s/%d, %p\n",
+					"%s/%d, %ps\n",
 				raw_smp_processor_id(), current->comm,
 				task_pid_nr(current), lock);
 			dump_stack();
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 4365df3..44657bc 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -438,7 +438,7 @@
 	else if (ext != 'f' && ext != 's')
 		sprint_symbol(sym, value);
 	else
-		kallsyms_lookup(value, NULL, NULL, NULL, sym);
+		sprint_symbol_no_offset(sym, value);
 
 	return string(buf, end, sym, spec);
 #else
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index c0eb50c..8d51644 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1563,7 +1563,7 @@
 	list_del(&hdev->list);
 	write_unlock_bh(&hci_dev_list_lock);
 
-	hci_dev_do_close(hdev, 0);
+	hci_dev_do_close(hdev, hdev->bus == HCI_SMD);
 
 	for (i = 0; i < NUM_REASSEMBLY; i++)
 		kfree_skb(hdev->reassembly[i]);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 3b5ad95..37ee9b1 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5371,7 +5371,7 @@
 	release_sock(sk);
 }
 
-int l2cap_logical_link_complete(struct hci_chan *chan, u8 status)
+static void l2cap_logical_link_complete(struct hci_chan *chan, u8 status)
 {
 	struct l2cap_pinfo *pi;
 	struct sock *sk;
@@ -5385,11 +5385,14 @@
 
 	BT_DBG("sk %p", sk);
 
+	if (!sk)
+		return;
+
 	lock_sock(sk);
 
 	if (sk->sk_state != BT_CONNECTED && !l2cap_pi(sk)->amp_id) {
 		release_sock(sk);
-		return 0;
+		return;
 	}
 
 	pi = l2cap_pi(sk);
@@ -5516,7 +5519,6 @@
 	}
 
 	release_sock(sk);
-	return 0;
 }
 
 static void l2cap_logical_link_worker(struct work_struct *work)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 6a4a2f0..8eb1e16 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -505,8 +505,10 @@
 		memset(&sec, 0, sizeof(sec));
 		sec.level = l2cap_pi(sk)->sec_level;
 
-		if (sk->sk_state == BT_CONNECTED)
+		if (sk->sk_state == BT_CONNECTED) {
 			sec.key_size = l2cap_pi(sk)->conn->hcon->enc_key_size;
+			sec.level = l2cap_pi(sk)->conn->hcon->sec_level;
+		}
 
 		len = min_t(unsigned int, len, sizeof(sec));
 		if (copy_to_user(optval, (char *) &sec, len))
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 8b6f23e..e15609c 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1353,20 +1353,23 @@
 	if (!hdev)
 		return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	if (!test_bit(HCI_UP, &hdev->flags)) {
 		err = cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENETDOWN);
-		goto failed;
+		goto done;
 	}
 
-	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
-					&cp->bdaddr);
-	if (!conn)
-		return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENOTCONN);
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
+	if (!conn) {
+		err = cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENOTCONN);
+		goto done;
+	}
 
-	if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
-		return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, EINPROGRESS);
+	if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
+		err = cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, EINPROGRESS);
+		goto done;
+	}
 
 	if (conn->link_mode & HCI_LM_AUTH) {
 		enc.handle = cpu_to_le16(conn->handle);
@@ -1383,8 +1386,8 @@
 		}
 	}
 
-failed:
-	hci_dev_unlock(hdev);
+done:
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 2484a9a..31fc4dc 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -717,6 +717,7 @@
 	memset(&cp, 0, sizeof(cp));
 	build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
 
+	hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
 	hcon->preq[0] = SMP_CMD_PAIRING_REQ;
 	memcpy(&hcon->preq[1], &cp, sizeof(cp));
 
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 880dbe2..e921d00 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -488,6 +488,10 @@
 	int i;
 	u16 ifmodes = wiphy->interface_modes;
 
+	if (WARN_ON(wiphy->ap_sme_capa &&
+		!(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME)))
+		return -EINVAL;
+
 	if (WARN_ON(wiphy->addresses && !wiphy->n_addresses))
 		return -EINVAL;
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index bf6915b..e6457ff 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -718,6 +718,10 @@
 	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
 		    dev->wiphy.available_antennas_rx);
 
+	if (dev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD)
+		NLA_PUT_U32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD,
+			dev->wiphy.probe_resp_offload);
+
 	if ((dev->wiphy.available_antennas_tx ||
 	     dev->wiphy.available_antennas_rx) && dev->ops->get_antenna) {
 		u32 tx_ant = 0, rx_ant = 0;
@@ -954,6 +958,10 @@
 	if (nl80211_put_iface_combinations(&dev->wiphy, msg))
 		goto nla_put_failure;
 
+	if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME)
+		NLA_PUT_U32(msg, NL80211_ATTR_DEVICE_AP_SME,
+			dev->wiphy.ap_sme_capa);
+
 	return genlmsg_end(msg, hdr);
 
  nla_put_failure:
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 3229bce..1fe28a2 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -1474,6 +1474,8 @@
 	pr_err("%s %d\n", __func__, event);
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_RESET_CTL, 0x10,
+			0x00);
 		snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_CTL, 0x01,
 			0x01);
 		snd_soc_update_bits(codec, SITAR_A_CDC_CLSG_CTL, 0x08, 0x08);
@@ -1996,7 +1998,6 @@
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x05, 0x05);
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x02, 0x00);
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x04, 0x04);
-	snd_soc_update_bits(codec, SITAR_A_CDC_CLK_MCLK_CTL, 0x01, 0x01);
 	usleep_range(50, 50);
 	sitar->clock_active = true;
 	return 0;
@@ -2005,7 +2006,6 @@
 {
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
 	pr_err("%s\n", __func__);
-	snd_soc_update_bits(codec, SITAR_A_CDC_CLK_MCLK_CTL, 0x01, 0x00);
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x04, 0x00);
 	ndelay(160);
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x02, 0x02);
@@ -3962,6 +3962,9 @@
 	/*enable HPF filter for TX paths */
 	{SITAR_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
 	{SITAR_A_CDC_TX2_MUX_CTL, 0x8, 0x0},
+
+	/*enable External clock select*/
+	{SITAR_A_CDC_CLK_MCLK_CTL, 0x01, 0x01},
 };
 
 static void sitar_codec_init_reg(struct snd_soc_codec *codec)
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index 753ef2e..3d489ff 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -63,9 +63,14 @@
 	SLIM_1_RX_1 = 145, /* BT-SCO and USB TX */
 	SLIM_1_TX_1 = 146, /* BT-SCO and USB RX */
 	SLIM_2_RX_1 = 147, /* HDMI RX */
-	SLIM_3_RX_1 = 148, /* In-call recording RX */
-	SLIM_3_RX_2 = 149, /* In-call recording RX */
-	SLIM_4_TX_1 = 150, /* In-call musid delivery TX */
+	SLIM_4_TX_1 = 148, /* In-call recording RX */
+	SLIM_4_TX_2 = 149, /* In-call recording RX */
+	SLIM_4_RX_1 = 150, /* In-call music delivery TX */
+};
+
+enum {
+	INCALL_REC_MONO,
+	INCALL_REC_STEREO,
 };
 
 static u32 top_spk_pamp_gpio  = PM8921_GPIO_PM_TO_SYS(18);
@@ -79,6 +84,8 @@
 static int msm_btsco_rate = BTSCO_RATE_8KHZ;
 static int msm_btsco_ch = 1;
 
+static int rec_mode = INCALL_REC_MONO;
+
 static struct clk *codec_clk;
 static int clk_users;
 
@@ -611,6 +618,23 @@
 	return 0;
 }
 
+static int msm_incall_rec_mode_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = rec_mode;
+	return 0;
+}
+
+static int msm_incall_rec_mode_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+
+	rec_mode = ucontrol->value.integer.value[0];
+	pr_debug("%s: rec_mode:%d\n", __func__, rec_mode);
+
+	return 0;
+}
+
 static const struct snd_kcontrol_new tabla_msm_controls[] = {
 	SOC_ENUM_EXT("Speaker Function", msm_enum[0], msm_get_spk,
 		msm_set_spk),
@@ -625,6 +649,11 @@
 		msm_btsco_rate_get, msm_btsco_rate_put),
 };
 
+static const struct snd_kcontrol_new incall_rec_mode_mixer_controls[] = {
+	 SOC_SINGLE_EXT("Incall Rec Mode", SND_SOC_NOPM, 0, 1, 0,
+			msm_incall_rec_mode_get, msm_incall_rec_mode_put),
+};
+
 static int msm_btsco_init(struct snd_soc_pcm_runtime *rtd)
 {
 	int err = 0;
@@ -638,6 +667,19 @@
 	return 0;
 }
 
+static int msm_incall_rec_init(struct snd_soc_pcm_runtime *rtd)
+{
+	int err = 0;
+	struct snd_soc_platform *platform = rtd->platform;
+
+	err = snd_soc_add_platform_controls(platform,
+			incall_rec_mode_mixer_controls,
+		ARRAY_SIZE(incall_rec_mode_mixer_controls));
+	if (err < 0)
+		return err;
+	return 0;
+}
+
 static void *def_tabla_mbhc_cal(void)
 {
 	void *tabla_cal;
@@ -831,6 +873,49 @@
 	return ret;
 }
 
+static int msm_slimbus_4_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret = 0;
+	unsigned int rx_ch = SLIM_4_RX_1, tx_ch[2];
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		pr_debug("%s: APQ Incall Playback SLIMBUS_4_RX -> MDM TX shared ch %d\n",
+			__func__, rx_ch);
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0, 1, &rx_ch);
+		if (ret < 0) {
+			pr_err("%s: Erorr %d setting SLIM_4 RX channel map\n",
+				__func__, ret);
+
+		}
+	} else {
+		if (rec_mode == INCALL_REC_STEREO) {
+			tx_ch[0] = SLIM_4_TX_1;
+			tx_ch[1] = SLIM_4_TX_2;
+			ret = snd_soc_dai_set_channel_map(cpu_dai, 2,
+							tx_ch, 0, 0);
+		} else {
+			tx_ch[0] = SLIM_4_TX_1;
+			ret = snd_soc_dai_set_channel_map(cpu_dai, 1,
+							tx_ch, 0, 0);
+		}
+		pr_debug("%s: Incall Record shared tx_ch[0]:%d, tx_ch[1]:%d\n",
+			__func__, tx_ch[0], tx_ch[1]);
+
+		if (ret < 0) {
+			pr_err("%s: Erorr %d setting SLIM_4 TX channel map\n",
+				__func__, ret);
+
+		}
+	}
+
+	return ret;
+}
+
+
 static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
 {
 	int err;
@@ -1118,6 +1203,12 @@
 	.shutdown = msm_shutdown,
 };
 
+static struct snd_soc_ops msm_slimbus_4_be_ops = {
+	.startup = msm_startup,
+	.hw_params = msm_slimbus_4_hw_params,
+	.shutdown = msm_shutdown,
+};
+
 /* Digital audio interface glue - connects codec <---> CPU */
 static struct snd_soc_dai_link msm_dai[] = {
 	/* FrontEnd DAI Links */
@@ -1413,6 +1504,35 @@
 		.ops = &msm_be_ops,
 	},
 
+	/* Incall Music Back End DAI Link */
+	{
+		.name = LPASS_BE_SLIMBUS_4_RX,
+		.stream_name = "Slimbus4 Playback",
+		.cpu_dai_name = "msm-dai-q6.16392",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.no_codec = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_slimbus_4_be_ops,
+	},
+	/* Incall Record Back End DAI Link */
+	{
+		.name = LPASS_BE_SLIMBUS_4_TX,
+		.stream_name = "Slimbus4 Capture",
+		.cpu_dai_name = "msm-dai-q6.16393",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.no_codec = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.init = &msm_incall_rec_init,
+		.ops = &msm_slimbus_4_be_ops,
+	},
 };
 
 struct snd_soc_card snd_soc_card_msm = {
diff --git a/sound/soc/msm/mdm9615.c b/sound/soc/msm/mdm9615.c
index 758ad94..760f13d 100644
--- a/sound/soc/msm/mdm9615.c
+++ b/sound/soc/msm/mdm9615.c
@@ -1021,6 +1021,17 @@
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ignore_suspend = 1,
 	},
+	{
+		.name = "VoLTE",
+		.stream_name = "VoLTE",
+		.cpu_dai_name   = "VoLTE",
+		.platform_name  = "msm-pcm-voice",
+		.dynamic = 1,
+		.dsp_link = &fe_media,
+		.be_id = MSM_FRONTEND_DAI_VOLTE,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+	},
 	/* Backend BT DAI Links */
 	{
 		.name = LPASS_BE_INT_BT_SCO_RX,
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 14d9adf..3f86962 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -62,7 +62,7 @@
 			.rates = SNDRV_PCM_RATE_8000_48000,
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
-			.channels_max = 2,
+			.channels_max = 4,
 			.rate_min =     8000,
 			.rate_max =	48000,
 		},
@@ -293,6 +293,28 @@
 		.ops = &msm_fe_dai_ops,
 		.name = "VOICE_STUB",
 	},
+	{
+		.playback = {
+			.stream_name = "VoLTE Playback",
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 2,
+			.rate_min =     8000,
+			.rate_max =     48000,
+		},
+		.capture = {
+			.stream_name = "VoLTE Capture",
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 2,
+			.rate_min =     8000,
+			.rate_max =     48000,
+		},
+		.ops = &msm_fe_dai_ops,
+		.name = "VoLTE",
+	},
 };
 
 static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index e6d5012..a53dd44 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -388,6 +388,8 @@
 	case SLIMBUS_0_TX:
 	case SLIMBUS_1_TX:
 	case SLIMBUS_2_TX:
+	case SLIMBUS_4_RX:
+	case SLIMBUS_4_TX:
 		rc = msm_dai_q6_slim_bus_hw_params(params, dai,
 				substream->stream);
 		break;
@@ -885,6 +887,7 @@
 	switch (dai->id) {
 	case SLIMBUS_0_RX:
 	case SLIMBUS_1_RX:
+	case SLIMBUS_4_RX:
 		/* channel number to be between 128 and 255. For RX port
 		 * use channel numbers from 138 to 144, for TX port
 		 * use channel numbers from 128 to 137
@@ -909,7 +912,7 @@
 	case SLIMBUS_0_TX:
 	case SLIMBUS_1_TX:
 	case SLIMBUS_2_TX:
-
+	case SLIMBUS_4_TX:
 		/* channel number to be between 128 and 255. For RX port
 		 * use channel numbers from 138 to 144, for TX port
 		 * use channel numbers from 128 to 137
@@ -1004,7 +1007,7 @@
 		SNDRV_PCM_RATE_16000,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 		.channels_min = 1,
-		.channels_max = 2,
+		.channels_max = 4,
 		.rate_min =     8000,
 		.rate_max =	48000,
 	},
@@ -1245,10 +1248,12 @@
 					&msm_dai_q6_mi2s_rx_dai);
 		break;
 	case SLIMBUS_0_RX:
+	case SLIMBUS_4_RX:
 		rc = snd_soc_register_dai(&pdev->dev,
 				&msm_dai_q6_slimbus_rx_dai);
 		break;
 	case SLIMBUS_0_TX:
+	case SLIMBUS_4_TX:
 		rc = snd_soc_register_dai(&pdev->dev,
 				&msm_dai_q6_slimbus_tx_dai);
 		break;
diff --git a/sound/soc/msm/msm-pcm-q6.c b/sound/soc/msm/msm-pcm-q6.c
index dd194d6..4686386 100644
--- a/sound/soc/msm/msm-pcm-q6.c
+++ b/sound/soc/msm/msm-pcm-q6.c
@@ -55,7 +55,7 @@
 	.rate_min =             8000,
 	.rate_max =             48000,
 	.channels_min =         1,
-	.channels_max =         2,
+	.channels_max =         4,
 	.buffer_bytes_max =     CAPTURE_NUM_PERIODS * CAPTURE_PERIOD_SIZE,
 	.period_bytes_min =	CAPTURE_PERIOD_SIZE,
 	.period_bytes_max =     CAPTURE_PERIOD_SIZE,
@@ -248,8 +248,14 @@
 
 	pr_debug("Samp_rate = %d\n", prtd->samp_rate);
 	pr_debug("Channel = %d\n", prtd->channel_mode);
-	ret = q6asm_enc_cfg_blk_pcm(prtd->audio_client, prtd->samp_rate,
-					prtd->channel_mode);
+	if (prtd->channel_mode > 2) {
+		ret = q6asm_enc_cfg_blk_multi_ch_pcm(prtd->audio_client,
+		prtd->samp_rate, prtd->channel_mode);
+	} else {
+		ret = q6asm_enc_cfg_blk_pcm(prtd->audio_client,
+		prtd->samp_rate, prtd->channel_mode);
+	}
+
 	if (ret < 0)
 		pr_debug("%s: cmd cfg pcm was block failed", __func__);
 
@@ -331,13 +337,6 @@
 	/* Capture path */
 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
 		runtime->hw = msm_pcm_hardware_capture;
-		ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM);
-		if (ret < 0) {
-			pr_err("%s: pcm in open failed\n", __func__);
-			q6asm_audio_client_free(prtd->audio_client);
-			kfree(prtd);
-			return -ENOMEM;
-		}
 	}
 
 	pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
@@ -622,12 +621,28 @@
 	struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
 	struct audio_buffer *buf;
 	int dir, ret;
+	int format = FORMAT_LINEAR_PCM;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		dir = IN;
 	else
 		dir = OUT;
 
+	/*capture path*/
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		if (params_channels(params) > 2)
+			format = FORMAT_MULTI_CHANNEL_LINEAR_PCM;
+		pr_debug("%s format = :0x%x\n", __func__, format);
+
+		ret = q6asm_open_read(prtd->audio_client, format);
+		if (ret < 0) {
+			pr_err("%s: q6asm_open_read failed\n", __func__);
+			q6asm_audio_client_free(prtd->audio_client);
+			kfree(prtd);
+			return -ENOMEM;
+		}
+	}
+
 	ret = q6asm_audio_client_buf_alloc_contiguous(dir,
 			prtd->audio_client,
 			runtime->hw.period_bytes_min,
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 6bac324..0f74afb 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -131,6 +131,8 @@
 	{ SECONDARY_I2S_RX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_1_RX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_1_TX, 0, 0, 0, 0, 0},
+	{ SLIMBUS_4_RX, 0, 0, 0, 0, 0},
+	{ SLIMBUS_4_TX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_INVALID, 0, 0, 0, 0, 0},
 };
 
@@ -439,6 +441,8 @@
 
 	if (val == MSM_FRONTEND_DAI_CS_VOICE)
 		session_id = voc_get_session_id(VOICE_SESSION_NAME);
+	else if (val == MSM_FRONTEND_DAI_VOLTE)
+		session_id = voc_get_session_id(VOLTE_SESSION_NAME);
 	else
 		session_id = voc_get_session_id(VOIP_SESSION_NAME);
 
@@ -946,6 +950,15 @@
 	msm_routing_put_audio_mixer),
 };
 
+static const struct snd_kcontrol_new slimbus_4_rx_mixer_controls[] = {
+	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SLIMBUS_4_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SLIMBUS_4_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+
 static const struct snd_kcontrol_new int_bt_sco_rx_mixer_controls[] = {
 	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_INT_BT_SCO_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -1031,6 +1044,9 @@
 	SOC_SINGLE_EXT("VOC_REC_UL", MSM_BACKEND_DAI_INCALL_RECORD_TX,
 		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
 		msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("SLIM_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX,
+		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+		msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new mmul2_mixer_controls[] = {
@@ -1046,6 +1062,9 @@
 	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_PRI_I2S_RX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_PRI_I2S_RX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new sec_i2s_rx_voice_mixer_controls[] = {
@@ -1055,6 +1074,9 @@
 	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SEC_I2S_RX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new slimbus_rx_voice_mixer_controls[] = {
@@ -1064,6 +1086,9 @@
 	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new bt_sco_rx_voice_mixer_controls[] = {
@@ -1076,6 +1101,9 @@
 	SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_INT_BT_SCO_RX,
 	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
 	msm_routing_put_voice_stub_mixer),
+	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new afe_pcm_rx_voice_mixer_controls[] = {
@@ -1088,6 +1116,9 @@
 	SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_AFE_PCM_RX,
 	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
 	msm_routing_put_voice_stub_mixer),
+	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_AFE_PCM_RX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new aux_pcm_rx_voice_mixer_controls[] = {
@@ -1100,6 +1131,9 @@
 	SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_AUXPCM_RX,
 	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
 	msm_routing_put_voice_stub_mixer),
+	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_AUXPCM_RX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new hdmi_rx_voice_mixer_controls[] = {
@@ -1109,6 +1143,9 @@
 	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_HDMI_RX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new stub_rx_mixer_controls[] = {
@@ -1141,6 +1178,24 @@
 	msm_routing_put_voice_mixer),
 };
 
+static const struct snd_kcontrol_new tx_volte_mixer_controls[] = {
+	SOC_SINGLE_EXT("PRI_TX_VoLTE", MSM_BACKEND_DAI_PRI_I2S_TX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SLIM_0_TX_VoLTE", MSM_BACKEND_DAI_SLIMBUS_0_TX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_VoLTE",
+	MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_VOLTE, 1, 0,
+	msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("AFE_PCM_TX_VoLTE", MSM_BACKEND_DAI_AFE_PCM_TX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("AUX_PCM_TX_VoLTE", MSM_BACKEND_DAI_AUXPCM_TX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+};
+
 static const struct snd_kcontrol_new tx_voip_mixer_controls[] = {
 	SOC_SINGLE_EXT("PRI_TX_Voip", MSM_BACKEND_DAI_PRI_I2S_TX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
@@ -1432,6 +1487,8 @@
 	SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("VoLTE_DL", "VoLTE Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("VoLTE_UL", "VoLTE Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("VOIP_UL", "VoIP Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("SLIM0_DL_HL", "SLIMBUS0_HOSTLESS Playback",
 		0, 0, 0, 0),
@@ -1473,10 +1530,15 @@
 	/* incall */
 	SND_SOC_DAPM_AIF_OUT("VOICE_PLAYBACK_TX", "Voice Farend Playback",
 				0, 0, 0 , 0),
+	SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_RX", "Slimbus4 Playback",
+				0, 0, 0 , 0),
 	SND_SOC_DAPM_AIF_IN("INCALL_RECORD_TX", "Voice Uplink Capture",
 				0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("INCALL_RECORD_RX", "Voice Downlink Capture",
 				0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("SLIMBUS_4_TX", "Slimbus4 Capture",
+				0, 0, 0, 0),
+
 	SND_SOC_DAPM_AIF_OUT("AUX_PCM_RX", "AUX PCM Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("AUX_PCM_TX", "AUX PCM Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("VOICE_STUB_DL", "VOICE_STUB Playback", 0, 0, 0, 0),
@@ -1512,6 +1574,9 @@
 	SND_SOC_DAPM_MIXER("Incall_Music Audio Mixer", SND_SOC_NOPM, 0, 0,
 			incall_music_delivery_mixer_controls,
 			ARRAY_SIZE(incall_music_delivery_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SLIMBUS_4_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
+			slimbus_4_rx_mixer_controls,
+			ARRAY_SIZE(slimbus_4_rx_mixer_controls)),
 	/* Voice Mixer */
 	SND_SOC_DAPM_MIXER("PRI_RX_Voice Mixer",
 				SND_SOC_NOPM, 0, 0, pri_rx_voice_mixer_controls,
@@ -1546,6 +1611,9 @@
 	SND_SOC_DAPM_MIXER("Voip_Tx Mixer",
 				SND_SOC_NOPM, 0, 0, tx_voip_mixer_controls,
 				ARRAY_SIZE(tx_voip_mixer_controls)),
+	SND_SOC_DAPM_MIXER("VoLTE_Tx Mixer",
+				SND_SOC_NOPM, 0, 0, tx_volte_mixer_controls,
+				ARRAY_SIZE(tx_volte_mixer_controls)),
 	SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 	int_bt_sco_rx_mixer_controls, ARRAY_SIZE(int_bt_sco_rx_mixer_controls)),
 	SND_SOC_DAPM_MIXER("INTERNAL_FM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
@@ -1604,9 +1672,13 @@
 	{"Incall_Music Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"Incall_Music Audio Mixer", "MultiMedia2", "MM_DL2"},
 	{"VOICE_PLAYBACK_TX", NULL, "Incall_Music Audio Mixer"},
+	{"SLIMBUS_4_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
+	{"SLIMBUS_4_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
+	{"SLIMBUS_4_RX", NULL, "SLIMBUS_4_RX Audio Mixer"},
 
 	{"MultiMedia1 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
 	{"MultiMedia1 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
+	{"MultiMedia1 Mixer", "SLIM_4_TX", "SLIMBUS_4_TX"},
 	{"MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
 	{"MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
@@ -1650,30 +1722,37 @@
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
 
 	{"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"PRI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"PRI_I2S_RX", NULL, "PRI_RX_Voice Mixer"},
 
 	{"SEC_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"SEC_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"SEC_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"SEC_I2S_RX", NULL, "SEC_RX_Voice Mixer"},
 
 	{"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"SLIM_0_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
 
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"INTERNAL_BT_SCO_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
 
 	{"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"AFE_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"AFE_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"PCM_RX", NULL, "AFE_PCM_RX_Voice Mixer"},
 
 	{"AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"AUX_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
 
 	{"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"HDMI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"HDMI_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"HDMI", NULL, "HDMI_RX_Voice Mixer"},
 	{"HDMI", NULL, "HDMI_DL_HL"},
@@ -1684,6 +1763,12 @@
 	{"Voice_Tx Mixer", "AFE_PCM_TX_Voice", "PCM_TX"},
 	{"Voice_Tx Mixer", "AUX_PCM_TX_Voice", "AUX_PCM_TX"},
 	{"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
+	{"VoLTE_Tx Mixer", "PRI_TX_VoLTE", "PRI_I2S_TX"},
+	{"VoLTE_Tx Mixer", "SLIM_0_TX_VoLTE", "SLIMBUS_0_TX"},
+	{"VoLTE_Tx Mixer", "INTERNAL_BT_SCO_TX_VoLTE", "INT_BT_SCO_TX"},
+	{"VoLTE_Tx Mixer", "AFE_PCM_TX_VoLTE", "PCM_TX"},
+	{"VoLTE_Tx Mixer", "AUX_PCM_TX_VoLTE", "AUX_PCM_TX"},
+	{"VoLTE_UL", NULL, "VoLTE_Tx Mixer"},
 	{"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"},
 	{"Voip_Tx Mixer", "SLIM_0_TX_Voip", "SLIMBUS_0_TX"},
 	{"Voip_Tx Mixer", "INTERNAL_BT_SCO_TX_Voip", "INT_BT_SCO_TX"},
@@ -1816,8 +1901,9 @@
 		if (fe_dai_map[i][session_type] != INVALID_SESSION) {
 
 			channels = bedai->channel;
-			if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
-				(channels > 2))
+			if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+				substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+				&& (channels > 2))
 				adm_multi_ch_copp_open(bedai->port_id,
 				path_type,
 				bedai->sample_rate,
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index eb6db4b..e5d8638 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -37,6 +37,9 @@
 #define LPASS_BE_SLIMBUS_1_RX "(Backend) SLIMBUS_1_RX"
 #define LPASS_BE_SLIMBUS_1_TX "(Backend) SLIMBUS_1_TX"
 
+#define LPASS_BE_SLIMBUS_4_RX "(Backend) SLIMBUS_4_RX"
+#define LPASS_BE_SLIMBUS_4_TX "(Backend) SLIMBUS_4_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
@@ -53,6 +56,7 @@
 	MSM_FRONTEND_DAI_AFE_RX,
 	MSM_FRONTEND_DAI_AFE_TX,
 	MSM_FRONTEND_DAI_VOICE_STUB,
+	MSM_FRONTEND_DAI_VOLTE,
 	MSM_FRONTEND_DAI_MAX,
 };
 
@@ -80,6 +84,8 @@
 	MSM_BACKEND_DAI_SEC_I2S_RX,
 	MSM_BACKEND_DAI_SLIMBUS_1_RX,
 	MSM_BACKEND_DAI_SLIMBUS_1_TX,
+	MSM_BACKEND_DAI_SLIMBUS_4_RX,
+	MSM_BACKEND_DAI_SLIMBUS_4_TX,
 	MSM_BACKEND_DAI_INVALID,
 	MSM_BACKEND_DAI_MAX,
 };
diff --git a/sound/soc/msm/msm-pcm-voice.c b/sound/soc/msm/msm-pcm-voice.c
index 5a0f27a..59b8bbd 100644
--- a/sound/soc/msm/msm-pcm-voice.c
+++ b/sound/soc/msm/msm-pcm-voice.c
@@ -29,7 +29,7 @@
 #include "msm-pcm-voice.h"
 #include "qdsp6/q6voice.h"
 
-static struct msm_voice voice_info;
+static struct msm_voice voice_info[VOICE_SESSION_INDEX_MAX];
 
 static struct snd_pcm_hardware msm_pcm_hardware = {
 
@@ -49,6 +49,13 @@
 
 	.fifo_size =            0,
 };
+static int is_volte(struct msm_voice *pvolte)
+{
+	if (pvolte == &voice_info[VOLTE_SESSION_INDEX])
+		return true;
+	else
+		return false;
+}
 
 static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
 {
@@ -78,8 +85,17 @@
 static int msm_pcm_open(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct msm_voice *voice = &voice_info;
+	struct msm_voice *voice;
 
+	if (!strncmp("VoLTE", substream->pcm->id, 5)) {
+		voice = &voice_info[VOLTE_SESSION_INDEX];
+		pr_debug("%s: Open VoLTE Substream Id=%s\n",
+				__func__, substream->pcm->id);
+	} else {
+		voice = &voice_info[VOICE_SESSION_INDEX];
+		pr_debug("%s: Open VOICE Substream Id=%s\n",
+				__func__, substream->pcm->id);
+	}
 	mutex_lock(&voice->lock);
 
 	runtime->hw = msm_pcm_hardware;
@@ -90,7 +106,8 @@
 		voice->capture_substream = substream;
 
 	voice->instance++;
-	pr_debug(" %s: instance: %d\n", __func__ , voice->instance);
+	pr_debug("%s: Instance = %d, Stream ID = %s\n",
+			__func__ , voice->instance, substream->pcm->id);
 	runtime->private_data = voice;
 
 	mutex_unlock(&voice->lock);
@@ -129,6 +146,7 @@
 
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct msm_voice *prtd = runtime->private_data;
+	uint16_t session_id = 0;
 	int ret = 0;
 
 	mutex_lock(&prtd->lock);
@@ -140,7 +158,11 @@
 	prtd->instance--;
 	if (!prtd->playback_start && !prtd->capture_start) {
 		pr_debug("end voice call\n");
-		voc_end_voice_call(voc_get_session_id(VOICE_SESSION_NAME));
+		if (is_volte(prtd))
+			session_id = voc_get_session_id(VOLTE_SESSION_NAME);
+		else
+			session_id = voc_get_session_id(VOICE_SESSION_NAME);
+		voc_end_voice_call(session_id);
 	}
 	mutex_unlock(&prtd->lock);
 
@@ -151,6 +173,7 @@
 	int ret = 0;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct msm_voice *prtd = runtime->private_data;
+	uint16_t session_id = 0;
 
 	mutex_lock(&prtd->lock);
 
@@ -159,9 +182,13 @@
 	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 		ret = msm_pcm_capture_prepare(substream);
 
-	if (prtd->playback_start && prtd->capture_start)
-		voc_start_voice_call(voc_get_session_id(VOICE_SESSION_NAME));
-
+	if (prtd->playback_start && prtd->capture_start) {
+		if (is_volte(prtd))
+			session_id = voc_get_session_id(VOLTE_SESSION_NAME);
+		else
+			session_id = voc_get_session_id(VOICE_SESSION_NAME);
+		voc_start_voice_call(session_id);
+	}
 	mutex_unlock(&prtd->lock);
 
 	return ret;
@@ -189,12 +216,26 @@
 				struct snd_ctl_elem_value *ucontrol)
 {
 	int volume = ucontrol->value.integer.value[0];
-
 	pr_debug("%s: volume: %d\n", __func__, volume);
-
 	voc_set_rx_vol_index(voc_get_session_id(VOICE_SESSION_NAME),
-			     RX_PATH,
-			     volume);
+						RX_PATH, volume);
+	return 0;
+}
+
+static int msm_volte_volume_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = 0;
+	return 0;
+}
+
+static int msm_volte_volume_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int volume = ucontrol->value.integer.value[0];
+	pr_debug("%s: volume: %d\n", __func__, volume);
+	voc_set_rx_vol_index(voc_get_session_id(VOLTE_SESSION_NAME),
+						RX_PATH, volume);
 	return 0;
 }
 
@@ -217,6 +258,25 @@
 	return 0;
 }
 
+static int msm_volte_mute_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = 0;
+	return 0;
+}
+
+static int msm_volte_mute_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int mute = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: mute=%d\n", __func__, mute);
+
+	voc_set_tx_mute(voc_get_session_id(VOLTE_SESSION_NAME), TX_PATH, mute);
+
+	return 0;
+}
+
 static int msm_voice_rx_device_mute_get(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
@@ -237,6 +297,26 @@
 	return 0;
 }
 
+static int msm_volte_rx_device_mute_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] =
+		voc_get_rx_device_mute(voc_get_session_id(VOLTE_SESSION_NAME));
+	return 0;
+}
+
+static int msm_volte_rx_device_mute_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int mute = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: mute=%d\n", __func__, mute);
+
+	voc_set_rx_device_mute(voc_get_session_id(VOLTE_SESSION_NAME), mute);
+
+	return 0;
+}
+
 static const char const *tty_mode[] = {"OFF", "HCO", "VCO", "FULL"};
 static const struct soc_enum msm_tty_mode_enum[] = {
 		SOC_ENUM_SINGLE_EXT(4, tty_mode),
@@ -343,6 +423,13 @@
 				msm_voice_slowtalk_get, msm_voice_slowtalk_put),
 	SOC_SINGLE_EXT("FENS Enable", SND_SOC_NOPM, 0, 1, 0,
 				msm_voice_fens_get, msm_voice_fens_put),
+	SOC_SINGLE_EXT("VoLTE Rx Device Mute", SND_SOC_NOPM, 0, 1, 0,
+			msm_volte_rx_device_mute_get,
+			msm_volte_rx_device_mute_put),
+	SOC_SINGLE_EXT("VoLTE Tx Mute", SND_SOC_NOPM, 0, 1, 0,
+				msm_volte_mute_get, msm_volte_mute_put),
+	SOC_SINGLE_EXT("VoLTE Rx Volume", SND_SOC_NOPM, 0, 5, 0,
+				msm_volte_volume_get, msm_volte_volume_put),
 };
 
 static struct snd_pcm_ops msm_pcm_ops = {
@@ -402,7 +489,8 @@
 static int __init msm_soc_platform_init(void)
 {
 	memset(&voice_info, 0, sizeof(voice_info));
-	mutex_init(&voice_info.lock);
+	mutex_init(&voice_info[VOICE_SESSION_INDEX].lock);
+	mutex_init(&voice_info[VOLTE_SESSION_INDEX].lock);
 
 	return platform_driver_register(&msm_pcm_driver);
 }
diff --git a/sound/soc/msm/msm-pcm-voice.h b/sound/soc/msm/msm-pcm-voice.h
index 71bdbc1..aa00577 100644
--- a/sound/soc/msm/msm-pcm-voice.h
+++ b/sound/soc/msm/msm-pcm-voice.h
@@ -13,6 +13,11 @@
 #define _MSM_PCM_VOICE_H
 #include <sound/apr_audio.h>
 
+enum {
+	VOICE_SESSION_INDEX,
+	VOLTE_SESSION_INDEX,
+	VOICE_SESSION_INDEX_MAX,
+};
 
 struct msm_voice {
 	struct snd_pcm_substream *playback_substream;
diff --git a/sound/soc/msm/msm-pcm-voip.c b/sound/soc/msm/msm-pcm-voip.c
index aec1bb2..570d71c 100644
--- a/sound/soc/msm/msm-pcm-voip.c
+++ b/sound/soc/msm/msm-pcm-voip.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* 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
@@ -37,6 +37,9 @@
 /* Length of the DSP frame info header added to the voc packet. */
 #define DSP_FRAME_HDR_LEN 1
 
+#define MODE_IS127		0x2
+#define MODE_4GV_NB		0x3
+#define MODE_4GV_WB		0x4
 #define MODE_AMR		0x5
 #define MODE_AMR_WB		0xD
 #define MODE_PCM		0xC
@@ -74,7 +77,10 @@
 };
 
 struct voip_frame {
+	union {
 	uint32_t frame_type;
+	uint32_t packet_rate;
+	} header;
 	uint32_t len;
 	uint8_t voc_pkt[VOIP_MAX_VOC_PKT_SIZE];
 };
@@ -276,7 +282,8 @@
 			 * Bits 0-3: Frame rate
 			 * Bits 4-7: Frame type
 			 */
-			buf_node->frame.frame_type = ((*voc_pkt) & 0xF0) >> 4;
+			buf_node->frame.header.frame_type =
+						((*voc_pkt) & 0xF0) >> 4;
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 			buf_node->frame.len = pkt_len - DSP_FRAME_HDR_LEN;
 			memcpy(&buf_node->frame.voc_pkt[0],
@@ -285,6 +292,24 @@
 			list_add_tail(&buf_node->list, &prtd->out_queue);
 			break;
 		}
+		case MODE_IS127:
+		case MODE_4GV_NB:
+		case MODE_4GV_WB: {
+			/* Remove the DSP frame info header.
+			 * Header format:
+			 * Bits 0-3: frame rate
+			 */
+			buf_node->frame.header.packet_rate = (*voc_pkt) & 0x0F;
+			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
+			buf_node->frame.len = pkt_len - DSP_FRAME_HDR_LEN;
+
+			memcpy(&buf_node->frame.voc_pkt[0],
+				voc_pkt,
+				buf_node->frame.len);
+
+			list_add_tail(&buf_node->list, &prtd->out_queue);
+			break;
+		}
 		default: {
 			buf_node->frame.len = pkt_len;
 			memcpy(&buf_node->frame.voc_pkt[0],
@@ -332,8 +357,8 @@
 			 * Bits 0-3: Frame rate
 			 * Bits 4-7: Frame type
 			 */
-			*voc_pkt = ((buf_node->frame.frame_type & 0x0F) << 4) |
-					(prtd->rate_type & 0x0F);
+			*voc_pkt = ((buf_node->frame.header.frame_type &
+					0x0F) << 4) | (prtd->rate_type & 0x0F);
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 			*pkt_len = buf_node->frame.len + DSP_FRAME_HDR_LEN;
 			memcpy(voc_pkt,
@@ -342,6 +367,23 @@
 			list_add_tail(&buf_node->list, &prtd->free_in_queue);
 			break;
 		}
+		case MODE_IS127:
+		case MODE_4GV_NB:
+		case MODE_4GV_WB: {
+			/* Add the DSP frame info header. Header format:
+			 * Bits 0-3 : Frame rate
+			*/
+			*voc_pkt = buf_node->frame.header.packet_rate & 0x0F;
+			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
+			*pkt_len = buf_node->frame.len + DSP_FRAME_HDR_LEN;
+
+			memcpy(voc_pkt,
+				&buf_node->frame.voc_pkt[0],
+				buf_node->frame.len);
+
+			list_add_tail(&buf_node->list, &prtd->free_in_queue);
+			break;
+		}
 		default: {
 			*pkt_len = buf_node->frame.len;
 
@@ -691,7 +733,7 @@
 	int ret = 0;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct voip_drv_info *prtd = runtime->private_data;
-	int32_t media_type = 0;
+	uint32_t media_type = 0;
 	uint32_t rate_type = 0;
 
 	mutex_lock(&prtd->lock);
@@ -702,7 +744,9 @@
 		ret = msm_pcm_capture_prepare(substream);
 
 	if ((runtime->format != FORMAT_SPECIAL) &&
-		 ((prtd->mode == MODE_AMR) || (prtd->mode == MODE_AMR_WB))) {
+		 ((prtd->mode == MODE_AMR) || (prtd->mode == MODE_AMR_WB) ||
+		 (prtd->mode == MODE_IS127) || (prtd->mode == MODE_4GV_NB) ||
+		 (prtd->mode == MODE_4GV_WB))) {
 		pr_err("mode:%d and format:%u are not mached\n",
 			prtd->mode, (uint32_t)runtime->format);
 		ret =  -EINVAL;
@@ -976,6 +1020,24 @@
 		*rate_type = 0;
 		break;
 	}
+	case MODE_IS127:
+	case MODE_4GV_NB:
+	case MODE_4GV_WB: {
+		switch (rate) {
+		case VOC_0_RATE:
+		case VOC_8_RATE:
+		case VOC_4_RATE:
+		case VOC_2_RATE:
+		case VOC_1_RATE:
+			*rate_type = rate;
+			break;
+		default:
+			pr_err("wrong rate for IS127/4GV_NB/WB.\n");
+			ret = -EINVAL;
+			break;
+		}
+		break;
+	}
 	default:
 		pr_err("wrong mode type.\n");
 		ret = -EINVAL;
@@ -988,7 +1050,7 @@
 static int voip_get_media_type(uint32_t mode,
 				unsigned int samp_rate)
 {
-	int32_t media_type;
+	uint32_t media_type;
 
 	pr_debug("%s: mode=%d, samp_rate=%d\n", __func__,
 		mode, samp_rate);
@@ -1005,6 +1067,15 @@
 		else
 			media_type = VSS_MEDIA_ID_PCM_WB;
 		break;
+	case MODE_IS127: /* EVRC-A */
+		media_type = VSS_MEDIA_ID_EVRC_MODEM;
+		break;
+	case MODE_4GV_NB: /* EVRC-B */
+		media_type = VSS_MEDIA_ID_4GV_NB_MODEM;
+		break;
+	case MODE_4GV_WB: /* EVRC-WB */
+		media_type = VSS_MEDIA_ID_4GV_WB_MODEM;
+		break;
 	default:
 		pr_debug(" input mode is not supported\n");
 		media_type = -EINVAL;
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index e254cce..04b0fb0 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -129,8 +129,8 @@
 		if (!clk_users) {
 			pr_debug("%s: disabling MCLK. clk_users = %d\n",
 					 __func__, clk_users);
-			clk_disable_unprepare(codec_clk);
 			sitar_mclk_enable(codec, 0);
+			clk_disable_unprepare(codec_clk);
 		}
 	}
 	return 0;
@@ -520,9 +520,6 @@
 	}
 	codec_clk = clk_get(cpu_dai->dev, "osr_clk");
 
-	sitar_hs_detect(codec, &hs_jack, &button_jack, sitar_mbhc_cal,
-			SITAR_MICBIAS2, msm8930_enable_codec_ext_clk, 0,
-			SITAR_EXT_CLK_RATE);
 	return 0;
 }
 
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index de98aa3..abfadb8 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1175,6 +1175,17 @@
 		.no_codec = 1,
 		.ignore_suspend = 1,
 	},
+	{
+		.name = "VoLTE",
+		.stream_name = "VoLTE",
+		.cpu_dai_name   = "VoLTE",
+		.platform_name  = "msm-pcm-voice",
+		.dynamic = 1,
+		.dsp_link = &fe_media,
+		.be_id = MSM_FRONTEND_DAI_VOLTE,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+	},
 	/* Backend BT/FM DAI Links */
 	{
 		.name = LPASS_BE_INT_BT_SCO_RX,
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index bc5c007..676ecf1 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -143,14 +143,14 @@
 	s32				result = 0;
 	struct adm_set_params_command	adm_params;
 	int index = afe_get_port_index(port_id);
-
-	pr_debug("%s: Port id %d, index %d\n", __func__, port_id, index);
-
 	if (index < 0 || index >= AFE_MAX_PORTS) {
 		pr_err("%s: invalid port idx %d portid %d\n",
 				__func__, index, port_id);
-		goto done;
+		return 0;
 	}
+
+	pr_debug("%s: Port id %d, index %d\n", __func__, port_id, index);
+
 	if (!aud_cal || aud_cal->cal_size == 0) {
 		pr_debug("%s: No ADM cal to send for port_id = %d!\n",
 			__func__, port_id);
@@ -489,6 +489,11 @@
 		} else if (channel_mode == 2) {
 			open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
 			open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+		} else if (channel_mode == 4) {
+			open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+			open.dev_channel_mapping[2] = PCM_CHANNEL_RB;
+			open.dev_channel_mapping[3] = PCM_CHANNEL_LB;
 		} else if (channel_mode == 6) {
 			open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
 			open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
@@ -575,16 +580,15 @@
 	int ret = 0, i = 0;
 	/* Assumes port_ids have already been validated during adm_open */
 	int index = afe_get_port_index(copp_id);
+	if (index < 0 || index >= AFE_MAX_PORTS) {
+		pr_err("%s: invalid port idx %d token %d\n",
+					__func__, index, copp_id);
+		return 0;
+	}
 
 	pr_debug("%s: session 0x%x path:%d num_copps:%d port_id[0]:%d\n",
 		 __func__, session_id, path, num_copps, port_id[0]);
 
-	if (index < 0 || index >= AFE_MAX_PORTS) {
-		pr_err("%s: invalid port idx %d token %d\n",
-					__func__, index, copp_id);
-		ret = -EINVAL;
-		goto fail_cmd;
-	}
 	route.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
 	route.hdr.pkt_size = sizeof(route);
@@ -609,7 +613,7 @@
 		pr_debug("%s: port_id[%d]: %d, index: %d\n", __func__, i,
 			 port_id[i], tmp);
 
-		if ((tmp >= 0) && (tmp < AFE_MAX_PORTS))
+		if (tmp >= 0 && tmp < AFE_MAX_PORTS)
 			route.session[0].copp_id[i] =
 					atomic_read(&this_adm.copp_id[tmp]);
 	}
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index f474542..dc120b08 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -152,6 +152,7 @@
 	case INT_FM_RX:
 	case VOICE_PLAYBACK_TX:
 	case RT_PROXY_PORT_001_RX:
+	case SLIMBUS_4_RX:
 		ret = MSM_AFE_PORT_TYPE_RX;
 		break;
 
@@ -168,6 +169,7 @@
 	case VOICE_RECORD_RX:
 	case INT_BT_SCO_TX:
 	case RT_PROXY_PORT_001_TX:
+	case SLIMBUS_4_TX:
 		ret = MSM_AFE_PORT_TYPE_TX;
 		break;
 
@@ -211,6 +213,8 @@
 	case INT_FM_TX:
 	case RT_PROXY_PORT_001_RX:
 	case RT_PROXY_PORT_001_TX:
+	case SLIMBUS_4_RX:
+	case SLIMBUS_4_TX:
 	{
 		ret = 0;
 		break;
@@ -274,6 +278,8 @@
 	case INT_FM_TX: return IDX_INT_FM_TX;
 	case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
 	case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
+	case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
+	case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
 
 	default: return -EINVAL;
 	}
@@ -299,6 +305,8 @@
 	case SLIMBUS_1_RX:
 	case SLIMBUS_1_TX:
 	case SLIMBUS_2_TX:
+	case SLIMBUS_4_RX:
+	case SLIMBUS_4_TX:
 		ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_sch_cfg);
 		break;
 	case RT_PROXY_PORT_001_RX:
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index c7ebd2c..f3a2383 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -1228,6 +1228,10 @@
 		open.uMode = STREAM_PRIORITY_HIGH;
 		open.format = LINEAR_PCM;
 		break;
+	case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
+		open.uMode = STREAM_PRIORITY_HIGH;
+		open.format = MULTI_CHANNEL_PCM;
+		break;
 	case FORMAT_MPEG4_AAC:
 		open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
 		open.format = MPEG4_AAC;
@@ -1664,6 +1668,56 @@
 	return -EINVAL;
 }
 
+int q6asm_enc_cfg_blk_multi_ch_pcm(struct audio_client *ac,
+			uint32_t rate, uint32_t channels)
+{
+	struct asm_stream_cmd_encdec_cfg_blk  enc_cfg;
+
+	int rc = 0;
+
+	pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__,
+			 ac->session, rate, channels);
+
+	q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
+
+	enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
+	enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
+	enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
+	enc_cfg.enc_blk.frames_per_buf = 1;
+	enc_cfg.enc_blk.format_id = MULTI_CHANNEL_PCM;
+	enc_cfg.enc_blk.cfg_size =
+		sizeof(struct asm_multi_channel_pcm_fmt_blk);
+	enc_cfg.enc_blk.cfg.mpcm.num_channels = channels;
+	enc_cfg.enc_blk.cfg.mpcm.bits_per_sample = 16;
+	enc_cfg.enc_blk.cfg.mpcm.sample_rate = rate;
+	enc_cfg.enc_blk.cfg.mpcm.is_signed = 1;
+	enc_cfg.enc_blk.cfg.mpcm.is_interleaved = 1;
+	enc_cfg.enc_blk.cfg.mpcm.channel_mapping[0] = PCM_CHANNEL_FL;
+	enc_cfg.enc_blk.cfg.mpcm.channel_mapping[1] = PCM_CHANNEL_FR;
+	enc_cfg.enc_blk.cfg.mpcm.channel_mapping[2] = PCM_CHANNEL_RB;
+	enc_cfg.enc_blk.cfg.mpcm.channel_mapping[3] = PCM_CHANNEL_LB;
+	enc_cfg.enc_blk.cfg.mpcm.channel_mapping[4] = 0;
+	enc_cfg.enc_blk.cfg.mpcm.channel_mapping[5] = 0;
+	enc_cfg.enc_blk.cfg.mpcm.channel_mapping[6] = 0;
+	enc_cfg.enc_blk.cfg.mpcm.channel_mapping[7] = 0;
+
+	rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
+	if (rc < 0) {
+		pr_err("Comamnd open failed\n");
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(ac->cmd_wait,
+			(atomic_read(&ac->cmd_state) == 0), 5*HZ);
+	if (!rc) {
+		pr_err("timeout opcode[0x%x] ", enc_cfg.hdr.opcode);
+		goto fail_cmd;
+	}
+	return 0;
+fail_cmd:
+	return -EINVAL;
+}
+
 int q6asm_enable_sbrps(struct audio_client *ac,
 			uint32_t sbr_ps_enable)
 {
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 6050929..f4b4dd1 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -33,6 +33,7 @@
 
 #define VOC_PATH_PASSIVE 0
 #define VOC_PATH_FULL 1
+#define VOC_PATH_VOLTE_PASSIVE 2
 
 /* CVP CAL Size: 245760 = 240 * 1024 */
 #define CVP_CAL_SIZE 245760
@@ -145,6 +146,9 @@
 	if (name != NULL) {
 		if (!strncmp(name, "Voice session", 13))
 			session_id = common.voice[VOC_PATH_PASSIVE].session_id;
+		else if (!strncmp(name, "VoLTE session", 13))
+			session_id =
+			common.voice[VOC_PATH_VOLTE_PASSIVE].session_id;
 		else
 			session_id = common.voice[VOC_PATH_FULL].session_id;
 
@@ -180,6 +184,11 @@
 	return (session_id == common.voice[VOC_PATH_FULL].session_id);
 }
 
+static bool is_volte_session(u16 session_id)
+{
+	return (session_id == common.voice[VOC_PATH_VOLTE_PASSIVE].session_id);
+}
+
 static int voice_apr_register(void)
 {
 	pr_debug("%s\n", __func__);
@@ -250,6 +259,65 @@
 	return -ENODEV;
 }
 
+static int voice_send_dual_control_cmd(struct voice_data *v)
+{
+	int ret = 0;
+	struct mvm_modem_dual_control_session_cmd mvm_voice_ctl_cmd;
+	void *apr_mvm;
+	u16 mvm_handle;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		return -EINVAL;
+	}
+	apr_mvm = common.apr_q6_mvm;
+	if (!apr_mvm) {
+		pr_err("%s: apr_mvm is NULL.\n", __func__);
+		return -EINVAL;
+	}
+	pr_debug("%s: VoLTE command to MVM\n", __func__);
+	if (is_volte_session(v->session_id)) {
+		mvm_handle = voice_get_mvm_handle(v);
+		mvm_voice_ctl_cmd.hdr.hdr_field = APR_HDR_FIELD(
+						APR_MSG_TYPE_SEQ_CMD,
+						APR_HDR_LEN(APR_HDR_SIZE),
+						APR_PKT_VER);
+		mvm_voice_ctl_cmd.hdr.pkt_size = APR_PKT_SIZE(
+						APR_HDR_SIZE,
+						sizeof(mvm_voice_ctl_cmd) -
+						APR_HDR_SIZE);
+		pr_debug("%s: send mvm Voice Ctl pkt size = %d\n",
+			__func__, mvm_voice_ctl_cmd.hdr.pkt_size);
+		mvm_voice_ctl_cmd.hdr.src_port = v->session_id;
+		mvm_voice_ctl_cmd.hdr.dest_port = mvm_handle;
+		mvm_voice_ctl_cmd.hdr.token = 0;
+		mvm_voice_ctl_cmd.hdr.opcode =
+					VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL;
+		mvm_voice_ctl_cmd.voice_ctl.enable_flag = true;
+		v->mvm_state = CMD_STATUS_FAIL;
+
+		ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_voice_ctl_cmd);
+		if (ret < 0) {
+			pr_err("%s: Error sending MVM Voice CTL CMD\n",
+							__func__);
+			ret = -EINVAL;
+			goto fail;
+		}
+		ret = wait_event_timeout(v->mvm_wait,
+				(v->mvm_state == CMD_STATUS_SUCCESS),
+				msecs_to_jiffies(TIMEOUT_MS));
+		if (!ret) {
+			pr_err("%s: wait_event timeout\n", __func__);
+			ret = -EINVAL;
+			goto fail;
+		}
+	}
+	ret = 0;
+fail:
+	return ret;
+}
+
+
 static int voice_create_mvm_cvs_session(struct voice_data *v)
 {
 	int ret = 0;
@@ -281,7 +349,8 @@
 	/* send cmd to create mvm session and wait for response */
 
 	if (!mvm_handle) {
-		if (is_voice_session(v->session_id)) {
+		if (is_voice_session(v->session_id) ||
+				is_volte_session(v->session_id)) {
 			mvm_session_cmd.hdr.hdr_field = APR_HDR_FIELD(
 						APR_MSG_TYPE_SEQ_CMD,
 						APR_HDR_LEN(APR_HDR_SIZE),
@@ -297,9 +366,15 @@
 			mvm_session_cmd.hdr.token = 0;
 			mvm_session_cmd.hdr.opcode =
 				VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION;
+			if (is_volte_session(v->session_id)) {
+				strlcpy(mvm_session_cmd.mvm_session.name,
+				"default volte voice",
+				sizeof(mvm_session_cmd.mvm_session.name));
+			} else {
 			strlcpy(mvm_session_cmd.mvm_session.name,
 				"default modem voice",
 				sizeof(mvm_session_cmd.mvm_session.name));
+			}
 
 			v->mvm_state = CMD_STATUS_FAIL;
 
@@ -356,7 +431,8 @@
 	}
 	/* send cmd to create cvs session */
 	if (!cvs_handle) {
-		if (is_voice_session(v->session_id)) {
+		if (is_voice_session(v->session_id) ||
+			is_volte_session(v->session_id)) {
 			pr_debug("%s: creating CVS passive session\n",
 				 __func__);
 
@@ -373,10 +449,15 @@
 			cvs_session_cmd.hdr.token = 0;
 			cvs_session_cmd.hdr.opcode =
 				VSS_ISTREAM_CMD_CREATE_PASSIVE_CONTROL_SESSION;
+			if (is_volte_session(v->session_id)) {
+				strlcpy(mvm_session_cmd.mvm_session.name,
+				"default volte voice",
+				sizeof(mvm_session_cmd.mvm_session.name));
+			} else {
 			strlcpy(cvs_session_cmd.cvs_session.name,
 				"default modem voice",
 				sizeof(cvs_session_cmd.cvs_session.name));
-
+			}
 			v->cvs_state = CMD_STATUS_FAIL;
 
 			ret = apr_send_pkt(apr_cvs,
@@ -3350,6 +3431,11 @@
 			pr_err("create mvm and cvs failed\n");
 			goto fail;
 		}
+		ret = voice_send_dual_control_cmd(v);
+		if (ret < 0) {
+			pr_err("Err Dual command failed\n");
+			goto fail;
+		}
 		ret = voice_setup_vocproc(v);
 		if (ret < 0) {
 			pr_err("setup voice failed\n");
@@ -3373,7 +3459,6 @@
 
 		v->voc_state = VOC_RUN;
 	}
-
 fail:	mutex_unlock(&v->lock);
 	return ret;
 }
@@ -3471,6 +3556,7 @@
 			case VSS_ICOMMON_CMD_SET_NETWORK:
 			case VSS_ICOMMON_CMD_SET_VOICE_TIMING:
 			case VSS_IWIDEVOICE_CMD_SET_WIDEVOICE:
+			case VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL:
 				pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
 				v->mvm_state = CMD_STATUS_SUCCESS;
 				wake_up(&v->mvm_wait);
diff --git a/sound/soc/msm/qdsp6/q6voice.h b/sound/soc/msm/qdsp6/q6voice.h
index 0fc7a01..cf691c0 100644
--- a/sound/soc/msm/qdsp6/q6voice.h
+++ b/sound/soc/msm/qdsp6/q6voice.h
@@ -107,6 +107,15 @@
 #define VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION	0x000110FF
 /**< No payload. Wait for APRV2_IBASIC_RSP_RESULT response. */
 
+#define VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL	0x00011327
+/*
+ * VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL
+ * Description: This command is required to let MVM know
+ * who is in control of session.
+ * Payload: Defined by vss_imvm_cmd_set_policy_dual_control_t.
+ * Result: Wait for APRV2_IBASIC_RSP_RESULT response.
+ */
+
 #define VSS_IMVM_CMD_CREATE_FULL_CONTROL_SESSION	0x000110FE
 /* Create a new full control MVM session. */
 
@@ -154,6 +163,14 @@
 #define VSS_IWIDEVOICE_CMD_SET_WIDEVOICE                0x00011243
 /* Enable/disable WideVoice */
 
+enum msm_audio_voc_rate {
+		VOC_0_RATE, /* Blank frame */
+		VOC_8_RATE, /* 1/8 rate    */
+		VOC_4_RATE, /* 1/4 rate    */
+		VOC_2_RATE, /* 1/2 rate    */
+		VOC_1_RATE  /* Full rate   */
+};
+
 struct vss_istream_cmd_set_tty_mode_t {
 	uint32_t mode;
 	/**<
@@ -228,6 +245,12 @@
 	*/
 } __packed;
 
+
+struct vss_imvm_cmd_set_policy_dual_control_t {
+	bool enable_flag;
+	/* Set to TRUE to enable modem state machine control */
+} __packed;
+
 struct vss_iwidevoice_cmd_set_widevoice_t {
 	uint32_t enable;
 	/* WideVoice enable/disable; possible values:
@@ -251,6 +274,11 @@
 	struct vss_imvm_cmd_create_control_session_t mvm_session;
 } __packed;
 
+struct mvm_modem_dual_control_session_cmd {
+	struct apr_hdr hdr;
+	struct vss_imvm_cmd_set_policy_dual_control_t voice_ctl;
+} __packed;
+
 struct mvm_set_tty_mode_cmd {
 	struct apr_hdr hdr;
 	struct vss_istream_cmd_set_tty_mode_t tty_mode;
@@ -637,6 +665,10 @@
 /* G.711 mu-law (contains two 10ms vocoder frames). */
 #define VSS_MEDIA_ID_G729		0x00010FD0
 /* G.729AB (contains two 10ms vocoder frames. */
+#define VSS_MEDIA_ID_4GV_NB_MODEM	0x00010FC3
+/*CDMA EVRC-B vocoder modem format */
+#define VSS_MEDIA_ID_4GV_WB_MODEM	0x00010FC4
+/*CDMA EVRC-WB vocoder modem format */
 
 #define VSS_IVOCPROC_CMD_SET_MUTE			0x000110EF
 
@@ -878,7 +910,7 @@
 	void *buf;
 };
 
-#define MAX_VOC_SESSIONS 2
+#define MAX_VOC_SESSIONS 3
 #define SESSION_ID_BASE 0xFFF0
 
 struct common_data {
@@ -947,6 +979,7 @@
 
 #define VOICE_SESSION_NAME "Voice session"
 #define VOIP_SESSION_NAME "VoIP session"
+#define VOLTE_SESSION_NAME "VoLTE session"
 uint16_t voc_get_session_id(char *name);
 
 int voc_start_playback(uint32_t set);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 0068c2a..f47b0d3 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3812,6 +3812,7 @@
 	mutex_init(&card->mutex);
 	mutex_init(&card->dapm_mutex);
 	mutex_init(&card->dsp_mutex);
+	spin_lock_init(&card->dsp_spinlock);
 
 	mutex_lock(&client_mutex);
 	list_add(&card->list, &card_list);
diff --git a/sound/soc/soc-dsp.c b/sound/soc/soc-dsp.c
index 6d4f178..1fb5585 100644
--- a/sound/soc/soc-dsp.c
+++ b/sound/soc/soc-dsp.c
@@ -635,10 +635,15 @@
 {
 	struct snd_soc_dsp_params *dsp_params;
 	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&fe->card->dsp_spinlock, flags);
 
 	if ((cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) ||
-				(cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH))
+				(cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH)) {
+		spin_unlock_irqrestore(&fe->card->dsp_spinlock, flags);
 		return ret;
+	}
 
 	list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
 
@@ -687,10 +692,14 @@
 			}
 			break;
 		}
-		if (ret < 0)
+
+		if (ret < 0) {
+			spin_unlock_irqrestore(&fe->card->dsp_spinlock, flags);
 			return ret;
+		}
 	}
 
+	spin_unlock_irqrestore(&fe->card->dsp_spinlock, flags);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(soc_dsp_be_dai_trigger);