Merge "msm: msm_watchdog: Don't pet the watchdog if it isn't enabled" into msm-3.0
diff --git a/arch/arm/boot/dts/msmcopper-regulator.dtsi b/arch/arm/boot/dts/msmcopper-regulator.dtsi
index 4d9f10e..b0c48fc 100644
--- a/arch/arm/boot/dts/msmcopper-regulator.dtsi
+++ b/arch/arm/boot/dts/msmcopper-regulator.dtsi
@@ -24,16 +24,16 @@
 			};
 
 			pm8941_s2: regulator@1700 {
-				regulator-min-microvolt = <1300000>;
-				regulator-max-microvolt = <1300000>;
+				regulator-min-microvolt = <2150000>;
+				regulator-max-microvolt = <2150000>;
 				qcom,enable-time = <500>;
 				qcom,pull-down-enable = <1>;
 				status = "okay";
 			};
 
 			pm8941_s3: regulator@1a00 {
-				regulator-min-microvolt = <1300000>;
-				regulator-max-microvolt = <1300000>;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
 				qcom,enable-time = <500>;
 				qcom,pull-down-enable = <1>;
 				status = "okay";
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 4e43cb2..1107412 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -214,6 +214,9 @@
 	void __iomem *base = gic_data_dist_base(gic);
 
 	for (i = 0; i * 32 < gic->max_irq; i++) {
+#ifdef CONFIG_ARCH_MSM8625
+		raw_spin_lock(&irq_controller_lock);
+#endif
 		gic->enabled_irqs[i]
 			= readl_relaxed(base + GIC_DIST_ENABLE_SET + i * 4);
 		/* disable all of them */
@@ -221,6 +224,9 @@
 		/* enable the wakeup set */
 		writel_relaxed(gic->wakeup_irqs[i],
 			base + GIC_DIST_ENABLE_SET + i * 4);
+#ifdef CONFIG_ARCH_MSM8625
+		raw_spin_unlock(&irq_controller_lock);
+#endif
 	}
 	mb();
 	return 0;
@@ -269,11 +275,17 @@
 
 	gic_show_resume_irq(gic);
 	for (i = 0; i * 32 < gic->max_irq; i++) {
+#ifdef CONFIG_ARCH_MSM8625
+		raw_spin_lock(&irq_controller_lock);
+#endif
 		/* disable all of them */
 		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4);
 		/* enable the enabled set */
 		writel_relaxed(gic->enabled_irqs[i],
 			base + GIC_DIST_ENABLE_SET + i * 4);
+#ifdef CONFIG_ARCH_MSM8625
+		raw_spin_unlock(&irq_controller_lock);
+#endif
 	}
 	mb();
 }
@@ -306,8 +318,13 @@
 		gic_arch_extn.irq_eoi(d);
 		raw_spin_unlock(&irq_controller_lock);
 	}
-
+#ifdef CONFIG_ARCH_MSM8625
+	raw_spin_lock(&irq_controller_lock);
+#endif
 	writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
+#ifdef CONFIG_ARCH_MSM8625
+	raw_spin_unlock(&irq_controller_lock);
+#endif
 }
 
 static int gic_set_type(struct irq_data *d, unsigned int type)
@@ -430,7 +447,13 @@
 	void __iomem *cpu_base = gic_data_cpu_base(gic);
 
 	do {
+#ifdef CONFIG_ARCH_MSM8625
+		raw_spin_lock(&irq_controller_lock);
+#endif
 		irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
+#ifdef CONFIG_ARCH_MSM8625
+		raw_spin_unlock(&irq_controller_lock);
+#endif
 		irqnr = irqstat & ~0x1c00;
 
 		if (likely(irqnr > 15 && irqnr < 1021)) {
@@ -439,7 +462,13 @@
 			continue;
 		}
 		if (irqnr < 16) {
+#ifdef CONFIG_ARCH_MSM8625
+			raw_spin_lock(&irq_controller_lock);
+#endif
 			writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
+#ifdef CONFIG_ARCH_MSM8625
+			raw_spin_unlock(&irq_controller_lock);
+#endif
 #ifdef CONFIG_SMP
 			handle_IPI(irqnr, regs);
 #endif
@@ -588,6 +617,9 @@
 	 * Deal with the banked PPI and SGI interrupts - disable all
 	 * PPI interrupts, ensure all SGI interrupts are enabled.
 	 */
+#ifdef CONFIG_ARCH_MSM8625
+	raw_spin_lock(&irq_controller_lock);
+#endif
 	writel_relaxed(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
 	writel_relaxed(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
 
@@ -607,6 +639,9 @@
 		writel_relaxed(0xF, base + GIC_CPU_CTRL);
 	else
 		writel_relaxed(1, base + GIC_CPU_CTRL);
+#ifdef CONFIG_ARCH_MSM8625
+	raw_spin_unlock(&irq_controller_lock);
+#endif
     mb();
 }
 
@@ -944,6 +979,9 @@
 	int cpu;
 	unsigned long sgir;
 	unsigned long map = 0;
+#ifdef CONFIG_ARCH_MSM8625
+	unsigned long flags;
+#endif
 
 	/* Convert our logical CPU mask into a physical one. */
 	for_each_cpu(cpu, mask)
@@ -959,9 +997,15 @@
 	 */
 	dsb();
 
+#ifdef CONFIG_ARCH_MSM8625
+	raw_spin_lock_irqsave(&irq_controller_lock, flags);
+#endif
 	/* this always happens on GIC0 */
 	writel_relaxed(sgir,
 			gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
+#ifdef CONFIG_ARCH_MSM8625
+	raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
+#endif
 	mb();
 }
 #endif
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/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index 2019f9b..24f0f41 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -430,6 +430,19 @@
 	.vcm_enable     = 0,
 };
 
+static struct i2c_board_info msm_act_main_cam1_i2c_info = {
+	I2C_BOARD_INFO("msm_actuator", 0x18),
+};
+
+static struct msm_actuator_info msm_act_main_cam_1_info = {
+	.board_info     = &msm_act_main_cam1_i2c_info,
+	.cam_name       = MSM_ACTUATOR_MAIN_CAM_1,
+	.bus_id         = APQ_8064_GSBI4_QUP_I2C_BUS_ID,
+	.vcm_pwd        = 0,
+	.vcm_enable     = 0,
+};
+
+
 static struct msm_camera_i2c_conf apq8064_front_cam_i2c_conf = {
 	.use_i2c_mux = 1,
 	.mux_dev = &msm8960_device_i2c_mux_gsbi4,
@@ -498,6 +511,7 @@
 	.csi_if	= 1,
 	.camera_type = BACK_CAMERA_2D,
 	.sensor_type = BAYER_SENSOR,
+	.actuator_info = &msm_act_main_cam_1_info,
 };
 
 static struct camera_vreg_t apq_8064_s5k3l1yx_vreg[] = {
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index b60519b..83e3c8d 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -492,6 +492,18 @@
 	.vcm_enable     = 0,
 };
 
+static struct i2c_board_info msm_act_main_cam1_i2c_info = {
+	I2C_BOARD_INFO("msm_actuator", 0x18),
+};
+
+static struct msm_actuator_info msm_act_main_cam_1_info = {
+	.board_info     = &msm_act_main_cam1_i2c_info,
+	.cam_name       = MSM_ACTUATOR_MAIN_CAM_1,
+	.bus_id         = MSM_8960_GSBI4_QUP_I2C_BUS_ID,
+	.vcm_pwd        = 0,
+	.vcm_enable     = 0,
+};
+
 static struct msm_camera_sensor_flash_data flash_imx074 = {
 	.flash_type	= MSM_CAMERA_FLASH_LED,
 #ifdef CONFIG_MSM_CAMERA_FLASH
@@ -654,6 +666,7 @@
 	.csi_if	= 1,
 	.camera_type = BACK_CAMERA_2D,
 	.sensor_type = BAYER_SENSOR,
+	.actuator_info = &msm_act_main_cam_1_info,
 };
 
 static struct pm8xxx_mpp_config_data privacy_light_on_config = {
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index ccfc770..d1b62ae 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -337,9 +337,14 @@
 	},
 };
 
+static struct smd_subsystem_restart_config smd_ssr_cfg = {
+	.disable_smsm_reset_handshake = 1,
+};
+
 static struct smd_platform smd_platform_data = {
 	.num_ss_configs = ARRAY_SIZE(smd_config_list),
 	.smd_ss_configs = smd_config_list,
+	.smd_ssr_config = &smd_ssr_cfg,
 	.num_smem_areas = ARRAY_SIZE(aux_smem_areas),
 	.smd_smem_areas = aux_smem_areas,
 };
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 2ed5897..8941b6d 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -48,7 +48,6 @@
 #include <mach/msm_battery.h>
 #include <linux/smsc911x.h>
 #include <linux/atmel_maxtouch.h>
-#include <linux/fmem.h>
 #include <linux/msm_adc.h>
 #include "devices.h"
 #include "timer.h"
@@ -436,9 +435,6 @@
 	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
 	.cached = 1,
 	.memory_type = MEMTYPE_EBI1,
-	.request_region = request_fmem_c_region,
-	.release_region = release_fmem_c_region,
-	.reusable = 1,
 };
 
 static struct platform_device android_pmem_adsp_device = {
@@ -760,14 +756,6 @@
 static void msm7x27a_cfg_uart2dm_serial(void) { }
 #endif
 
-struct fmem_platform_data fmem_pdata;
-
-struct platform_device fmem_device = {
-	.name = "fmem",
-	.id = -1,
-	.dev = { .platform_data = &fmem_pdata },
-};
-
 static struct platform_device *rumi_sim_devices[] __initdata = {
 	&msm_device_dmov,
 	&msm_device_smd,
@@ -805,7 +793,6 @@
 	&android_pmem_device,
 	&android_pmem_adsp_device,
 	&android_pmem_audio_device,
-	&fmem_device,
 	&msm_device_nand,
 	&msm_device_snd,
 	&msm_device_adspdec,
@@ -856,19 +843,8 @@
 	},
 };
 
-#ifdef CONFIG_ANDROID_PMEM
-static struct android_pmem_platform_data *pmem_pdata_array[] __initdata = {
-		&android_pmem_adsp_pdata,
-		&android_pmem_audio_pdata,
-		&android_pmem_pdata,
-};
-#endif
-
 static void __init size_pmem_devices(void)
 {
-#ifdef CONFIG_ANDROID_PMEM
-	unsigned int i;
-	unsigned int reusable_count = 0;
 
 	if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
 		pmem_mdp_size = MSM7x25A_MSM_PMEM_MDP_SIZE;
@@ -878,30 +854,11 @@
 		pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
 	}
 
+#ifdef CONFIG_ANDROID_PMEM
 	android_pmem_adsp_pdata.size = pmem_adsp_size;
 	android_pmem_pdata.size = pmem_mdp_size;
 	android_pmem_audio_pdata.size = pmem_audio_size;
-
-	fmem_pdata.size = 0;
-
-	/* Find pmem devices that should use FMEM (reusable) memory.
-	 */
-	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
-		struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
-
-		if (!reusable_count && pdata->reusable)
-			fmem_pdata.size += pdata->size;
-
-		reusable_count += (pdata->reusable) ? 1 : 0;
-
-		if (pdata->reusable && reusable_count > 1) {
-			pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
-				__func__, pdata->name);
-			pdata->reusable = 0;
-		}
-	}
 #endif
-
 }
 
 static void __init reserve_memory_for(struct android_pmem_platform_data *p)
@@ -912,12 +869,9 @@
 static void __init reserve_pmem_memory(void)
 {
 #ifdef CONFIG_ANDROID_PMEM
-	unsigned int i;
-	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
-		if (!pmem_pdata_array[i]->reusable)
-			reserve_memory_for(pmem_pdata_array[i]);
-	}
-
+	reserve_memory_for(&android_pmem_adsp_pdata);
+	reserve_memory_for(&android_pmem_pdata);
+	reserve_memory_for(&android_pmem_audio_pdata);
 	msm7x27a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
 #endif
 }
@@ -943,7 +897,6 @@
 {
 	reserve_info = &msm7x27a_reserve_info;
 	msm_reserve();
-	fmem_pdata.phys = reserve_memory_for_fmem(fmem_pdata.size);
 }
 
 static void __init msm8625_reserve(void)
diff --git a/arch/arm/mach-msm/devices-msm7x27.c b/arch/arm/mach-msm/devices-msm7x27.c
index 5ec339e..d36b8d9 100644
--- a/arch/arm/mach-msm/devices-msm7x27.c
+++ b/arch/arm/mach-msm/devices-msm7x27.c
@@ -427,7 +427,7 @@
 	.exit_sleep3 = msm_irq_exit_sleep3,
 };
 
-void msm_pm_register_irqs(void)
+void __init msm_pm_register_irqs(void)
 {
 	msm_pm_set_irq_extns(&msm7x27_pm_irq_calls);
 }
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 1391981..bd0376e 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -447,7 +447,7 @@
 	.exit_sleep3 = msm_gic_irq_exit_sleep3,
 };
 
-void msm_pm_register_irqs(void)
+void __init msm_pm_register_irqs(void)
 {
 	if (cpu_is_msm8625())
 		msm_pm_set_irq_extns(&msm8625_pm_irq_calls);
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 0e15a4f..5f08d77 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -681,7 +681,7 @@
 	.exit_sleep3 = msm_irq_exit_sleep3,
 };
 
-void msm_pm_register_irqs(void)
+void __init msm_pm_register_irqs(void)
 {
 	msm_pm_set_irq_extns(&msm7x30_pm_irq_calls);
 }
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index a32079b..674d55c 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -443,7 +443,7 @@
 	.exit_sleep3 = msm_irq_exit_sleep3,
 };
 
-void msm_pm_register_irqs(void)
+void __init msm_pm_register_irqs(void)
 {
 	msm_pm_set_irq_extns(&qsd8x50_pm_irq_calls);
 }
diff --git a/arch/arm/mach-msm/headsmp.S b/arch/arm/mach-msm/headsmp.S
index 979c1f8..1602811 100644
--- a/arch/arm/mach-msm/headsmp.S
+++ b/arch/arm/mach-msm/headsmp.S
@@ -1,7 +1,7 @@
 /*
  *  Copyright (c) 2003 ARM Limited
  *  All Rights Reserved
- *  Copyright (c) 2010, 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 as
@@ -10,6 +10,8 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 
+__CPUINIT
+
 /*
  * MSM specific entry point for secondary CPUs.  This provides
  * a "holding pen" into which all secondary cores are held until we're
diff --git a/arch/arm/mach-msm/idle_stats_device.c b/arch/arm/mach-msm/idle_stats_device.c
index d5a61af..3c0e7a9 100644
--- a/arch/arm/mach-msm/idle_stats_device.c
+++ b/arch/arm/mach-msm/idle_stats_device.c
@@ -103,9 +103,10 @@
 {
 	hrtimer_cancel(&device->busy_timer);
 	hrtimer_set_expires(&device->busy_timer, us_to_ktime(0));
-	if (device->stats->nr_collected >= device->max_samples)
-		return;
-
+	if (device->stats->nr_collected >= MSM_IDLE_STATS_NR_MAX_INTERVALS) {
+		pr_warning("idle_stats_device: Overwriting samples\n");
+		device->stats->nr_collected = 0;
+	}
 	device->stats->pulse_chain[device->stats->nr_collected] = *pulse;
 	device->stats->nr_collected++;
 
@@ -230,6 +231,7 @@
 void msm_idle_stats_idle_end(struct msm_idle_stats_device *device,
 				struct msm_idle_pulse *pulse)
 {
+	int tmp;
 	u32 idle_time = 0;
 	spin_lock(&device->lock);
 	if (ktime_to_us(device->idle_start) != 0) {
@@ -254,7 +256,18 @@
 				 ktime_to_us(busy_timer)))
 				busy_timer = device->remaining_time;
 		    start_busy_timer(device, busy_timer);
-	    }
+		    /* If previous busy interval exceeds the current submit,
+		     * raise a busy timer expired event intentionally.
+		     */
+		    tmp = device->stats->nr_collected - 1;
+		    if (tmp > 0) {
+			if ((device->stats->pulse_chain[tmp - 1].busy_start_time
+			+ device->stats->pulse_chain[tmp - 1].busy_interval) >
+			  device->stats->pulse_chain[tmp].busy_start_time)
+				msm_idle_stats_update_event(device,
+				   MSM_IDLE_STATS_EVENT_BUSY_TIMER_EXPIRED);
+		    }
+		}
 	}
 	spin_unlock(&device->lock);
 }
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index fb7f977..339a955 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -1,7 +1,7 @@
 /* linux/include/asm-arm/arch-msm/dma.h
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-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
@@ -255,10 +255,10 @@
 #endif
 
 /* channels for APQ8064 */
-#define DMOV8064_CE_IN_CHAN        2
+#define DMOV8064_CE_IN_CHAN        0
 #define DMOV8064_CE_IN_CRCI       14
 
-#define DMOV8064_CE_OUT_CHAN       3
+#define DMOV8064_CE_OUT_CHAN       1
 #define DMOV8064_CE_OUT_CRCI       15
 
 
diff --git a/arch/arm/mach-msm/mpm-8625.c b/arch/arm/mach-msm/mpm-8625.c
index 8ef7d61..6b88103 100644
--- a/arch/arm/mach-msm/mpm-8625.c
+++ b/arch/arm/mach-msm/mpm-8625.c
@@ -175,7 +175,7 @@
 }
 #endif
 
-void msm_gic_irq_extn_init(void __iomem *db, void __iomem *cb)
+void __init msm_gic_irq_extn_init(void __iomem *db, void __iomem *cb)
 {
 	dist_base = db;
 	cpu_base = cb;
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index c237013..a22b175 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -650,7 +650,7 @@
 }
 #endif
 
-static bool msm_pm_spm_power_collapse(
+static bool __ref msm_pm_spm_power_collapse(
 	unsigned int cpu, bool from_idle, bool notify_rpm)
 {
 	void *entry;
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index 4f3c7e4..39e321a 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -1410,7 +1410,7 @@
  * Return value:
  *      0: success
  */
-static int msm_pm_power_collapse_standalone(bool from_idle)
+static int __ref msm_pm_power_collapse_standalone(bool from_idle)
 {
 	int collapsed = 0;
 	int ret;
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/arch/arm/mach-msm/sysmon.c b/arch/arm/mach-msm/sysmon.c
index ddb8502..679393d 100644
--- a/arch/arm/mach-msm/sysmon.c
+++ b/arch/arm/mach-msm/sysmon.c
@@ -111,10 +111,10 @@
 	mutex_lock(&ss->lock);
 	switch (ss->transport) {
 	case TRANSPORT_SMD:
-		ret = sysmon_send_smd(ss, tx_buf, ARRAY_SIZE(tx_buf));
+		ret = sysmon_send_smd(ss, tx_buf, strlen(tx_buf));
 		break;
 	case TRANSPORT_HSIC:
-		ret = sysmon_send_hsic(ss, tx_buf, ARRAY_SIZE(tx_buf));
+		ret = sysmon_send_hsic(ss, tx_buf, strlen(tx_buf));
 		break;
 	default:
 		ret = -EINVAL;
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 2e422c4..f643dca 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -323,11 +323,11 @@
 #endif
 
 #ifndef CONFIG_SPARSEMEM
-static void arm_memory_present(void)
+static void __init arm_memory_present(void)
 {
 }
 #else
-static void arm_memory_present(void)
+static void __init arm_memory_present(void)
 {
 	struct meminfo *mi = &meminfo;
 	int i;
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index a31afb8..c841d87 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -614,8 +614,8 @@
 	}
 }
 
-static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
-	unsigned long phys, const struct mem_type *type)
+static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
+	unsigned long end, unsigned long phys, const struct mem_type *type)
 {
 	pud_t *pud = pud_offset(pgd, addr);
 	unsigned long next;
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 6fa053b..050fd83 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1325,7 +1325,7 @@
 {
 	int result;
 
-	calc_gmemsize(&drawctxt->context_gmem_shadow, adreno_dev->gmem_base);
+	calc_gmemsize(&drawctxt->context_gmem_shadow, adreno_dev->gmem_size);
 	tmp_ctx.gmem_base = adreno_dev->gmem_base;
 
 	result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index a992059..fe01764 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -464,8 +464,11 @@
 	if (context) {
 		total_sizedwords += 3; /* sop timestamp */
 		total_sizedwords += 4; /* eop timestamp */
+		total_sizedwords += 3; /* global timestamp without cache
+					* flush for non-zero context */
+	} else {
+		total_sizedwords += 4; /* global timestamp for recovery*/
 	}
-	total_sizedwords += 4; /* global timestamp for recovery*/
 
 	ringcmds = adreno_ringbuffer_allocspace(rb, total_sizedwords);
 	rcmd_gpu = rb->buffer_desc.gpuaddr
@@ -538,14 +541,24 @@
 		GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
 			KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp)));
 		GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
-	}
 
-	GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 3));
-	GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
-	GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
-		      KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
-			      eoptimestamp)));
-	GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+		GSL_RB_WRITE(ringcmds, rcmd_gpu,
+			cp_type3_packet(CP_MEM_WRITE, 2));
+		GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
+			      KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
+				      eoptimestamp)));
+		GSL_RB_WRITE(ringcmds, rcmd_gpu,
+			rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+	} else {
+		GSL_RB_WRITE(ringcmds, rcmd_gpu,
+			cp_type3_packet(CP_EVENT_WRITE, 3));
+		GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
+		GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
+			      KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
+				      eoptimestamp)));
+		GSL_RB_WRITE(ringcmds, rcmd_gpu,
+			rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+	}
 
 	if (!(flags & KGSL_CMD_FLAGS_NO_TS_CMP)) {
 		/* Conditional execution based on memory values */
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index d050599..37a1ff2 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -791,6 +791,9 @@
 		(struct msm_camera_sensor_info *) s_ctrl->sensordata;
 	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
 
+	v4l2_subdev_call(p_mctl->sensor_sdev, core, ioctl,
+		VIDIOC_MSM_SENSOR_RELEASE, NULL);
+
 	if (camdev->is_ispif) {
 		v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
 			VIDIOC_MSM_ISPIF_RELEASE, NULL);
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index e0fa962..cc56ccf 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -368,6 +368,24 @@
 	return rc;
 }
 
+int32_t msm_sensor_release(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	long fps = 0;
+	uint32_t delay = 0;
+	CDBG("%s called\n", __func__);
+	s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
+	if (s_ctrl->curr_res != MSM_SENSOR_INVALID_RES) {
+		fps = s_ctrl->msm_sensor_reg->
+			output_settings[s_ctrl->curr_res].vt_pixel_clk /
+			s_ctrl->curr_frame_length_lines /
+			s_ctrl->curr_line_length_pclk;
+		delay = 1000 / fps;
+		CDBG("%s fps = %ld, delay = %d\n", __func__, fps, delay);
+		msleep(delay);
+	}
+	return 0;
+}
+
 long msm_sensor_subdev_ioctl(struct v4l2_subdev *sd,
 			unsigned int cmd, void *arg)
 {
@@ -376,6 +394,8 @@
 	switch (cmd) {
 	case VIDIOC_MSM_SENSOR_CFG:
 		return s_ctrl->func_tbl->sensor_config(s_ctrl, argp);
+	case VIDIOC_MSM_SENSOR_RELEASE:
+		return msm_sensor_release(s_ctrl);
 	default:
 		return -ENOIOCTLCMD;
 	}
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/video/msm/sensors/msm_sensor.h
index 421e1d1..0104b98 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.h
+++ b/drivers/media/video/msm/sensors/msm_sensor.h
@@ -249,4 +249,7 @@
 #define VIDIOC_MSM_SENSOR_CFG \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 10, void __user *)
 
+#define VIDIOC_MSM_SENSOR_RELEASE \
+	_IO('V', BASE_VIDIOC_PRIVATE + 11)
+
 #endif
diff --git a/drivers/media/video/msm/sensors/ov5647_v4l2.c b/drivers/media/video/msm/sensors/ov5647_v4l2.c
index 7c23fe6..ca2bb98 100644
--- a/drivers/media/video/msm/sensors/ov5647_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov5647_v4l2.c
@@ -449,7 +449,7 @@
 	gain_lsb = (uint8_t) (gain);
 	gain_hsb = (uint8_t)((gain & 0x300)>>8);
 	/* adjust frame rate */
-	if (line > 980) {
+	if (line > 980 && line <= 984) {
 
 		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
 		s_ctrl->sensor_output_reg_addr->frame_length_lines,
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index 95cdc59..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;
 }
 
@@ -1610,6 +1630,65 @@
 	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;
@@ -1988,6 +2067,9 @@
 	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;
@@ -2050,6 +2132,9 @@
 	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/mfd/wcd9xxx-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c
index 3b7bdc8..3aff7f17 100644
--- a/drivers/mfd/wcd9xxx-slimslave.c
+++ b/drivers/mfd/wcd9xxx-slimslave.c
@@ -141,7 +141,7 @@
 	struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
 	u16 slave_port_id = 0;
 
-	pr_err("%s: pgd_la[%d]\n", __func__, wcd9xxx_pgd_la);
+	pr_debug("%s: pgd_la[%d]\n", __func__, wcd9xxx_pgd_la);
 	/* DSP requires 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
@@ -218,7 +218,7 @@
 	struct slim_ch prop;
 
 	/* Configure slave interface device */
-	pr_err("%s: ch_cnt[%d] rate=%d\n", __func__, ch_cnt, rate);
+	pr_debug("%s: ch_cnt[%d] rate=%d\n", __func__, ch_cnt, rate);
 
 	for (i = 0; i < ch_cnt; i++) {
 		idx = (ch_num[i] - BASE_CH_NUM -
@@ -458,7 +458,7 @@
 	int ret = 0;
 	struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
 
-	pr_err("%s: ch_cnt[%d]\n", __func__, ch_cnt);
+	pr_debug("%s: ch_cnt[%d]\n", __func__, ch_cnt);
 	for (i = 0; i < ch_cnt; i++) {
 		idx = (ch_num[i] - BASE_CH_NUM -
 				SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
@@ -498,7 +498,7 @@
 	int i = 0 , idx = 0;
 	struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
 
-	pr_err("%s: ch_cnt[%d]\n", __func__, ch_cnt);
+	pr_debug("%s: ch_cnt[%d]\n", __func__, ch_cnt);
 	for (i = 0; i < ch_cnt; i++) {
 		idx = (ch_num[i] - BASE_CH_NUM);
 		sph[i] = tx[idx].sph;
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 5dbf839..44228a6 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1625,6 +1625,11 @@
 		  MMC_QUIRK_BLK_NO_CMD23),
 	MMC_FIXUP("MMC32G", 0x11, CID_OEMID_ANY, add_quirk_mmc,
 		  MMC_QUIRK_BLK_NO_CMD23),
+
+	/* Some INAND MCP devices advertise incorrect timeout values */
+	MMC_FIXUP("SEM04G", 0x45, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_INAND_DATA_TIMEOUT),
+
 	END_FIXUP
 };
 
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index ca86323..843a707 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -523,6 +523,11 @@
 				data->timeout_ns =  100000000;	/* 100ms */
 		}
 	}
+	/* Increase the timeout values for some bad INAND MCP devices */
+	if (card->quirks & MMC_QUIRK_INAND_DATA_TIMEOUT) {
+		data->timeout_ns = 4000000000u; /* 4s */
+		data->timeout_clks = 0;
+	}
 }
 EXPORT_SYMBOL(mmc_set_data_timeout);
 
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index aa1a589..b0439bc 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -132,6 +132,10 @@
 	unsigned int		rconn_mohm;
 	struct mutex		last_ocv_uv_mutex;
 	int			last_ocv_uv;
+	int			last_cc_uah; /* used for Iavg calc for UUC */
+	struct timeval		t;
+	int			last_uuc_uah;
+	int			enable_fcc_learning;
 };
 
 static struct pm8921_bms_chip *the_chip;
@@ -966,6 +970,8 @@
 		convert_vbatt_raw_to_uv(chip, usb_chg,
 			raw->last_good_ocv_raw, &raw->last_good_ocv_uv);
 		chip->last_ocv_uv = raw->last_good_ocv_uv;
+		/* forget the old cc value upon ocv */
+		chip->last_cc_uah = 0;
 	} else {
 		raw->last_good_ocv_uv = chip->last_ocv_uv;
 	}
@@ -1147,20 +1153,128 @@
 	*val = cc_uah;
 }
 
-static int calculate_unusable_charge_uah(struct pm8921_bms_chip *chip,
-				int rbatt, int fcc_uah,
-				int batt_temp, int chargecycles)
+static int calculate_uuc_uah_at_given_current(struct pm8921_bms_chip *chip,
+				 int batt_temp, int chargecycles,
+				int rbatt, int fcc_uah, int i_ma)
 {
-	int voltage_unusable_uv, pc_unusable;
+	int unusable_uv, pc_unusable, uuc;
 
-	/* calculate unusable charge */
-	voltage_unusable_uv = (rbatt * chip->i_test)
-						+ (chip->v_failure * 1000);
-	pc_unusable = calculate_pc(chip, voltage_unusable_uv,
-						batt_temp, chargecycles);
-	pr_debug("rbatt = %umilliOhms unusable_v =%d unusable_pc = %d\n",
-			rbatt, voltage_unusable_uv, pc_unusable);
-	return (fcc_uah * pc_unusable) / 100;
+	/* calculate unusable charge with itest */
+	unusable_uv = (rbatt * i_ma) + (chip->v_failure * 1000);
+	pc_unusable = calculate_pc(chip, unusable_uv, batt_temp, chargecycles);
+	uuc = (fcc_uah * pc_unusable) / 100;
+	pr_debug("For i_ma = %d, unusable_uv = %d unusable_pc = %d uuc = %d\n",
+					i_ma, unusable_uv, pc_unusable, uuc);
+	return uuc;
+}
+
+/* soc_rbatt when uuc_reported should be equal to uuc_now */
+#define SOC_RBATT_CHG		80
+#define SOC_RBATT_DISCHG	10
+static int calculate_unusable_charge_uah(struct pm8921_bms_chip *chip,
+				int rbatt, int fcc_uah, int cc_uah,
+				int soc_rbatt, int batt_temp, int chargecycles)
+{
+	struct timeval now;
+	int delta_time_s;
+	int delta_cc_uah;
+	int iavg_ua, iavg_ma;
+	int uuc_uah_itest, uuc_uah_iavg, uuc_now, uuc_reported;
+	s64 stepsize = 0;
+	int firsttime = 0;
+
+	delta_cc_uah = cc_uah - chip->last_cc_uah;
+	do_gettimeofday(&now);
+	if (chip->t.tv_sec != 0) {
+		delta_time_s = (now.tv_sec - chip->t.tv_sec);
+	} else {
+		/* uuc calculation for the first time */
+		delta_time_s = 0;
+		firsttime = 1;
+	}
+
+	if (delta_time_s != 0)
+		iavg_ua = div_s64((s64)delta_cc_uah * 3600, delta_time_s);
+	else
+		iavg_ua = 0;
+
+	iavg_ma = iavg_ua/1000;
+
+	pr_debug("t.tv_sec = %d, now.tv_sec = %d\n", (int)chip->t.tv_sec,
+				(int)now.tv_sec);
+
+	pr_debug("delta_time_s = %d iavg_ma = %d\n", delta_time_s, iavg_ma);
+
+	if (iavg_ma == 0) {
+		pr_debug("Iavg = 0 returning last uuc = %d\n",
+				chip->last_uuc_uah);
+		uuc_reported = chip->last_uuc_uah;
+		goto out;
+	}
+
+	/* calculate unusable charge with itest */
+	uuc_uah_itest = calculate_uuc_uah_at_given_current(chip,
+					batt_temp, chargecycles,
+					rbatt, fcc_uah, chip->i_test);
+
+	pr_debug("itest = %d uuc_itest = %d\n", chip->i_test, uuc_uah_itest);
+
+	/* calculate unusable charge with iavg */
+	iavg_ma = max(0, iavg_ma);
+	uuc_uah_iavg = calculate_uuc_uah_at_given_current(chip,
+					batt_temp, chargecycles,
+					rbatt, fcc_uah, iavg_ma);
+	pr_debug("iavg = %d uuc_iavg = %d\n", iavg_ma, uuc_uah_iavg);
+
+	if (firsttime) {
+		if (cc_uah < chip->last_cc_uah)
+			chip->last_uuc_uah = uuc_uah_itest;
+		else
+			chip->last_uuc_uah = uuc_uah_iavg;
+		pr_debug("firsttime uuc_prev = %d\n", chip->last_uuc_uah);
+	}
+
+	uuc_now = min(uuc_uah_itest, uuc_uah_iavg);
+
+	uuc_reported = -EINVAL;
+	if (cc_uah < chip->last_cc_uah) {
+		/* charging */
+		if (uuc_now < chip->last_uuc_uah) {
+			stepsize = max(1, (SOC_RBATT_CHG - soc_rbatt));
+			/* uuc_reported = uuc_prev + deltauuc / stepsize */
+			uuc_reported = div_s64 (stepsize * chip->last_uuc_uah
+					+ (uuc_now - chip->last_uuc_uah),
+					stepsize);
+			uuc_reported = max(0, uuc_reported);
+		}
+	} else {
+		if (uuc_now > chip->last_uuc_uah) {
+			stepsize = max(1, (soc_rbatt - SOC_RBATT_DISCHG));
+			/* uuc_reported = uuc_prev + deltauuc / stepsize */
+			uuc_reported = div_s64 (stepsize * chip->last_uuc_uah
+					+ (uuc_now - chip->last_uuc_uah),
+					stepsize);
+			uuc_reported = max(0, uuc_reported);
+		}
+	}
+	if (uuc_reported == -EINVAL)
+		uuc_reported = chip->last_uuc_uah;
+
+	pr_debug("uuc_now = %d uuc_prev = %d stepsize = %d uuc_reported = %d\n",
+			uuc_now, chip->last_uuc_uah, (int)stepsize,
+			uuc_reported);
+
+out:
+	/* remember the reported uuc */
+	chip->last_uuc_uah = uuc_reported;
+
+	/* remember cc_uah */
+	chip->last_cc_uah = cc_uah;
+
+	/* remember this time */
+	chip->t = now;
+
+	return uuc_reported;
 }
 
 /* calculate remainging charge at the time of ocv */
@@ -1211,7 +1325,9 @@
 	*rbatt = get_rbatt(chip, soc_rbatt, batt_temp);
 
 	*unusable_charge_uah = calculate_unusable_charge_uah(chip, *rbatt,
-					*fcc_uah, batt_temp, chargecycles);
+					*fcc_uah, *cc_uah, soc_rbatt,
+					batt_temp,
+					chargecycles);
 	pr_debug("UUC = %uuAh\n", *unusable_charge_uah);
 }
 
@@ -1644,6 +1760,8 @@
 #define OCV_TOL_MASK			0xF0
 #define IBAT_TOL_DEFAULT	0x03
 #define IBAT_TOL_NOCHG		0x0F
+#define OCV_TOL_DEFAULT		0x20
+#define OCV_TOL_NO_OCV		0x00
 void pm8921_bms_charging_began(void)
 {
 	int batt_temp, rc;
@@ -1705,7 +1823,7 @@
 
 	bms_end_ocv_uv = raw.last_good_ocv_uv;
 
-	if (is_battery_full
+	if (is_battery_full && the_chip->enable_fcc_learning
 		&& the_chip->start_percent <= MIN_START_PERCENT_FOR_LEARNING) {
 		int fcc_uah, new_fcc_uah, delta_fcc_uah;
 
@@ -1745,6 +1863,11 @@
 
 		the_chip->last_ocv_uv = the_chip->max_voltage_uv;
 		raw.last_good_ocv_uv = the_chip->max_voltage_uv;
+		/*
+		 * since we are treating this as an ocv event
+		 * forget the old cc value
+		 */
+		the_chip->last_cc_uah = 0;
 		pr_debug("EOC ocv_reading = 0x%x cc = 0x%x\n",
 				the_chip->ocv_reading_at_100,
 				the_chip->cc_reading_at_100);
@@ -1776,6 +1899,22 @@
 }
 EXPORT_SYMBOL_GPL(pm8921_bms_charging_end);
 
+int pm8921_bms_stop_ocv_updates(struct pm8921_bms_chip *chip)
+{
+	pr_debug("stopping ocv updates\n");
+	return pm_bms_masked_write(chip, BMS_TOLERANCES,
+			OCV_TOL_MASK, OCV_TOL_NO_OCV);
+}
+EXPORT_SYMBOL_GPL(pm8921_bms_stop_ocv_updates);
+
+int pm8921_bms_start_ocv_updates(struct pm8921_bms_chip *chip)
+{
+	pr_debug("stopping ocv updates\n");
+	return pm_bms_masked_write(chip, BMS_TOLERANCES,
+			OCV_TOL_MASK, OCV_TOL_DEFAULT);
+}
+EXPORT_SYMBOL_GPL(pm8921_bms_start_ocv_updates);
+
 static irqreturn_t pm8921_bms_sbi_write_ok_handler(int irq, void *data)
 {
 	pr_debug("irq = %d triggered", irq);
@@ -2110,6 +2249,8 @@
 	CALIB_HKADC,
 	CALIB_CCADC,
 	GET_VBAT_VSENSE_SIMULTANEOUS,
+	STOP_OCV,
+	START_OCV,
 };
 
 static int test_batt_temp = 5;
@@ -2202,13 +2343,30 @@
 		pm8921_bms_get_simultaneous_battery_voltage_and_current(
 			&ibat_ua,
 			&vbat_uv);
+	default:
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int set_calc(void *data, u64 val)
+{
+	int param = (int)data;
+	int ret = 0;
+
+	switch (param) {
+	case STOP_OCV:
+		pm8921_bms_stop_ocv_updates(the_chip);
+		break;
+	case START_OCV:
+		pm8921_bms_start_ocv_updates(the_chip);
 		break;
 	default:
 		ret = -EINVAL;
 	}
 	return ret;
 }
-DEFINE_SIMPLE_ATTRIBUTE(calc_fops, get_calc, NULL, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(calc_fops, get_calc, set_calc, "%llu\n");
 
 static int get_reading(void *data, u64 * val)
 {
@@ -2346,6 +2504,10 @@
 				(void *)CALIB_HKADC, &calc_fops);
 	debugfs_create_file("calib_ccadc", 0644, chip->dent,
 				(void *)CALIB_CCADC, &calc_fops);
+	debugfs_create_file("stop_ocv", 0644, chip->dent,
+				(void *)STOP_OCV, &calc_fops);
+	debugfs_create_file("start_ocv", 0644, chip->dent,
+				(void *)START_OCV, &calc_fops);
 
 	debugfs_create_file("simultaneous", 0644, chip->dent,
 			(void *)GET_VBAT_VSENSE_SIMULTANEOUS, &calc_fops);
@@ -2467,6 +2629,7 @@
 	chip->ref1p25v_channel = pdata->bms_cdata.ref1p25v_channel;
 	chip->batt_id_channel = pdata->bms_cdata.batt_id_channel;
 	chip->revision = pm8xxx_get_revision(chip->dev->parent);
+	chip->enable_fcc_learning = pdata->enable_fcc_learning;
 	INIT_WORK(&chip->calib_hkadc_work, calibrate_hkadc_work);
 
 	rc = request_irqs(chip, pdev);
diff --git a/drivers/usb/gadget/ci13xxx_msm_hsic.c b/drivers/usb/gadget/ci13xxx_msm_hsic.c
index c74b69a..eeacceb 100644
--- a/drivers/usb/gadget/ci13xxx_msm_hsic.c
+++ b/drivers/usb/gadget/ci13xxx_msm_hsic.c
@@ -283,6 +283,12 @@
 	return 0;
 }
 
+static void msm_hsic_wakeup(void)
+{
+	if (atomic_read(&the_mhsic->in_lpm))
+		pm_runtime_resume(the_mhsic->dev);
+}
+
 static void msm_hsic_start(void)
 {
 	int ret;
@@ -580,6 +586,10 @@
 		dev_dbg(dev, "CI13XXX_CONTROLLER_SUSPEND_EVENT received\n");
 		queue_work(mhsic->wq, &mhsic->suspend_w);
 		break;
+	case CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT:
+		dev_dbg(dev, "CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT received\n");
+		msm_hsic_wakeup();
+		break;
 	default:
 		dev_dbg(dev, "unknown ci13xxx_udc event\n");
 		break;
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 54d041a..d754a88 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -1476,6 +1476,15 @@
 		dbg_trace("remote wakeup feature is not enabled\n");
 		goto out;
 	}
+	spin_unlock_irqrestore(udc->lock, flags);
+
+	udc->udc_driver->notify_event(udc,
+		CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT);
+
+	if (udc->transceiver)
+		otg_set_suspend(udc->transceiver, 0);
+
+	spin_lock_irqsave(udc->lock, flags);
 	if (!hw_cread(CAP_PORTSC, PORTSC_SUSP)) {
 		ret = -EINVAL;
 		dbg_trace("port is not suspended\n");
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 0c811e1..8e2b093 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -120,9 +120,10 @@
 #define CI13XXX_ZERO_ITC		BIT(4)
 #define CI13XXX_IS_OTG			BIT(5)
 
-#define CI13XXX_CONTROLLER_RESET_EVENT		0
-#define CI13XXX_CONTROLLER_CONNECT_EVENT	1
-#define CI13XXX_CONTROLLER_SUSPEND_EVENT	2
+#define CI13XXX_CONTROLLER_RESET_EVENT			0
+#define CI13XXX_CONTROLLER_CONNECT_EVENT		1
+#define CI13XXX_CONTROLLER_SUSPEND_EVENT		2
+#define CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT	3
 	void	(*notify_event) (struct ci13xxx *udc, unsigned event);
 };
 
diff --git a/drivers/usb/gadget/f_accessory.c b/drivers/usb/gadget/f_accessory.c
index 0187b69..9f14b09 100644
--- a/drivers/usb/gadget/f_accessory.c
+++ b/drivers/usb/gadget/f_accessory.c
@@ -296,7 +296,7 @@
 	}
 }
 
-static int __init create_bulk_endpoints(struct acc_dev *dev,
+static int create_bulk_endpoints(struct acc_dev *dev,
 				struct usb_endpoint_descriptor *in_desc,
 				struct usb_endpoint_descriptor *out_desc)
 {
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index 4dc3c80..537e0b5 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -118,6 +118,8 @@
  *			calculated or the peak system current (mA)
  * @v_failure:		the voltage at which the battery is considered empty(mV)
  * @calib_delay_ms:	how often should the adc calculate gain and offset
+ * @enable_fcc_learning:	if set the driver will learn full charge
+ *				capacity of the battery upon end of charge
  */
 struct pm8921_bms_platform_data {
 	struct pm8xxx_bms_core_data	bms_cdata;
@@ -128,6 +130,7 @@
 	unsigned int			calib_delay_ms;
 	unsigned int			max_voltage_uv;
 	unsigned int			rconn_mohm;
+	int				enable_fcc_learning;
 };
 
 #if defined(CONFIG_PM8921_BMS) || defined(CONFIG_PM8921_BMS_MODULE)
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 0fcae7c..8a0c4d5 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -202,6 +202,7 @@
 #define MMC_QUIRK_DISABLE_CD	(1<<5)		/* disconnect CD/DAT[3] resistor */
 #define MMC_QUIRK_INAND_CMD38	(1<<6)		/* iNAND devices have broken CMD38 */
 #define MMC_QUIRK_BLK_NO_CMD23	(1<<7)		/* Avoid CMD23 for regular multiblock */
+#define MMC_QUIRK_INAND_DATA_TIMEOUT  (1<<8)    /* For incorrect data timeout */
 	unsigned int    poweroff_notify_state;	/* eMMC4.5 notify feature */
 #define MMC_NO_POWER_NOTIFICATION	0
 #define MMC_POWERED_ON			1
diff --git a/include/sound/soc.h b/include/sound/soc.h
index f51b006..12a8fd5 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -814,6 +814,7 @@
 	struct list_head list;
 	struct mutex mutex;
 	struct mutex dapm_mutex;
+	struct mutex dapm_power_mutex;
 	struct mutex dsp_mutex;
 	spinlock_t dsp_spinlock;
 
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 8c07206..95c6b1d 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1530,7 +1530,7 @@
 	if (PCM_RUNTIME_CHECK(substream))
 		return -ENXIO;
 	runtime = substream->runtime;
-	pr_err("%s called with cmd = %d\n", __func__, cmd);
+	pr_debug("%s called with cmd = %d\n", __func__, cmd);
 	err = substream->ops->ioctl(substream, cmd, arg);
 	return err;
 }
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index 961f833..ea05a58e 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -57,6 +57,14 @@
 #define GPIO_SEC_I2S_RX_MCLK 50
 #define I2S_MCLK_RATE 1536000
 
+#define GPIO_MI2S_WS     27
+#define GPIO_MI2S_SCLK   28
+#define GPIO_MI2S_DOUT3  29
+#define GPIO_MI2S_DOUT2  30
+#define GPIO_MI2S_DOUT1  31
+#define GPIO_MI2S_DOUT0  32
+#define GPIO_MI2S_MCLK   33
+
 static struct clk *sec_i2s_rx_osr_clk;
 static struct clk *sec_i2s_rx_bit_clk;
 
@@ -84,6 +92,41 @@
 	},
 };
 
+static struct request_gpio mi2s_gpio[] = {
+	{
+		.gpio_no = GPIO_MI2S_WS,
+		.gpio_name = "MI2S_WS",
+	},
+	{
+		.gpio_no = GPIO_MI2S_SCLK,
+		.gpio_name = "MI2S_SCLK",
+	},
+	{
+		.gpio_no = GPIO_MI2S_DOUT3,
+		.gpio_name = "MI2S_DOUT3",
+	},
+	{
+		.gpio_no = GPIO_MI2S_DOUT2,
+		.gpio_name = "MI2S_DOUT2",
+	},
+	{
+		.gpio_no = GPIO_MI2S_DOUT1,
+		.gpio_name = "MI2S_DOUT1",
+	},
+	{
+		.gpio_no = GPIO_MI2S_DOUT0,
+		.gpio_name = "MI2S_DOUT0",
+	},
+	{
+		.gpio_no = GPIO_MI2S_MCLK,
+		.gpio_name = "MI2S_MCLK",
+	},
+};
+
+static struct clk *mi2s_bit_clk;
+
+
+
 static u32 top_spk_pamp_gpio  = PM8921_GPIO_PM_TO_SYS(18);
 static u32 bottom_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(19);
 static int msm_spk_control;
@@ -736,7 +779,7 @@
 	},
 };
 
-static struct snd_soc_dsp_link slimbus0_hl_media = {
+static struct snd_soc_dsp_link bidir_hl_media = {
 	.playback = true,
 	.capture = true,
 	.trigger = {
@@ -745,8 +788,7 @@
 	},
 };
 
-static struct snd_soc_dsp_link int_fm_hl_media = {
-	.playback = true,
+static struct snd_soc_dsp_link tx_hl_media = {
 	.capture = true,
 	.trigger = {
 		SND_SOC_DSP_TRIGGER_POST,
@@ -754,6 +796,14 @@
 	},
 };
 
+
+static struct snd_soc_dsp_link rx_hl_media = {
+	.playback = true,
+	.trigger = {
+		SND_SOC_DSP_TRIGGER_POST,
+		SND_SOC_DSP_TRIGGER_POST
+	},
+};
 static int msm_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 			struct snd_pcm_hw_params *params)
 {
@@ -815,6 +865,71 @@
 	return 0;
 }
 
+static int msm_mi2s_free_gpios(void)
+{
+	int	i;
+	for (i = 0; i < ARRAY_SIZE(mi2s_gpio); i++)
+		gpio_free(mi2s_gpio[i].gpio_no);
+	return 0;
+}
+
+static void msm_mi2s_shutdown(struct snd_pcm_substream *substream)
+{
+	if (mi2s_bit_clk) {
+		clk_disable(mi2s_bit_clk);
+		clk_put(mi2s_bit_clk);
+		mi2s_bit_clk = NULL;
+	}
+	msm_mi2s_free_gpios();
+}
+
+static int configure_mi2s_gpio(void)
+{
+	int	rtn;
+	int	i;
+	int	j;
+	for (i = 0; i < ARRAY_SIZE(mi2s_gpio); i++) {
+		rtn = gpio_request(mi2s_gpio[i].gpio_no,
+						   mi2s_gpio[i].gpio_name);
+		pr_debug("%s: gpio = %d, gpio name = %s, rtn = %d\n",
+				 __func__,
+				 mi2s_gpio[i].gpio_no,
+				 mi2s_gpio[i].gpio_name,
+				 rtn);
+		if (rtn) {
+			pr_err("%s: Failed to request gpio %d\n",
+				   __func__,
+				   mi2s_gpio[i].gpio_no);
+			for (j = i; j >= 0; j--)
+				gpio_free(mi2s_gpio[j].gpio_no);
+			goto err;
+		}
+	}
+err:
+	return rtn;
+}
+static int msm_mi2s_startup(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	configure_mi2s_gpio();
+	mi2s_bit_clk = clk_get(cpu_dai->dev, "bit_clk");
+	if (IS_ERR(mi2s_bit_clk))
+		return PTR_ERR(mi2s_bit_clk);
+	clk_set_rate(mi2s_bit_clk, 0);
+	ret = clk_enable(mi2s_bit_clk);
+	if (IS_ERR_VALUE(ret)) {
+		pr_err("Unable to enable mi2s_bit_clk\n");
+		clk_put(mi2s_bit_clk);
+		return ret;
+	}
+	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM);
+	if (IS_ERR_VALUE(ret))
+		pr_err("set format for CPU dai failed\n");
+	return ret;
+}
+
 static int msm_startup(struct snd_pcm_substream *substream)
 {
 	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
@@ -958,6 +1073,12 @@
 	.hw_params = mpq8064_sec_i2s_rx_hw_params,
 };
 
+static struct snd_soc_ops msm_mi2s_tx_be_ops = {
+	.startup = msm_mi2s_startup,
+	.shutdown = msm_mi2s_shutdown,
+};
+
+
 /* Digital audio interface glue - connects codec <---> CPU */
 static struct snd_soc_dai_link msm_dai[] = {
 	/* FrontEnd DAI Links */
@@ -1015,7 +1136,7 @@
 		.cpu_dai_name	= "SLIMBUS0_HOSTLESS",
 		.platform_name  = "msm-pcm-hostless",
 		.dynamic = 1,
-		.dsp_link = &slimbus0_hl_media,
+		.dsp_link = &bidir_hl_media,
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ignore_suspend = 1,
 		/* .be_id = do not care */
@@ -1026,7 +1147,7 @@
 		.cpu_dai_name	= "INT_FM_HOSTLESS",
 		.platform_name  = "msm-pcm-hostless",
 		.dynamic = 1,
-		.dsp_link = &int_fm_hl_media,
+		.dsp_link = &bidir_hl_media,
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ignore_suspend = 1,
 		/* .be_id = do not care */
@@ -1064,11 +1185,47 @@
 		.cpu_dai_name = "VOICE_STUB",
 		.platform_name = "msm-pcm-hostless",
 		.dynamic = 1,
-		.dsp_link = &fe_media,
+		.dsp_link = &bidir_hl_media,
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ignore_suspend = 1,
 		/* .be_id = do not care */
 	},
+	/* MI2S TX Hostless */
+	{
+		.name = "MI2S_TX Hostless",
+		.stream_name = "MI2S_TX Hostless",
+		.cpu_dai_name = "MI2S_TX_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dsp_link = &tx_hl_media,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.no_codec = 1,
+		.ignore_suspend = 1,
+	},
+	/* HDMI Hostless */
+	{
+		.name = "HDMI_RX_HOSTLESS",
+		.stream_name = "HDMI_RX_HOSTLESS",
+		.cpu_dai_name = "HDMI_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dsp_link = &rx_hl_media,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.no_codec = 1,
+		.ignore_suspend = 1,
+	},
+	/* Secondary I2S RX Hostless */
+	{
+		.name = "SEC_I2S_RX Hostless",
+		.stream_name = "SEC_I2S_RX Hostless",
+		.cpu_dai_name = "SEC_I2S_RX_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dsp_link = &rx_hl_media,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.no_codec = 1,
+		.ignore_suspend = 1,
+	},
 	/* Backend DAI Links */
 	{
 		.name = LPASS_BE_SLIMBUS_0_RX,
@@ -1142,6 +1299,19 @@
 		.be_id = MSM_BACKEND_DAI_HDMI_RX,
 		.be_hw_params_fixup = msm_hdmi_be_hw_params_fixup,
 	},
+	{
+		.name = LPASS_BE_MI2S_TX,
+		.stream_name = "MI2S Capture",
+		.cpu_dai_name = "msm-dai-q6.7",
+		.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_MI2S_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_tx_be_ops,
+	},
 	/* Backend AFE DAI Links */
 	{
 		.name = LPASS_BE_AFE_PCM_RX,
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index b3fb7c1..cb760fa 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -29,6 +29,7 @@
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
 #include <linux/android_pmem.h>
+#include <sound/timer.h>
 
 #include "msm-compr-q6.h"
 #include "msm-pcm-routing.h"
@@ -92,6 +93,9 @@
 		prtd->pcm_irq_pos += prtd->pcm_count;
 		if (atomic_read(&prtd->start))
 			snd_pcm_period_elapsed(substream);
+		else
+			if (substream->timer_running)
+				snd_timer_interrupt(substream->timer, 1);
 		atomic_inc(&prtd->out_count);
 		wake_up(&the_locks.write_wait);
 		if (!atomic_read(&prtd->start)) {
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 3f86962..23134ea 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -315,6 +315,32 @@
 		.ops = &msm_fe_dai_ops,
 		.name = "VoLTE",
 	},
+	{
+		.capture = {
+			.stream_name = "MI2S_TX Hostless Capture",
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 8,
+			.rate_min =     8000,
+			.rate_max =    48000,
+		},
+		.ops = &msm_fe_dai_ops,
+		.name = "MI2S_TX_HOSTLESS",
+	},
+	{
+		.playback = {
+			.stream_name = "SEC_I2S_RX Hostless 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,
+		},
+		.ops = &msm_fe_dai_ops,
+		.name = "SEC_I2S_RX_HOSTLESS",
+	},
 };
 
 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 a53dd44..c1304c8 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -90,6 +90,9 @@
 	SOC_ENUM_EXT("SEC RX Format", mi2s_config_enum[0],
 				 msm_dai_q6_mi2s_format_get,
 				 msm_dai_q6_mi2s_format_put),
+	SOC_ENUM_EXT("MI2S TX Format", mi2s_config_enum[0],
+				 msm_dai_q6_mi2s_format_get,
+				 msm_dai_q6_mi2s_format_put),
 };
 
 static u8 num_of_bits_set(u8 sd_line_mask)
@@ -238,7 +241,8 @@
 	}
 	if (mi2s_pdata->capability == MSM_MI2S_CAP_RX)
 		dai_driver->playback.channels_max = num_of_sd_lines << 1;
-
+	else if (mi2s_pdata->capability == MSM_MI2S_CAP_TX)
+		dai_driver->capture.channels_max = num_of_sd_lines << 1;
 	return 0;
 
 error_invalid_data:
@@ -381,6 +385,7 @@
 		rc = msm_dai_q6_cdc_hw_params(params, dai, substream->stream);
 		break;
 	case MI2S_RX:
+	case MI2S_TX:
 		rc = msm_dai_q6_mi2s_hw_params(params, dai, substream->stream);
 		break;
 	case SLIMBUS_0_RX:
@@ -787,12 +792,13 @@
 		kfree(dai_data);
 		goto rtn;
 	}
-	if (mi2s_pdata->capability == MSM_MI2S_CAP_RX) {
+	if (mi2s_pdata->capability == MSM_MI2S_CAP_RX)
 		kcontrol = &mi2s_config_controls[0];
-		rc = snd_ctl_add(dai->card->snd_card,
-					snd_ctl_new1(kcontrol, dai_data));
-	}
+	else
+		kcontrol = &mi2s_config_controls[2];
 
+	rc = snd_ctl_add(dai->card->snd_card,
+					 snd_ctl_new1(kcontrol, dai_data));
 rtn:
 	return rc;
 }
@@ -861,6 +867,7 @@
 	case PRIMARY_I2S_TX:
 	case PRIMARY_I2S_RX:
 	case MI2S_RX:
+	case MI2S_TX:
 	case SECONDARY_I2S_RX:
 		rc = msm_dai_q6_cdc_set_fmt(dai, fmt);
 		break;
@@ -1176,6 +1183,20 @@
 	.remove = msm_dai_q6_dai_probe,
 };
 
+static struct snd_soc_dai_driver msm_dai_q6_mi2s_tx_dai = {
+	.capture = {
+		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+		SNDRV_PCM_RATE_16000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &msm_dai_q6_ops,
+	.probe = msm_dai_q6_dai_mi2s_probe,
+	.remove = msm_dai_q6_dai_remove,
+};
+
 static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_rx_dai = {
 	.playback = {
 		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
@@ -1247,6 +1268,10 @@
 		rc = snd_soc_register_dai(&pdev->dev,
 					&msm_dai_q6_mi2s_rx_dai);
 		break;
+	case MI2S_TX:
+		rc = snd_soc_register_dai(&pdev->dev,
+					&msm_dai_q6_mi2s_tx_dai);
+		break;
 	case SLIMBUS_0_RX:
 	case SLIMBUS_4_RX:
 		rc = snd_soc_register_dai(&pdev->dev,
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 0f74afb..18001b0 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -128,6 +128,7 @@
 	{ VOICE_RECORD_RX, 0, 0, 0, 0, 0},
 	{ VOICE_RECORD_TX, 0, 0, 0, 0, 0},
 	{ MI2S_RX, 0, 0, 0, 0, 0},
+	{ MI2S_TX, 0, 0, 0, 0},
 	{ SECONDARY_I2S_RX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_1_RX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_1_TX, 0, 0, 0, 0, 0},
@@ -1023,6 +1024,9 @@
 	SOC_SINGLE_EXT("PRI_TX", MSM_BACKEND_DAI_PRI_I2S_TX,
 		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
 		msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_MI2S_TX,
+		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+		msm_routing_put_audio_mixer),
 	SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
 		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
 		msm_routing_put_audio_mixer),
@@ -1053,6 +1057,9 @@
 	SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_MI2S_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = {
@@ -1164,6 +1171,9 @@
 	SOC_SINGLE_EXT("PRI_TX_Voice", MSM_BACKEND_DAI_PRI_I2S_TX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("MI2S_TX_Voice", MSM_BACKEND_DAI_MI2S_TX,
+	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 	SOC_SINGLE_EXT("SLIM_0_TX_Voice", MSM_BACKEND_DAI_SLIMBUS_0_TX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
@@ -1200,6 +1210,9 @@
 	SOC_SINGLE_EXT("PRI_TX_Voip", MSM_BACKEND_DAI_PRI_I2S_TX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("MI2S_TX_Voip", MSM_BACKEND_DAI_MI2S_TX,
+	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 	SOC_SINGLE_EXT("SLIM_0_TX_Voip", MSM_BACKEND_DAI_SLIMBUS_0_TX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
@@ -1236,6 +1249,9 @@
 	SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
 	MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
 	msm_routing_put_port_mixer),
+	SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+	MSM_BACKEND_DAI_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
 };
 
 static const struct snd_kcontrol_new auxpcm_rx_port_mixer_controls[] = {
@@ -1265,6 +1281,19 @@
 	msm_routing_put_port_mixer),
 };
 
+
+static const struct snd_kcontrol_new hdmi_rx_port_mixer_controls[] = {
+	SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_BACKEND_DAI_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+};
+
+static const struct snd_kcontrol_new sec_i2s_rx_port_mixer_controls[] = {
+	SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_BACKEND_DAI_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+};
+
 static const struct snd_kcontrol_new fm_switch_mixer_controls =
 	SOC_SINGLE_EXT("Switch", SND_SOC_NOPM,
 	0, 1, 0, msm_routing_get_switch_mixer,
@@ -1499,10 +1528,14 @@
 	SND_SOC_DAPM_AIF_OUT("INTFM_UL_HL", "INT_FM_HOSTLESS Capture",
 		0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("HDMI_DL_HL", "HDMI_HOSTLESS Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("SEC_I2S_DL_HL", "SEC_I2S_RX_HOSTLESS Playback",
+		0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("AUXPCM_DL_HL", "AUXPCM_HOSTLESS Playback",
 		0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("AUXPCM_UL_HL", "AUXPCM_HOSTLESS Capture",
 		0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("MI2S_UL_HL", "MI2S_TX_HOSTLESS Capture",
+		0, 0, 0, 0),
 
 	/* Backend AIF */
 	/* Stream name equals to backend dai link stream name
@@ -1514,6 +1547,7 @@
 	SND_SOC_DAPM_AIF_OUT("HDMI", "HDMI Playback", 0, 0, 0 , 0),
 	SND_SOC_DAPM_AIF_OUT("MI2S_RX", "MI2S Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("PRI_I2S_TX", "Primary I2S Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MI2S_TX", "MI2S Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("INT_BT_SCO_RX", "Internal BT-SCO Playback",
 				0, 0, 0 , 0),
@@ -1641,6 +1675,12 @@
 	SND_SOC_DAPM_MIXER("AFE_PCM_RX Port Mixer",
 	SND_SOC_NOPM, 0, 0, afe_pcm_rx_port_mixer_controls,
 	ARRAY_SIZE(afe_pcm_rx_port_mixer_controls)),
+	SND_SOC_DAPM_MIXER("HDMI_RX Port Mixer",
+	SND_SOC_NOPM, 0, 0, hdmi_rx_port_mixer_controls,
+	ARRAY_SIZE(hdmi_rx_port_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SEC_I2S_RX Port Mixer",
+	SND_SOC_NOPM, 0, 0, sec_i2s_rx_port_mixer_controls,
+	ARRAY_SIZE(sec_i2s_rx_port_mixer_controls)),
 };
 
 static const struct snd_soc_dapm_route intercon[] = {
@@ -1686,6 +1726,8 @@
 	{"MI2S_RX", NULL, "MI2S_RX Audio Mixer"},
 
 	{"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
+	{"MultiMedia1 Mixer", "MI2S_TX", "MI2S_TX"},
+	{"MultiMedia2 Mixer", "MI2S_TX", "MI2S_TX"},
 	{"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
 
@@ -1758,6 +1800,7 @@
 	{"HDMI", NULL, "HDMI_DL_HL"},
 
 	{"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
+	{"Voice_Tx Mixer", "MI2S_TX_Voice", "MI2S_TX"},
 	{"Voice_Tx Mixer", "SLIM_0_TX_Voice", "SLIMBUS_0_TX"},
 	{"Voice_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice", "INT_BT_SCO_TX"},
 	{"Voice_Tx Mixer", "AFE_PCM_TX_Voice", "PCM_TX"},
@@ -1770,6 +1813,7 @@
 	{"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", "MI2S_TX_Voip", "MI2S_TX"},
 	{"Voip_Tx Mixer", "SLIM_0_TX_Voip", "SLIMBUS_0_TX"},
 	{"Voip_Tx Mixer", "INTERNAL_BT_SCO_TX_Voip", "INT_BT_SCO_TX"},
 	{"Voip_Tx Mixer", "AFE_PCM_TX_Voip", "PCM_TX"},
@@ -1785,11 +1829,13 @@
 	{"AUXPCM_UL_HL", NULL, "AUX_PCM_TX"},
 	{"PCM_RX_DL_HL", "Switch", "SLIM0_DL_HL"},
 	{"PCM_RX", NULL, "PCM_RX_DL_HL"},
+	{"MI2S_UL_HL", NULL, "MI2S_TX"},
+	{"SEC_I2S_RX", NULL, "SEC_I2S_DL_HL"},
 	{"SLIMBUS_0_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
 	{"SLIMBUS_0_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"SLIMBUS_0_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
+	{"SLIMBUS_0_RX Port Mixer", "MI2S_TX", "MI2S_TX"},
 	{"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Port Mixer"},
-
 	{"AFE_PCM_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
 	{"PCM_RX", NULL, "AFE_PCM_RX Port Mixer"},
 
@@ -1812,6 +1858,12 @@
 	{"SLIMBUS_1_RX", NULL, "SLIMBUS_1_RX Port Mixer"},
 	{"INTERNAL_BT_SCO_RX Port Mixer", "SLIM_1_TX", "SLIMBUS_1_TX"},
 	{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX Port Mixer"},
+
+	{"HDMI_RX Port Mixer", "MI2S_TX", "MI2S_TX"},
+	{"HDMI", NULL, "HDMI_RX Port Mixer"},
+
+	{"SEC_I2S_RX Port Mixer", "MI2S_TX", "MI2S_TX"},
+	{"SEC_I2S_RX", NULL, "SEC_I2S_RX Port Mixer"},
 };
 
 static int msm_pcm_routing_hw_params(struct snd_pcm_substream *substream,
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index e5d8638..546c396 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -32,6 +32,7 @@
 #define LPASS_BE_SEC_I2S_RX "(Backend) SECONDARY_I2S_RX"
 
 #define LPASS_BE_MI2S_RX "(Backend) MI2S_RX"
+#define LPASS_BE_MI2S_TX "(Backend) MI2S_TX"
 #define LPASS_BE_STUB_RX "(Backend) STUB_RX"
 #define LPASS_BE_STUB_TX "(Backend) STUB_TX"
 #define LPASS_BE_SLIMBUS_1_RX "(Backend) SLIMBUS_1_RX"
@@ -81,6 +82,7 @@
 	MSM_BACKEND_DAI_INCALL_RECORD_RX,
 	MSM_BACKEND_DAI_INCALL_RECORD_TX,
 	MSM_BACKEND_DAI_MI2S_RX,
+	MSM_BACKEND_DAI_MI2S_TX,
 	MSM_BACKEND_DAI_SEC_I2S_RX,
 	MSM_BACKEND_DAI_SLIMBUS_1_RX,
 	MSM_BACKEND_DAI_SLIMBUS_1_TX,
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index abfadb8..44fab3f 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -254,6 +254,8 @@
 {
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 
+	mutex_lock(&dapm->codec->mutex);
+
 	pr_debug("%s: msm8960_spk_control = %d", __func__, msm8960_spk_control);
 	if (msm8960_spk_control == MSM8960_SPK_ON) {
 		snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
@@ -268,6 +270,7 @@
 	}
 
 	snd_soc_dapm_sync(dapm);
+	mutex_unlock(&dapm->codec->mutex);
 }
 
 static int msm8960_get_spk(struct snd_kcontrol *kcontrol,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index f47b0d3..4192609 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3811,6 +3811,7 @@
 	card->instantiated = 0;
 	mutex_init(&card->mutex);
 	mutex_init(&card->dapm_mutex);
+	mutex_init(&card->dapm_power_mutex);
 	mutex_init(&card->dsp_mutex);
 	spin_lock_init(&card->dsp_spinlock);
 
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 265df9e..2284f19 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1306,15 +1306,24 @@
 	struct snd_soc_dapm_context *cur_dapm = NULL;
 	int ret, i;
 	int *sort;
+	int nWidgets;
 
 	if (power_up)
 		sort = dapm_up_seq;
 	else
 		sort = dapm_down_seq;
 
+	nWidgets = ARRAY_SIZE(dapm_up_seq);
+
 	list_for_each_entry_safe(w, n, list, power_list) {
 		ret = 0;
 
+		if (!w->name)
+			continue;
+
+		if (!((w->id >= 0) && (w->id < nWidgets)))
+			continue;
+
 		/* Do we need to apply any queued changes? */
 		if (sort[w->id] != cur_sort || w->reg != cur_reg ||
 		    w->dapm != cur_dapm || w->subseq != cur_subseq) {
@@ -1500,6 +1509,8 @@
 
 	trace_snd_soc_dapm_start(card);
 
+	mutex_lock(&card->dapm_power_mutex);
+
 	list_for_each_entry(d, &card->dapm_list, list)
 		if (d->n_widgets || d->codec == NULL)
 			d->dev_power = 0;
@@ -1609,6 +1620,8 @@
 		"DAPM sequencing finished, waiting %dms\n", card->pop_time);
 	pop_wait(card->pop_time);
 
+	mutex_unlock(&card->dapm_power_mutex);
+
 	trace_snd_soc_dapm_done(card);
 
 	return 0;