Merge "msm: headsmp: Fix section mismatch warning" into msm-3.0
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 5a4b08f..4821290 100644
--- a/arch/arm/boot/dts/msmcopper.dtsi
+++ b/arch/arm/boot/dts/msmcopper.dtsi
@@ -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 1574a54..64451eb 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -42,6 +42,7 @@
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 # CONFIG_MSM_HW3D is not set
+CONFIG_MSM_PIL_LPASS_QDSP6V5=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index a6bbaf4..87296cc 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -69,6 +69,7 @@
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_RPM_LOG=y
 CONFIG_MSM_RPM_STATS_LOG=y
+CONFIG_MSM_IOMMU=y
 CONFIG_MSM_WATCHDOG=y
 CONFIG_MSM_DLOAD_MODE=y
 CONFIG_MSM_ETM=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index df49bdc..fd06714 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -68,6 +68,7 @@
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_RPM_LOG=y
 CONFIG_MSM_RPM_STATS_LOG=y
+CONFIG_MSM_IOMMU=y
 CONFIG_MSM_WATCHDOG=y
 CONFIG_MSM_DLOAD_MODE=y
 CONFIG_MSM_ETM=y
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 1bd91a8..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
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index d33a71f..5b0b9c3 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -77,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
@@ -442,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)
@@ -1971,6 +1978,7 @@
 	&apq_cpudai_slim_4_rx,
 	&apq_cpudai_slim_4_tx,
 	&msm8960_gemini_device,
+	&apq8064_iommu_domain_device,
 };
 
 static struct platform_device *sim_devices[] __initdata = {
@@ -2576,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()) {
@@ -2597,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-8930.c b/arch/arm/mach-msm/board-8930.c
index 4327fd9..24e6a79 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -1791,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 = {
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 45ebcaa..6328ab3 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2495,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;
@@ -2589,6 +2587,7 @@
 #ifdef CONFIG_MSM_CACHE_DUMP
 	&msm_cache_dump_device,
 #endif
+	&msm8960_iommu_domain_device,
 };
 
 static struct platform_device *sim_devices[] __initdata = {
@@ -3155,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-copper.c b/arch/arm/mach-msm/board-copper.c
index d81ad92..ccfc770 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -456,6 +456,8 @@
 			"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-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index af3d187..2a703f0 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -581,83 +581,83 @@
 	int i = 0;
 	int remainder;
 	/* device address byte = 0x72 */
-	gpio_set_value_cansleep(96, 0);
+	gpio_set_value(96, 0);
 	udelay(67);
-	gpio_set_value_cansleep(96, 1);
+	gpio_set_value(96, 1);
 	udelay(33);
-	gpio_set_value_cansleep(96, 0);
+	gpio_set_value(96, 0);
 	udelay(33);
-	gpio_set_value_cansleep(96, 1);
+	gpio_set_value(96, 1);
 	udelay(67);
-	gpio_set_value_cansleep(96, 0);
+	gpio_set_value(96, 0);
 	udelay(33);
-	gpio_set_value_cansleep(96, 1);
+	gpio_set_value(96, 1);
 	udelay(67);
-	gpio_set_value_cansleep(96, 0);
+	gpio_set_value(96, 0);
 	udelay(33);
-	gpio_set_value_cansleep(96, 1);
+	gpio_set_value(96, 1);
 	udelay(67);
-	gpio_set_value_cansleep(96, 0);
+	gpio_set_value(96, 0);
 	udelay(67);
-	gpio_set_value_cansleep(96, 1);
+	gpio_set_value(96, 1);
 	udelay(33);
-	gpio_set_value_cansleep(96, 0);
+	gpio_set_value(96, 0);
 	udelay(67);
-	gpio_set_value_cansleep(96, 1);
+	gpio_set_value(96, 1);
 	udelay(33);
-	gpio_set_value_cansleep(96, 0);
+	gpio_set_value(96, 0);
 	udelay(33);
-	gpio_set_value_cansleep(96, 1);
+	gpio_set_value(96, 1);
 	udelay(67);
-	gpio_set_value_cansleep(96, 0);
+	gpio_set_value(96, 0);
 	udelay(67);
-	gpio_set_value_cansleep(96, 1);
+	gpio_set_value(96, 1);
 	udelay(33);
 
 	/* t-EOS and t-start */
-	gpio_set_value_cansleep(96, 0);
+	gpio_set_value(96, 0);
 	ndelay(4200);
-	gpio_set_value_cansleep(96, 1);
+	gpio_set_value(96, 1);
 	ndelay(9000);
 
 	/* data byte */
 	/* RFA = 0 */
-	gpio_set_value_cansleep(96, 0);
+	gpio_set_value(96, 0);
 	udelay(67);
-	gpio_set_value_cansleep(96, 1);
+	gpio_set_value(96, 1);
 	udelay(33);
 
 	/* Address bits */
-	gpio_set_value_cansleep(96, 0);
+	gpio_set_value(96, 0);
 	udelay(67);
-	gpio_set_value_cansleep(96, 1);
+	gpio_set_value(96, 1);
 	udelay(33);
-	gpio_set_value_cansleep(96, 0);
+	gpio_set_value(96, 0);
 	udelay(67);
-	gpio_set_value_cansleep(96, 1);
+	gpio_set_value(96, 1);
 	udelay(33);
 
 	/* Data bits */
 	for (i = 0; i < 5; i++) {
 		remainder = (level) & (16);
 		if (remainder) {
-			gpio_set_value_cansleep(96, 0);
+			gpio_set_value(96, 0);
 			udelay(33);
-			gpio_set_value_cansleep(96, 1);
+			gpio_set_value(96, 1);
 			udelay(67);
 		} else {
-			gpio_set_value_cansleep(96, 0);
+			gpio_set_value(96, 0);
 			udelay(67);
-			gpio_set_value_cansleep(96, 1);
+			gpio_set_value(96, 1);
 			udelay(33);
 		}
 		level = level << 1;
 	}
 
 	/* t-EOS */
-	gpio_set_value_cansleep(96, 0);
+	gpio_set_value(96, 0);
 	ndelay(12000);
-	gpio_set_value_cansleep(96, 1);
+	gpio_set_value(96, 1);
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index f1960ce..2ed5897 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -567,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-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 510ce6b..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 */
diff --git a/arch/arm/mach-msm/cache_erp.c b/arch/arm/mach-msm/cache_erp.c
index 9a721e4..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)
@@ -193,11 +197,25 @@
 	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;
 
+	void *const saw_bases[] = {
+		MSM_SAW0_BASE,
+		MSM_SAW1_BASE,
+		MSM_SAW2_BASE,
+		MSM_SAW3_BASE,
+	};
+
 	if (print_regs) {
-		pr_alert("L1 Error detected on CPU %d!\n", smp_processor_id());
-		pr_alert("\tCESR    = 0x%08x\n", cesr);
+		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) {
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 39eddfa..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
@@ -2249,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-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 9e3ac63..5718fe0 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -373,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/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index 74e1115..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)
 
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index dbc1389..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,8 +68,8 @@
 
 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;
 }
@@ -235,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;
@@ -260,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;
@@ -282,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) {
@@ -325,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/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.h b/arch/arm/mach-msm/pil-q6v5.h
index 23471d1..b17d4e7 100644
--- a/arch/arm/mach-msm/pil-q6v5.h
+++ b/arch/arm/mach-msm/pil-q6v5.h
@@ -22,6 +22,7 @@
 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;
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 430a4c0..abcd336 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -287,7 +287,6 @@
 	int bytes_read;
 	int pkt_size;
 	struct smd_pkt_dev *smd_pkt_devp;
-	struct smd_channel *chl;
 	unsigned long flags;
 
 	smd_pkt_devp = file->private_data;
@@ -312,20 +311,30 @@
 	D_READ("Begin %s on smd_pkt_dev id:%d buffer_size %d\n",
 		__func__, smd_pkt_devp->i, count);
 
-	chl = smd_pkt_devp->ch;
 wait_for_packet:
 	r = wait_event_interruptible(smd_pkt_devp->ch_read_wait_queue,
-				     (smd_cur_packet_size(chl) > 0 &&
-				      smd_read_avail(chl)) ||
+				     !smd_pkt_devp->ch ||
+				     (smd_cur_packet_size(smd_pkt_devp->ch) > 0
+				      && smd_read_avail(smd_pkt_devp->ch)) ||
 				     smd_pkt_devp->has_reset);
 
+	mutex_lock(&smd_pkt_devp->rx_lock);
 	if (smd_pkt_devp->has_reset) {
+		mutex_unlock(&smd_pkt_devp->rx_lock);
 		pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
 			__func__, smd_pkt_devp->i);
 		return notify_reset(smd_pkt_devp);
 	}
 
+	if (!smd_pkt_devp->ch) {
+		mutex_unlock(&smd_pkt_devp->rx_lock);
+		pr_err("%s on a closed smd_pkt_dev id:%d\n",
+			__func__, smd_pkt_devp->i);
+		return -EINVAL;
+	}
+
 	if (r < 0) {
+		mutex_unlock(&smd_pkt_devp->rx_lock);
 		/* qualify error message */
 		if (r != -ERESTARTSYS) {
 			/* we get this anytime a signal comes in */
@@ -337,8 +346,6 @@
 	}
 
 	/* Here we have a whole packet waiting for us */
-
-	mutex_lock(&smd_pkt_devp->rx_lock);
 	pkt_size = smd_cur_packet_size(smd_pkt_devp->ch);
 
 	if (!pkt_size) {
@@ -429,7 +436,7 @@
 		return -EINVAL;
 	}
 
-	if (smd_pkt_devp->do_reset_notification) {
+	if (smd_pkt_devp->do_reset_notification || smd_pkt_devp->has_reset) {
 		pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
 			__func__, smd_pkt_devp->i);
 		/* notify client that a reset occurred */
@@ -485,6 +492,9 @@
 						__func__, smd_pkt_devp->i);
 					return notify_reset(smd_pkt_devp);
 				}
+				pr_err("%s on smd_pkt_dev id:%d failed r:%d\n",
+					__func__, smd_pkt_devp->i, r);
+				return r;
 			}
 			bytes_written += r;
 		}
@@ -512,11 +522,20 @@
 
 	smd_pkt_devp->poll_mode = 1;
 	poll_wait(file, &smd_pkt_devp->ch_read_wait_queue, wait);
+	mutex_lock(&smd_pkt_devp->ch_lock);
+	if (smd_pkt_devp->has_reset || !smd_pkt_devp->ch) {
+		mutex_unlock(&smd_pkt_devp->ch_lock);
+		pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
+			__func__, smd_pkt_devp->i);
+		return POLLERR;
+	}
+
 	if (smd_read_avail(smd_pkt_devp->ch)) {
 		mask |= POLLIN | POLLRDNORM;
 		D_POLL("%s sets POLLIN for smd_pkt_dev id: %d\n",
 			__func__, smd_pkt_devp->i);
 	}
+	mutex_unlock(&smd_pkt_devp->ch_lock);
 
 	return mask;
 }
@@ -814,8 +833,12 @@
 		r = wait_event_interruptible_timeout(
 				smd_pkt_devp->ch_opened_wait_queue,
 				smd_pkt_devp->is_open, (2 * HZ));
-		if (r == 0)
+		if (r == 0) {
 			r = -ETIMEDOUT;
+			/* close the ch to sync smd's state with smd_pkt */
+			smd_close(smd_pkt_devp->ch);
+			smd_pkt_devp->ch = NULL;
+		}
 
 		if (r < 0) {
 			pr_err("%s: wait on smd_pkt_dev id:%d OPEN event failed"
@@ -864,6 +887,8 @@
 	clean_and_signal(smd_pkt_devp);
 
 	mutex_lock(&smd_pkt_devp->ch_lock);
+	mutex_lock(&smd_pkt_devp->rx_lock);
+	mutex_lock(&smd_pkt_devp->tx_lock);
 	if (smd_pkt_devp->ch != 0) {
 		r = smd_close(smd_pkt_devp->ch);
 		smd_pkt_devp->ch = 0;
@@ -873,6 +898,8 @@
 		if (smd_pkt_devp->pil)
 			pil_put(smd_pkt_devp->pil);
 	}
+	mutex_unlock(&smd_pkt_devp->tx_lock);
+	mutex_unlock(&smd_pkt_devp->rx_lock);
 	mutex_unlock(&smd_pkt_devp->ch_lock);
 
 	smd_pkt_devp->has_reset = 0;
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index f6d3cad..a992059 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -857,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_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index 65bcb09..1d80a30 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -397,15 +397,15 @@
 	return baseptr[pte] & GSL_PT_PAGE_ADDR_MASK;
 }
 
-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),
@@ -460,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;
@@ -468,23 +468,21 @@
 		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;
-
 	if (mmu->flags & KGSL_FLAGS_STARTED) {
 		/* page table not current, then setup mmu to use new
 		 *  specified page table
@@ -497,13 +495,13 @@
 			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
@@ -511,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) {
@@ -533,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
@@ -546,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)
@@ -587,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;
@@ -691,25 +686,21 @@
 	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);
 
@@ -720,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;
 }
 
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index b7f7b0a..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);
@@ -304,14 +298,13 @@
 	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 */
@@ -323,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);
 
@@ -333,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 = {
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 323c992..2b359ec 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -328,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);
 
@@ -359,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);
@@ -385,7 +385,7 @@
 	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);
 
@@ -400,7 +400,7 @@
 			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);
@@ -418,7 +418,7 @@
 	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);
@@ -543,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);
 
@@ -561,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);
 
@@ -753,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);
 
@@ -764,8 +764,9 @@
 	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);
 
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 63ecdd6..e35f368 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -116,18 +116,20 @@
 	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 {
@@ -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/z180.c b/drivers/gpu/msm/z180.c
index 5902361..3ca9e18 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -468,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),
@@ -881,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);
 	}
 }
 
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index a027a2d..e9c710a 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -603,6 +603,7 @@
 	struct vcd_property_profile vcd_property_profile;
 	struct vcd_property_hdr vcd_property_hdr;
 	struct vcd_property_codec vcd_property_codec;
+	struct vcd_property_i_period vcd_property_i_period;
 	int rc = 0;
 
 	/* Validate params */
@@ -614,7 +615,7 @@
 	if (rc < 0) {
 		WFD_MSG_ERR("Error getting codec property");
 		rc = -EINVAL;
-		goto err;
+		goto err_set_profile;
 	}
 
 	if (!((vcd_property_codec.codec == VCD_CODEC_H264
@@ -624,7 +625,7 @@
 		WFD_MSG_ERR("Attempting to set %d for codec type %d",
 			codec, vcd_property_codec.codec);
 		rc = -EINVAL;
-		goto err;
+		goto err_set_profile;
 	}
 
 	/* Set property */
@@ -671,12 +672,31 @@
 				"not setting profile (%d)",
 				codec, profile);
 		rc = -ENOTSUPP;
-		goto err;
+		goto err_set_profile;
 	}
 
 	rc = vcd_set_property(client_ctx->vcd_handle,
 				&vcd_property_hdr, &vcd_property_profile);
-err:
+
+	/* Disable B-frames, since VSG doesn't support out of order i/p bufs */
+	vcd_property_hdr.prop_id = VCD_I_INTRA_PERIOD;
+	vcd_property_hdr.sz = sizeof(struct vcd_property_i_period);
+
+	rc = vcd_get_property(client_ctx->vcd_handle,
+				&vcd_property_hdr, &vcd_property_i_period);
+	if (rc) {
+		WFD_MSG_ERR("Error getting I-period property");
+		goto err_set_profile;
+	}
+	vcd_property_i_period.b_frames = 0;
+	rc = vcd_set_property(client_ctx->vcd_handle,
+				&vcd_property_hdr, &vcd_property_i_period);
+	if (rc) {
+		WFD_MSG_ERR("Error setting I-period property");
+		goto err_set_profile;
+	}
+
+err_set_profile:
 	return rc;
 }
 
@@ -1529,6 +1549,146 @@
 	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_cyclic_intra_refresh_mb(
+		struct video_client_ctx *client_ctx,
+		__s32 value)
+{
+	struct vcd_property_hdr vcd_property_hdr;
+	struct vcd_property_intra_refresh_mb_number cir_mb_num;
+	int rc = 0;
+
+	if (!client_ctx) {
+		WFD_MSG_ERR("Invalid parameters\n");
+		rc = -EINVAL;
+		goto set_cir_mbs_fail;
+	}
+
+	vcd_property_hdr.prop_id = VCD_I_INTRA_REFRESH;
+	vcd_property_hdr.sz = sizeof(cir_mb_num);
+
+	cir_mb_num.cir_mb_number = value;
+
+	rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
+			&cir_mb_num);
+	if (rc) {
+		WFD_MSG_ERR("Failed to set CIR MBs\n");
+		goto set_cir_mbs_fail;
+	}
+
+set_cir_mbs_fail:
+	return rc;
+}
+
+static long venc_get_cyclic_intra_refresh_mb(
+		struct video_client_ctx *client_ctx,
+		__s32 *value)
+{
+	struct vcd_property_hdr vcd_property_hdr;
+	struct vcd_property_intra_refresh_mb_number cir_mb_num;
+	int rc = 0;
+
+	if (!client_ctx || !value) {
+		WFD_MSG_ERR("Invalid parameters\n");
+		rc = -EINVAL;
+		goto get_cir_mbs_fail;
+	}
+
+	vcd_property_hdr.prop_id = VCD_I_INTRA_REFRESH;
+	vcd_property_hdr.sz = sizeof(cir_mb_num);
+
+	rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+			&cir_mb_num);
+	if (rc) {
+		WFD_MSG_ERR("Failed to set CIR MBs\n");
+		goto get_cir_mbs_fail;
+	}
+
+	*value = cir_mb_num.cir_mb_number;
+
+get_cir_mbs_fail:
+	return rc;
+}
 static long venc_set_input_buffer(struct v4l2_subdev *sd, void *arg)
 {
 	struct mem_region *mregion = arg;
@@ -1904,6 +2064,12 @@
 	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;
+	case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
+		rc = venc_set_cyclic_intra_refresh_mb(client_ctx, ctrl->value);
+		break;
 	default:
 		WFD_MSG_ERR("Set property not suported: %d\n", ctrl->id);
 		rc = -ENOTSUPP;
@@ -1963,6 +2129,12 @@
 		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;
+	case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
+		rc = venc_get_cyclic_intra_refresh_mb(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/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 c12636c..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 {
@@ -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 "
@@ -1310,6 +1324,7 @@
 				MDP_CLOSE, (void *)inst->mdp_inst);
 err_mdp_open:
 	kfree(inst);
+err_dev_busy:
 	return rc;
 }
 
@@ -1345,6 +1360,10 @@
 		kfree(inst);
 	}
 
+	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;
 }
@@ -1487,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/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 2da48ab..f319eb5 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -168,8 +168,6 @@
 	return rc;
 }
 
-#ifdef CONFIG_PM_SLEEP
-#define USB_PHY_SUSP_DIG_VOL  500000
 static int msm_hsusb_config_vddcx(int high)
 {
 	struct msm_otg *motg = the_msm_otg;
@@ -190,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)
 {
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 222d353..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]) {
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index ea04723..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;
diff --git a/sound/soc/msm/msm-pcm-voip.c b/sound/soc/msm/msm-pcm-voip.c
index 2301472..570d71c 100644
--- a/sound/soc/msm/msm-pcm-voip.c
+++ b/sound/soc/msm/msm-pcm-voip.c
@@ -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;
 
@@ -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;
@@ -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/qdsp6/q6voice.h b/sound/soc/msm/qdsp6/q6voice.h
index 3310abd..cf691c0 100644
--- a/sound/soc/msm/qdsp6/q6voice.h
+++ b/sound/soc/msm/qdsp6/q6voice.h
@@ -163,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;
 	/**<
@@ -657,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