Merge "msm: 9615: Add platform data for LTC4088 charger" into msm-3.0
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 3eeac92..2097e0a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1634,6 +1634,12 @@
 	def_bool n
 	depends on SPARSEMEM
 
+config ARCH_ENABLE_MEMORY_HOTPLUG
+	def_bool n
+
+config ARCH_ENABLE_MEMORY_HOTREMOVE
+	def_bool n
+
 config FORCE_MAX_ZONEORDER
 	int "Maximum zone order" if ARCH_SHMOBILE
 	range 11 64 if ARCH_SHMOBILE
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 7fcf9dc..fea7044 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/smp.h>
+#include <linux/cpu_pm.h>
 #include <linux/cpumask.h>
 #include <linux/io.h>
 #include <linux/syscore_ops.h>
@@ -282,7 +283,7 @@
 		return -EINVAL;
 
 	mask = 0xff << shift;
-	bit = 1 << (cpu + shift);
+	bit = 1 << (cpu_logical_map(cpu) + shift);
 
 	raw_spin_lock(&irq_controller_lock);
 	val = readl_relaxed(reg) & ~mask;
@@ -379,9 +380,15 @@
 	unsigned int irq_start)
 {
 	unsigned int gic_irqs, irq_limit, i;
+	u32 cpumask;
 	void __iomem *base = gic->dist_base;
-	u32 cpumask = 1 << smp_processor_id();
+	u32 cpu = 0;
 
+#ifdef CONFIG_SMP
+	cpu = cpu_logical_map(smp_processor_id());
+#endif
+
+	cpumask = 1 << cpu;
 	cpumask |= cpumask << 8;
 	cpumask |= cpumask << 16;
 
@@ -396,6 +403,8 @@
 	if (gic_irqs > 1020)
 		gic_irqs = 1020;
 
+	gic->gic_irqs = gic_irqs;
+
 	/*
 	 * Set all global interrupts to be level triggered, active low.
 	 */
@@ -467,6 +476,189 @@
     mb();
 }
 
+#ifdef CONFIG_CPU_PM
+/*
+ * Saves the GIC distributor registers during suspend or idle.  Must be called
+ * with interrupts disabled but before powering down the GIC.  After calling
+ * this function, no interrupts will be delivered by the GIC, and another
+ * platform-specific wakeup source must be enabled.
+ */
+static void gic_dist_save(unsigned int gic_nr)
+{
+	unsigned int gic_irqs;
+	void __iomem *dist_base;
+	int i;
+
+	if (gic_nr >= MAX_GIC_NR)
+		BUG();
+
+	gic_irqs = gic_data[gic_nr].gic_irqs;
+	dist_base = gic_data[gic_nr].dist_base;
+
+	if (!dist_base)
+		return;
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
+		gic_data[gic_nr].saved_spi_conf[i] =
+			readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+		gic_data[gic_nr].saved_spi_target[i] =
+			readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
+		gic_data[gic_nr].saved_spi_enable[i] =
+			readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
+}
+
+/*
+ * Restores the GIC distributor registers during resume or when coming out of
+ * idle.  Must be called before enabling interrupts.  If a level interrupt
+ * that occured while the GIC was suspended is still present, it will be
+ * handled normally, but any edge interrupts that occured will not be seen by
+ * the GIC and need to be handled by the platform-specific wakeup source.
+ */
+static void gic_dist_restore(unsigned int gic_nr)
+{
+	unsigned int gic_irqs;
+	unsigned int i;
+	void __iomem *dist_base;
+
+	if (gic_nr >= MAX_GIC_NR)
+		BUG();
+
+	gic_irqs = gic_data[gic_nr].gic_irqs;
+	dist_base = gic_data[gic_nr].dist_base;
+
+	if (!dist_base)
+		return;
+
+	writel_relaxed(0, dist_base + GIC_DIST_CTRL);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
+		writel_relaxed(gic_data[gic_nr].saved_spi_conf[i],
+			dist_base + GIC_DIST_CONFIG + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+		writel_relaxed(0xa0a0a0a0,
+			dist_base + GIC_DIST_PRI + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+		writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
+			dist_base + GIC_DIST_TARGET + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
+		writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
+			dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+	writel_relaxed(1, dist_base + GIC_DIST_CTRL);
+}
+
+static void gic_cpu_save(unsigned int gic_nr)
+{
+	int i;
+	u32 *ptr;
+	void __iomem *dist_base;
+	void __iomem *cpu_base;
+
+	if (gic_nr >= MAX_GIC_NR)
+		BUG();
+
+	dist_base = gic_data[gic_nr].dist_base;
+	cpu_base = gic_data[gic_nr].cpu_base;
+
+	if (!dist_base || !cpu_base)
+		return;
+
+	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
+	for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
+		ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
+	for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
+		ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
+
+}
+
+static void gic_cpu_restore(unsigned int gic_nr)
+{
+	int i;
+	u32 *ptr;
+	void __iomem *dist_base;
+	void __iomem *cpu_base;
+
+	if (gic_nr >= MAX_GIC_NR)
+		BUG();
+
+	dist_base = gic_data[gic_nr].dist_base;
+	cpu_base = gic_data[gic_nr].cpu_base;
+
+	if (!dist_base || !cpu_base)
+		return;
+
+	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
+	for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
+		writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
+	for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
+		writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(32, 4); i++)
+		writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4);
+
+	writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
+	writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
+}
+
+static int gic_notifier(struct notifier_block *self, unsigned long cmd,	void *v)
+{
+	int i;
+
+	for (i = 0; i < MAX_GIC_NR; i++) {
+		switch (cmd) {
+		case CPU_PM_ENTER:
+			gic_cpu_save(i);
+			break;
+		case CPU_PM_ENTER_FAILED:
+		case CPU_PM_EXIT:
+			gic_cpu_restore(i);
+			break;
+		case CPU_CLUSTER_PM_ENTER:
+			gic_dist_save(i);
+			break;
+		case CPU_CLUSTER_PM_ENTER_FAILED:
+		case CPU_CLUSTER_PM_EXIT:
+			gic_dist_restore(i);
+			break;
+		}
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block gic_notifier_block = {
+	.notifier_call = gic_notifier,
+};
+
+static void __init gic_pm_init(struct gic_chip_data *gic)
+{
+	gic->saved_ppi_enable = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
+		sizeof(u32));
+	BUG_ON(!gic->saved_ppi_enable);
+
+	gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
+		sizeof(u32));
+	BUG_ON(!gic->saved_ppi_conf);
+
+	cpu_pm_register_notifier(&gic_notifier_block);
+}
+#else
+static void __init gic_pm_init(struct gic_chip_data *gic)
+{
+}
+#endif
+
 void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
 	void __iomem *dist_base, void __iomem *cpu_base)
 {
@@ -482,8 +674,10 @@
 	if (gic_nr == 0)
 		gic_cpu_base_addr = cpu_base;
 
+	gic_chip.flags |= gic_arch_extn.flags;
 	gic_dist_init(gic, irq_start);
 	gic_cpu_init(gic);
+	gic_pm_init(gic);
 }
 
 void __cpuinit gic_secondary_init(unsigned int gic_nr)
@@ -506,7 +700,12 @@
 #ifdef CONFIG_SMP
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 {
-	unsigned long map = *cpus_addr(*mask);
+	int cpu;
+	unsigned long map = 0;
+
+	/* Convert our logical CPU mask into a physical one. */
+	for_each_cpu(cpu, mask)
+		map |= 1 << cpu_logical_map(cpu);
 
 	/*
 	 * Ensure that stores to Normal memory are visible to the
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 83d012c..9f3d72b 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -75,6 +75,7 @@
 CONFIG_MSM_QDSS=y
 CONFIG_MSM_SLEEP_STATS=y
 CONFIG_STRICT_MEMORY_RWX=y
+CONFIG_MSM_SHOW_RESUME_IRQ=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index e90400b..9491ab3 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -53,6 +53,14 @@
 	unsigned int wakeup_irqs[32];
 	unsigned int enabled_irqs[32];
 #endif
+#ifdef CONFIG_CPU_PM
+	u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
+	u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
+	u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
+	u32 __percpu *saved_ppi_enable;
+	u32 __percpu *saved_ppi_conf;
+#endif
+	unsigned int gic_irqs;
 };
 #endif
 
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index a6dadf0..8145184 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -71,6 +71,12 @@
 extern void platform_smp_prepare_cpus(unsigned int);
 
 /*
+ * Logical CPU mapping.
+ */
+extern int __cpu_logical_map[NR_CPUS];
+#define cpu_logical_map(cpu)	__cpu_logical_map[cpu]
+
+/*
  * Initial data for bringing up a secondary CPU.
  */
 struct secondary_data {
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index a920c5f..0cd27bc 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -289,7 +289,7 @@
 	.notifier_call = arch_timer_cpu_notify,
 };
 
-int arch_timer_register(struct resource *res, int res_nr)
+int __init arch_timer_register(struct resource *res, int res_nr)
 {
 	struct irqaction *irqa;
 	unsigned int cpu = smp_processor_id();
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 8aa7dcb..9fe0964 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -39,6 +39,7 @@
 #include <asm/tlbflush.h>
 #include <asm/ptrace.h>
 #include <asm/localtimer.h>
+#include <asm/smp_plat.h>
 
 /*
  * as from 2.5, kernels no longer have an init_tasks structure
@@ -261,6 +262,20 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
+int __cpu_logical_map[NR_CPUS];
+
+void __init smp_setup_processor_id(void)
+{
+	int i;
+	u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0;
+
+	cpu_logical_map(0) = cpu;
+	for (i = 1; i < NR_CPUS; ++i)
+		cpu_logical_map(i) = i == cpu ? 0 : i;
+
+	printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu);
+}
+
 /*
  * Called by both boot and secondaries to move global data into
  * per-processor storage.
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 143fb86..be8c31c 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -764,7 +764,9 @@
 {
 	unsigned int pll_vdd_dig;
 
-	if (tgt->l2_level->speed.pll_l_val > HFPLL_LOW_VDD_PLL_L_MAX)
+	if (tgt->l2_level->speed.src != HFPLL)
+		pll_vdd_dig = 0;
+	else if (tgt->l2_level->speed.pll_l_val > HFPLL_LOW_VDD_PLL_L_MAX)
 		pll_vdd_dig = HFPLL_NOMINAL_VDD;
 	else
 		pll_vdd_dig = HFPLL_LOW_VDD;
@@ -776,7 +778,9 @@
 {
 	unsigned int pll_vdd_core;
 
-	if (tgt->speed.pll_l_val > HFPLL_LOW_VDD_PLL_L_MAX)
+	if (tgt->speed.src != HFPLL)
+		pll_vdd_core = 0;
+	else if (tgt->speed.pll_l_val > HFPLL_LOW_VDD_PLL_L_MAX)
 		pll_vdd_core = HFPLL_NOMINAL_VDD;
 	else
 		pll_vdd_core = HFPLL_LOW_VDD;
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 0041f0d..644a666 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -25,11 +25,13 @@
 #include <linux/skbuff.h>
 #include <linux/debugfs.h>
 #include <linux/clk.h>
+#include <linux/wakelock.h>
 
 #include <mach/sps.h>
 #include <mach/bam_dmux.h>
 #include <mach/msm_smsm.h>
 #include <mach/subsystem_notif.h>
+#include <mach/socinfo.h>
 
 #define BAM_CH_LOCAL_OPEN       0x1
 #define BAM_CH_REMOTE_OPEN      0x2
@@ -194,6 +196,8 @@
 static DEFINE_RWLOCK(ul_wakeup_lock);
 static DECLARE_WORK(kickoff_ul_wakeup, kickoff_ul_wakeup_func);
 static int bam_connection_is_active;
+static int wait_for_ack;
+static struct wake_lock bam_wakelock;
 /* End A2 power collaspe */
 
 /* subsystem restart */
@@ -228,12 +232,19 @@
 		return;
 
 	info = kmalloc(sizeof(struct rx_pkt_info), GFP_KERNEL);
-	if (!info)
-		return; /*need better way to handle this */
+	if (!info) {
+		pr_err("%s: unable to alloc rx_pkt_info\n", __func__);
+		return;
+	}
 
 	INIT_WORK(&info->work, handle_bam_mux_cmd);
 
 	info->skb = __dev_alloc_skb(BUFFER_SIZE, GFP_KERNEL);
+	if (info->skb == NULL) {
+		pr_err("%s: unable to alloc skb\n", __func__);
+		kfree(info);
+		return;
+	}
 	ptr = skb_put(info->skb, BUFFER_SIZE);
 
 	mutex_lock(&bam_rx_pool_mutexlock);
@@ -373,6 +384,7 @@
 					DMA_TO_DEVICE);
 	if (!dma_address) {
 		pr_err("%s: dma_map_single() failed\n", __func__);
+		kfree(pkt);
 		rc = -ENOMEM;
 		return rc;
 	}
@@ -991,6 +1003,8 @@
 		schedule_delayed_work(&ul_timeout_work,
 				msecs_to_jiffies(UL_TIMEOUT_DELAY));
 	} else {
+		wait_for_ack = 1;
+		INIT_COMPLETION(ul_wakeup_ack_completion);
 		smsm_change_state(SMSM_APPS_STATE, SMSM_A2_POWER_CONTROL, 0);
 		bam_is_connected = 0;
 		notify_all(BAM_DMUX_UL_DISCONNECTED, (unsigned long)(NULL));
@@ -999,17 +1013,31 @@
 }
 static void ul_wakeup(void)
 {
+	int ret;
+
 	mutex_lock(&wakeup_lock);
 	if (bam_is_connected) { /* bam got connected before lock grabbed */
 		mutex_unlock(&wakeup_lock);
 		return;
 	}
+	/*
+	 * must wait for the previous power down request to have been acked
+	 * chances are it already came in and this will just fall through
+	 * instead of waiting
+	 */
+	if (wait_for_ack) {
+		ret = wait_for_completion_interruptible_timeout(
+					&ul_wakeup_ack_completion, HZ);
+		BUG_ON(ret == 0);
+	}
 	INIT_COMPLETION(ul_wakeup_ack_completion);
 	smsm_change_state(SMSM_APPS_STATE, 0, SMSM_A2_POWER_CONTROL);
-	wait_for_completion_interruptible_timeout(&ul_wakeup_ack_completion,
-							HZ);
-	wait_for_completion_interruptible_timeout(&bam_connection_completion,
-							HZ);
+	ret = wait_for_completion_interruptible_timeout(
+						&ul_wakeup_ack_completion, HZ);
+	BUG_ON(ret == 0);
+	ret = wait_for_completion_interruptible_timeout(
+						&bam_connection_completion, HZ);
+	BUG_ON(ret == 0);
 
 	bam_is_connected = 1;
 	schedule_delayed_work(&ul_timeout_work,
@@ -1070,10 +1098,16 @@
 
 static void vote_dfab(void)
 {
+	int rc;
+
+	rc = clk_enable(dfab_clk);
+	if (rc)
+		pr_err("bam_dmux vote for dfab failed rc = %d\n", rc);
 }
 
 static void unvote_dfab(void)
 {
+	clk_disable(dfab_clk);
 }
 
 static int restart_notifier_cb(struct notifier_block *this,
@@ -1151,6 +1185,8 @@
 	a2_props.options = SPS_BAM_OPT_IRQ_WAKEUP;
 	a2_props.num_pipes = A2_NUM_PIPES;
 	a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
+	if (cpu_is_msm9615())
+		a2_props.manage = SPS_BAM_MGR_DEVICE_REMOTE;
 	/* need to free on tear down */
 	ret = sps_register_bam_device(&a2_props, &h);
 	if (ret < 0) {
@@ -1298,14 +1334,19 @@
 static void bam_dmux_smsm_cb(void *priv, uint32_t old_state, uint32_t new_state)
 {
 	DBG("%s: smsm activity\n", __func__);
-	if (bam_mux_initialized && new_state & SMSM_A2_POWER_CONTROL)
+	if (bam_mux_initialized && new_state & SMSM_A2_POWER_CONTROL) {
+		wake_lock(&bam_wakelock);
 		reconnect_to_bam();
-	else if (bam_mux_initialized && !(new_state & SMSM_A2_POWER_CONTROL))
+	} else if (bam_mux_initialized &&
+					!(new_state & SMSM_A2_POWER_CONTROL)) {
 		disconnect_to_bam();
-	else if (new_state & SMSM_A2_POWER_CONTROL)
+		wake_unlock(&bam_wakelock);
+	} else if (new_state & SMSM_A2_POWER_CONTROL) {
+		wake_lock(&bam_wakelock);
 		bam_init();
-	else
+	} else {
 		pr_err("%s: unsupported state change\n", __func__);
+	}
 
 }
 
@@ -1360,6 +1401,7 @@
 	init_completion(&ul_wakeup_ack_completion);
 	init_completion(&bam_connection_completion);
 	INIT_DELAYED_WORK(&ul_timeout_work, ul_timeout);
+	wake_lock_init(&bam_wakelock, WAKE_LOCK_SUSPEND, "bam_dmux_wakelock");
 
 	rc = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_A2_POWER_CONTROL,
 					bam_dmux_smsm_cb, NULL);
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 2b9b0be..3d0d0e5 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1669,6 +1669,7 @@
 	&msm_voice,
 	&msm_voip,
 	&msm_lpa_pcm,
+	&msm_compr_dsp,
 
 #if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
 		defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
@@ -1727,6 +1728,7 @@
 	&msm_cpudai_afe_02_rx,
 	&msm_cpudai_afe_02_tx,
 	&msm_pcm_afe,
+	&msm_compr_dsp,
 	&msm_pcm_hostless,
 	&msm_bus_apps_fabric,
 	&msm_bus_sys_fabric,
diff --git a/arch/arm/mach-msm/board-msm7x30-regulator.c b/arch/arm/mach-msm/board-msm7x30-regulator.c
index edfcc6b..a3f5ee1 100644
--- a/arch/arm/mach-msm/board-msm7x30-regulator.c
+++ b/arch/arm/mach-msm/board-msm7x30-regulator.c
@@ -295,7 +295,7 @@
 	PCOM_VREG_LDO(ldo16, 35, NULL,  2600000,  2600000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo17, 36, NULL,  2600000,  2600000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo18, 37, NULL,  2200000,  2200000, 0, -1, 0, 0, 0, 0),
-	PCOM_VREG_LDO(ldo19, 45, NULL,  2500000,  2500000, 0, -1, 0, 0, 0, 0),
+	PCOM_VREG_LDO(ldo19, 45, NULL,  2400000,  2500000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo20, 38, NULL,  1500000,  1800000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo21, 39, NULL,  1100000,  1100000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo22, 40, NULL,  1200000,  1300000, 0, -1, 0, 0, 0, 0),
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index 100689b..e716b25 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -3000,7 +3000,6 @@
 	.disable = rcg_clk_disable,
 	.auto_off = rcg_clk_disable,
 	.set_rate = rcg_clk_set_rate,
-	.set_min_rate = rcg_clk_set_min_rate,
 	.get_rate = rcg_clk_get_rate,
 	.list_rate = rcg_clk_list_rate,
 	.is_enabled = rcg_clk_is_enabled,
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 3214be5..d7322b6 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -642,7 +642,6 @@
 	.auto_off = rcg_clk_disable,
 	.handoff = rcg_clk_handoff,
 	.set_rate = rcg_clk_set_rate,
-	.set_min_rate = rcg_clk_set_min_rate,
 	.get_rate = rcg_clk_get_rate,
 	.list_rate = rcg_clk_list_rate,
 	.is_enabled = rcg_clk_is_enabled,
@@ -1534,7 +1533,6 @@
 	.auto_off = qdss_clk_auto_off,
 	.handoff = qdss_clk_handoff,
 	.set_rate = rcg_clk_set_rate,
-	.set_min_rate = rcg_clk_set_min_rate,
 	.get_rate = rcg_clk_get_rate,
 	.list_rate = rcg_clk_list_rate,
 	.is_enabled = rcg_clk_is_enabled,
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 662e9a6..454e9cf 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -546,7 +546,6 @@
 	.auto_off = rcg_clk_disable,
 	.handoff = rcg_clk_handoff,
 	.set_rate = rcg_clk_set_rate,
-	.set_min_rate = rcg_clk_set_min_rate,
 	.get_rate = rcg_clk_get_rate,
 	.list_rate = rcg_clk_list_rate,
 	.is_enabled = rcg_clk_is_enabled,
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index e47981e..553fb4d 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -424,7 +424,6 @@
 	.disable = rcg_clk_disable,
 	.auto_off = rcg_clk_disable,
 	.set_rate = rcg_clk_set_rate,
-	.set_min_rate = rcg_clk_set_min_rate,
 	.get_rate = rcg_clk_get_rate,
 	.list_rate = rcg_clk_list_rate,
 	.is_enabled = rcg_clk_is_enabled,
diff --git a/arch/arm/mach-msm/clock-dummy.c b/arch/arm/mach-msm/clock-dummy.c
index feef984..dfd4a67 100644
--- a/arch/arm/mach-msm/clock-dummy.c
+++ b/arch/arm/mach-msm/clock-dummy.c
@@ -22,11 +22,6 @@
 	return 0;
 }
 
-static int dummy_clk_set_min_rate(struct clk *clk, unsigned long rate)
-{
-	return 0;
-}
-
 static int dummy_clk_set_max_rate(struct clk *clk, unsigned long rate)
 {
 	return 0;
@@ -55,7 +50,6 @@
 static struct clk_ops clk_ops_dummy = {
 	.reset = dummy_clk_reset,
 	.set_rate = dummy_clk_set_rate,
-	.set_min_rate = dummy_clk_set_min_rate,
 	.set_max_rate = dummy_clk_set_max_rate,
 	.set_flags = dummy_clk_set_flags,
 	.get_rate = dummy_clk_get_rate,
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 8aee414..f8d84be 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -523,22 +523,6 @@
 	return _rcg_clk_set_rate(clk, nf);
 }
 
-/* Set a clock to a rate greater than some minimum. */
-int rcg_clk_set_min_rate(struct clk *c, unsigned long rate)
-{
-	struct rcg_clk *clk = to_rcg_clk(c);
-	struct clk_freq_tbl *nf;
-
-	for (nf = clk->freq_tbl; nf->freq_hz != FREQ_END
-			&& nf->freq_hz < rate; nf++)
-		;
-
-	if (nf->freq_hz == FREQ_END)
-		return -EINVAL;
-
-	return _rcg_clk_set_rate(clk, nf);
-}
-
 /* Get the currently-set rate of a clock in Hz. */
 unsigned long rcg_clk_get_rate(struct clk *c)
 {
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index e651d47..2123513 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -144,7 +144,6 @@
 int rcg_clk_enable(struct clk *clk);
 void rcg_clk_disable(struct clk *clk);
 int rcg_clk_set_rate(struct clk *clk, unsigned long rate);
-int rcg_clk_set_min_rate(struct clk *clk, unsigned long rate);
 unsigned long rcg_clk_get_rate(struct clk *clk);
 int rcg_clk_list_rate(struct clk *clk, unsigned n);
 int rcg_clk_is_enabled(struct clk *clk);
diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c
index 79fe662..58cea99 100644
--- a/arch/arm/mach-msm/clock-pcom.c
+++ b/arch/arm/mach-msm/clock-pcom.c
@@ -74,7 +74,7 @@
 	return pc_clk_reset(id, action);
 }
 
-static int pc_clk_set_rate(struct clk *clk, unsigned long rate)
+static int _pc_clk_set_rate(struct clk *clk, unsigned long rate)
 {
 	/* The rate _might_ be rounded off to the nearest KHz value by the
 	 * remote function. So a return value of 0 doesn't necessarily mean
@@ -89,7 +89,7 @@
 		return (int)id < 0 ? -EINVAL : 0;
 }
 
-static int pc_clk_set_min_rate(struct clk *clk, unsigned long rate)
+static int _pc_clk_set_min_rate(struct clk *clk, unsigned long rate)
 {
 	int rc;
 	int id = to_pcom_clk(clk)->id;
@@ -105,6 +105,14 @@
 		return (int)id < 0 ? -EINVAL : 0;
 }
 
+static int pc_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->flags & CLKFLAG_MIN)
+		return _pc_clk_set_min_rate(clk, rate);
+	else
+		return _pc_clk_set_rate(clk, rate);
+}
+
 static int pc_clk_set_max_rate(struct clk *clk, unsigned long rate)
 {
 	int id = to_pcom_clk(clk)->id;
@@ -173,7 +181,6 @@
 	.auto_off = pc_clk_disable,
 	.reset = pc_reset,
 	.set_rate = pc_clk_set_rate,
-	.set_min_rate = pc_clk_set_min_rate,
 	.set_max_rate = pc_clk_set_max_rate,
 	.set_flags = pc_clk_set_flags,
 	.get_rate = pc_clk_get_rate,
@@ -188,7 +195,6 @@
 	.auto_off = pc_clk_disable,
 	.reset = pc_reset,
 	.set_rate = pc_clk_set_ext_config,
-	.set_min_rate = pc_clk_set_min_rate,
 	.set_max_rate = pc_clk_set_max_rate,
 	.set_flags = pc_clk_set_flags,
 	.get_rate = pc_clk_get_rate,
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 75cba59..4757f7d 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -104,7 +104,7 @@
 	return;
 }
 
-static int rpm_clk_set_min_rate(struct clk *clk, unsigned long rate)
+static int rpm_clk_set_rate(struct clk *clk, unsigned long rate)
 {
 	unsigned long flags;
 	struct rpm_clk *r = to_rpm_clk(clk);
@@ -189,7 +189,7 @@
 struct clk_ops clk_ops_rpm = {
 	.enable = rpm_clk_enable,
 	.disable = rpm_clk_disable,
-	.set_min_rate = rpm_clk_set_min_rate,
+	.set_rate = rpm_clk_set_rate,
 	.get_rate = rpm_clk_get_rate,
 	.is_enabled = rpm_clk_is_enabled,
 	.round_rate = rpm_clk_round_rate,
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index 0a99a6d..24df9b6 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -45,7 +45,7 @@
 		.peer = &active, \
 		.c = { \
 			.ops = &clk_ops_rpm, \
-			.flags = CLKFLAG_SKIP_AUTO_OFF | CLKFLAG_MIN, \
+			.flags = CLKFLAG_SKIP_AUTO_OFF, \
 			.dbg_name = #name, \
 			CLK_INIT(name.c), \
 			.depends = dep, \
@@ -58,7 +58,7 @@
 		.active_only = true, \
 		.c = { \
 			.ops = &clk_ops_rpm, \
-			.flags = CLKFLAG_SKIP_AUTO_OFF | CLKFLAG_MIN, \
+			.flags = CLKFLAG_SKIP_AUTO_OFF, \
 			.dbg_name = #active, \
 			CLK_INIT(active.c), \
 			.depends = dep, \
diff --git a/arch/arm/mach-msm/clock-voter.c b/arch/arm/mach-msm/clock-voter.c
index 2624f6c..ef502b3 100644
--- a/arch/arm/mach-msm/clock-voter.c
+++ b/arch/arm/mach-msm/clock-voter.c
@@ -175,7 +175,6 @@
 	.enable = voter_clk_enable,
 	.disable = voter_clk_disable,
 	.set_rate = voter_clk_set_rate,
-	.set_min_rate = voter_clk_set_rate,
 	.get_rate = voter_clk_get_rate,
 	.is_enabled = voter_clk_is_enabled,
 	.round_rate = voter_clk_round_rate,
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index d4f3e45..57fd749 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -228,13 +228,12 @@
 }
 EXPORT_SYMBOL(clk_get_rate);
 
-static int _clk_set_rate(struct clk *clk, unsigned long rate,
-			 int (*set_fn)(struct clk *, unsigned long))
+int clk_set_rate(struct clk *clk, unsigned long rate)
 {
 	unsigned long start_rate, flags;
 	int rc;
 
-	if (!set_fn)
+	if (!clk->ops->set_rate)
 		return -ENOSYS;
 
 	spin_lock_irqsave(&clk->lock, flags);
@@ -244,13 +243,13 @@
 		rc = vote_rate_vdd(clk, rate);
 		if (rc)
 			goto err_vote_vdd;
-		rc = set_fn(clk, rate);
+		rc = clk->ops->set_rate(clk, rate);
 		if (rc)
 			goto err_set_rate;
 		/* Release vdd requirements for starting frequency. */
 		unvote_rate_vdd(clk, start_rate);
 	} else {
-		rc = set_fn(clk, rate);
+		rc = clk->ops->set_rate(clk, rate);
 	}
 
 	if (!rc)
@@ -265,6 +264,7 @@
 	spin_unlock_irqrestore(&clk->lock, flags);
 	return rc;
 }
+EXPORT_SYMBOL(clk_set_rate);
 
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
@@ -275,21 +275,6 @@
 }
 EXPORT_SYMBOL(clk_round_rate);
 
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	if (clk->flags & CLKFLAG_MIN)
-		return _clk_set_rate(clk, rate, clk->ops->set_min_rate);
-	else
-		return _clk_set_rate(clk, rate, clk->ops->set_rate);
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-int clk_set_min_rate(struct clk *clk, unsigned long rate)
-{
-	return _clk_set_rate(clk, rate, clk->ops->set_min_rate);
-}
-EXPORT_SYMBOL(clk_set_min_rate);
-
 int clk_set_max_rate(struct clk *clk, unsigned long rate)
 {
 	if (!clk->ops->set_max_rate)
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 81f12c6..ec8ff6c 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -66,7 +66,6 @@
 	int (*handoff)(struct clk *clk);
 	int (*reset)(struct clk *clk, enum clk_reset_action action);
 	int (*set_rate)(struct clk *clk, unsigned long rate);
-	int (*set_min_rate)(struct clk *clk, unsigned long rate);
 	int (*set_max_rate)(struct clk *clk, unsigned long rate);
 	int (*set_flags)(struct clk *clk, unsigned flags);
 	unsigned long (*get_rate)(struct clk *clk);
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index e814b4e..ad803f8 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1457,6 +1457,11 @@
 	.id     = -1,
 };
 
+struct platform_device msm_compr_dsp = {
+	.name	= "msm-compr-dsp",
+	.id	= -1,
+};
+
 struct platform_device msm_pcm_hostless = {
 	.name	= "msm-pcm-hostless",
 	.id	= -1,
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 147f01d..1ba63c9 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -171,6 +171,7 @@
 extern struct platform_device msm_cpudai_afe_02_rx;
 extern struct platform_device msm_cpudai_afe_02_tx;
 extern struct platform_device msm_pcm_afe;
+extern struct platform_device msm_compr_dsp;
 
 extern struct platform_device msm_8960_q6_lpass;
 extern struct platform_device msm_8960_q6_mss_fw;
diff --git a/arch/arm/mach-msm/include/mach/clk.h b/arch/arm/mach-msm/include/mach/clk.h
index e8d3842..8c0ebfa 100644
--- a/arch/arm/mach-msm/include/mach/clk.h
+++ b/arch/arm/mach-msm/include/mach/clk.h
@@ -25,9 +25,6 @@
 
 struct clk;
 
-/* Rate is minimum clock rate in Hz */
-int clk_set_min_rate(struct clk *clk, unsigned long rate);
-
 /* Rate is maximum clock rate in Hz */
 int clk_set_max_rate(struct clk *clk, unsigned long rate);
 
diff --git a/arch/arm/mach-msm/msm_dsps.c b/arch/arm/mach-msm/msm_dsps.c
index bcb777f..5419087 100644
--- a/arch/arm/mach-msm/msm_dsps.c
+++ b/arch/arm/mach-msm/msm_dsps.c
@@ -40,7 +40,7 @@
 #include <mach/subsystem_notif.h>
 
 #define DRV_NAME	"msm_dsps"
-#define DRV_VERSION	"3.00"
+#define DRV_VERSION	"3.01"
 
 #define PPSS_PAUSE_REG	0x1804
 
@@ -655,11 +655,12 @@
 	if (dsps_state & SMSM_RESET) {
 		pr_err("%s: DSPS fatal error detected. Resetting\n",
 		       __func__);
+		panic("DSPS fatal error detected.");
 	} else {
 		pr_debug("%s: User-initiated DSPS reset. Resetting\n",
 			 __func__);
+		panic("User-initiated DSPS reset.");
 	}
-	subsystem_restart("dsps");
 }
 
 
@@ -682,7 +683,7 @@
 		pr_err
 		    ("%s: SMSM_RESET state detected. restarting the DSPS\n",
 		     __func__);
-		subsystem_restart("dsps");
+		panic("SMSM_RESET state detected.");
 	}
 }
 
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 672f332..b16b687 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -220,6 +220,7 @@
 		dev_err(pil->desc->dev, "Failed to bring out of reset\n");
 		goto release_fw;
 	}
+	dev_info(pil->desc->dev, "brought out of reset\n");
 
 release_fw:
 	release_firmware(fw);
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 7759c74..6d36495 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -17,3 +17,4 @@
 obj-y += aac_in.o qcelp_in.o evrc_in.o amrnb_in.o audio_utils.o
 obj-y += audio_wma.o audio_wmapro.o audio_aac.o audio_multi_aac.o audio_utils_aio.o
 obj-$(CONFIG_MSM_ULTRASOUND) += ultrasound/
+obj-y += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_evrc.o audio_qcelp.o amrwb_in.o
diff --git a/arch/arm/mach-msm/qdsp6v2/amrwb_in.c b/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
new file mode 100644
index 0000000..030d08f
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
@@ -0,0 +1,322 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/msm_audio_amrwb.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/wait.h>
+#include <sound/apr_audio.h>
+#include <sound/q6asm.h>
+#include <asm/atomic.h>
+#include <asm/ioctls.h>
+#include "audio_utils.h"
+
+/* Buffer with meta*/
+#define PCM_BUF_SIZE		(4096 + sizeof(struct meta_in))
+
+/* Maximum 10 frames in buffer with meta */
+#define FRAME_SIZE		(1 + ((61+sizeof(struct meta_out_dsp)) * 10))
+
+void q6asm_amrwb_in_cb(uint32_t opcode, uint32_t token,
+		uint32_t *payload, void *priv)
+{
+	struct q6audio_in * audio = (struct q6audio_in *)priv;
+	unsigned long flags;
+
+	pr_debug("%s:session id %d: opcode - %d\n", __func__,
+			audio->ac->session, opcode);
+
+	spin_lock_irqsave(&audio->dsp_lock, flags);
+	switch (opcode) {
+	case ASM_DATA_EVENT_READ_DONE:
+		audio_in_get_dsp_frames(audio, token, payload);
+		break;
+	case ASM_DATA_EVENT_WRITE_DONE:
+		atomic_inc(&audio->in_count);
+		wake_up(&audio->write_wait);
+		break;
+	case ASM_DATA_CMDRSP_EOS:
+		audio->eos_rsp = 1;
+		wake_up(&audio->read_wait);
+		break;
+	case ASM_STREAM_CMDRSP_GET_ENCDEC_PARAM:
+		break;
+	case ASM_STREAM_CMDRSP_GET_PP_PARAMS:
+		break;
+	case ASM_SESSION_EVENT_TX_OVERFLOW:
+		pr_err("%s:session id %d: ASM_SESSION_EVENT_TX_OVERFLOW\n",
+			__func__, audio->ac->session);
+		break;
+	default:
+		pr_err("%s:session id %d: Ignore opcode[0x%x]\n", __func__,
+				audio->ac->session, opcode);
+		break;
+	}
+	spin_unlock_irqrestore(&audio->dsp_lock, flags);
+}
+
+/* ------------------- device --------------------- */
+static long amrwb_in_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_in  *audio = file->private_data;
+	int rc = 0;
+	int cnt = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		struct msm_audio_amrwb_enc_config *enc_cfg;
+		enc_cfg = audio->enc_cfg;
+		pr_debug("%s:session id %d: default buf alloc[%d]\n", __func__,
+				audio->ac->session, audio->buf_alloc);
+		if (audio->enabled == 1) {
+			pr_info("%s:AUDIO_START already over\n", __func__);
+			rc = 0;
+			break;
+		}
+		rc = audio_in_buf_alloc(audio);
+		if (rc < 0) {
+			pr_err("%s:session id %d: buffer allocation failed\n",
+				__func__, audio->ac->session);
+			break;
+		}
+
+		rc = q6asm_enc_cfg_blk_amrwb(audio->ac,
+			audio->buf_cfg.frames_per_buf,
+			enc_cfg->band_mode,
+			enc_cfg->dtx_enable);
+
+		if (rc < 0) {
+			pr_err("%s:session id %d: cmd amrwb media format block"
+				"failed\n", __func__, audio->ac->session);
+			break;
+		}
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			rc = q6asm_media_format_block_pcm(audio->ac,
+				audio->pcm_cfg.sample_rate,
+				audio->pcm_cfg.channel_count);
+
+			if (rc < 0) {
+				pr_err("%s:session id %d: media format block"
+				"failed\n", __func__, audio->ac->session);
+				break;
+			}
+		}
+		pr_debug("%s:session id %d: AUDIO_START enable[%d]\n",
+				__func__, audio->ac->session,
+				audio->enabled);
+		rc = audio_in_enable(audio);
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("%s:session id %d: Audio Start procedure failed"
+				"rc=%d\n", __func__, audio->ac->session, rc);
+			break;
+		}
+		while (cnt++ < audio->str_cfg.buffer_count)
+			q6asm_read(audio->ac); /* Push buffer to DSP */
+		rc = 0;
+		pr_debug("%s:session id %d: AUDIO_START success enable[%d]\n",
+				__func__, audio->ac->session, audio->enabled);
+		break;
+	}
+	case AUDIO_STOP: {
+		pr_debug("%s:AUDIO_STOP\n", __func__);
+		rc = audio_in_disable(audio);
+		if (rc  < 0) {
+			pr_err("%s:session id %d: Audio Stop procedure failed"
+				"rc=%d\n", __func__, audio->ac->session, rc);
+			break;
+		}
+		break;
+	}
+	case AUDIO_GET_AMRWB_ENC_CONFIG: {
+		if (copy_to_user((void *)arg, audio->enc_cfg,
+			sizeof(struct msm_audio_amrwb_enc_config)))
+			rc = -EFAULT;
+		break;
+	}
+	case AUDIO_SET_AMRWB_ENC_CONFIG: {
+		struct msm_audio_amrwb_enc_config cfg;
+		struct msm_audio_amrwb_enc_config *enc_cfg;
+		enc_cfg = audio->enc_cfg;
+		if (copy_from_user(&cfg, (void *) arg,
+				sizeof(struct msm_audio_amrwb_enc_config))) {
+			rc = -EFAULT;
+			break;
+		}
+		if (cfg.band_mode > 8) {
+			pr_err("%s:session id %d: invalid band mode\n",
+				__func__, audio->ac->session);
+			rc = -EINVAL;
+			break;
+		}
+		/* ToDo: AMR WB encoder accepts values between 0-8
+		   while openmax provides value between 9-17
+		   as per spec */
+		enc_cfg->band_mode = cfg.band_mode;
+		enc_cfg->dtx_enable = (cfg.dtx_enable ? 1 : 0);
+		/* Currently DSP does not support different frameformat */
+		enc_cfg->frame_format = 0;
+		pr_debug("%s:session id %d: band_mode = 0x%x dtx_enable=0x%x\n",
+				__func__, audio->ac->session,
+				enc_cfg->band_mode, enc_cfg->dtx_enable);
+		break;
+	}
+	default:
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+static int amrwb_in_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_in *audio = NULL;
+	struct msm_audio_amrwb_enc_config *enc_cfg;
+	int rc = 0;
+
+	audio = kzalloc(sizeof(struct q6audio_in), GFP_KERNEL);
+
+	if (audio == NULL) {
+		pr_err("%s:session id %d: Could not allocate memory for amrwb"
+			"driver\n", __func__, audio->ac->session);
+		return -ENOMEM;
+	}
+	/* Allocate memory for encoder config param */
+	audio->enc_cfg = kzalloc(sizeof(struct msm_audio_amrwb_enc_config),
+				GFP_KERNEL);
+	if (audio->enc_cfg == NULL) {
+		pr_err("%s:session id %d: Could not allocate memory for amrwb"
+			"config param\n", __func__, audio->ac->session);
+		kfree(audio);
+		return -ENOMEM;
+	}
+	enc_cfg = audio->enc_cfg;
+
+	mutex_init(&audio->lock);
+	mutex_init(&audio->read_lock);
+	mutex_init(&audio->write_lock);
+	spin_lock_init(&audio->dsp_lock);
+	init_waitqueue_head(&audio->read_wait);
+	init_waitqueue_head(&audio->write_wait);
+
+	/* Settings will be re-config at AUDIO_SET_CONFIG,
+	* but at least we need to have initial config
+	*/
+	audio->str_cfg.buffer_size = FRAME_SIZE;
+	audio->str_cfg.buffer_count = FRAME_NUM;
+	audio->min_frame_size = 32;
+	audio->max_frames_per_buf = 10;
+	audio->pcm_cfg.buffer_size = PCM_BUF_SIZE;
+	audio->pcm_cfg.buffer_count = PCM_BUF_COUNT;
+	enc_cfg->band_mode = 8;
+	enc_cfg->dtx_enable = 0;
+	audio->pcm_cfg.channel_count = 1;
+	audio->pcm_cfg.sample_rate = 16000;
+	audio->buf_cfg.meta_info_enable = 0x01;
+	audio->buf_cfg.frames_per_buf = 0x01;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb)q6asm_amrwb_in_cb,
+				(void *)audio);
+
+	if (!audio->ac) {
+		pr_err("%s:session id %d: Could not allocate memory for audio"
+			"client\n", __func__, audio->ac->session);
+		kfree(audio->enc_cfg);
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	/* open amrwb encoder in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) &&
+		(file->f_mode & FMODE_READ)) {
+		audio->feedback = NON_TUNNEL_MODE;
+		rc = q6asm_open_read_write(audio->ac, FORMAT_AMRWB,
+					FORMAT_LINEAR_PCM);
+		if (rc < 0) {
+			pr_err("%s:session id %d: NT mode Open failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		pr_info("%s:session id %d: NT mode encoder success\n",
+				__func__, audio->ac->session);
+	} else if (!(file->f_mode & FMODE_WRITE) &&
+				(file->f_mode & FMODE_READ)) {
+		audio->feedback = TUNNEL_MODE;
+		rc = q6asm_open_read(audio->ac, FORMAT_AMRWB);
+		if (rc < 0) {
+			pr_err("%s:session id %d: T mode Open failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		/* register for tx overflow (valid for tunnel mode only) */
+		rc = q6asm_reg_tx_overflow(audio->ac, 0x01);
+		if (rc < 0) {
+			pr_err("%s:session id %d: TX Overflow registration"
+				"failed rc=%d\n", __func__, audio->ac->session,
+				rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		pr_info("%s:session id %d: T mode encoder success\n",
+				__func__, audio->ac->session);
+	} else {
+		pr_err("%s:session id %d: Unexpected mode\n", __func__,
+				audio->ac->session);
+		rc = -EACCES;
+		goto fail;
+	}
+
+	audio->opened = 1;
+	atomic_set(&audio->in_count, PCM_BUF_COUNT);
+	atomic_set(&audio->out_count, 0x00);
+	audio->enc_ioctl = amrwb_in_ioctl;
+	file->private_data = audio;
+
+	pr_info("%s:session id %d: success\n", __func__, audio->ac->session);
+	return 0;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio->enc_cfg);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_in_fops = {
+	.owner		= THIS_MODULE,
+	.open		= amrwb_in_open,
+	.release	= audio_in_release,
+	.read		= audio_in_read,
+	.write		= audio_in_write,
+	.unlocked_ioctl	= audio_in_ioctl,
+};
+
+struct miscdevice audio_amrwb_in_misc = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "msm_amrwb_in",
+	.fops	= &audio_in_fops,
+};
+
+static int __init amrwb_in_init(void)
+{
+	return misc_register(&audio_amrwb_in_misc);
+}
+
+device_initcall(amrwb_in_init);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c b/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c
new file mode 100644
index 0000000..6768f7a
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c
@@ -0,0 +1,179 @@
+/* amrnb audio output device
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 "audio_utils_aio.h"
+
+static void q6_audio_amrnb_cb(uint32_t opcode, uint32_t token,
+		uint32_t *payload, void *priv)
+{
+	struct q6audio_aio *audio = (struct q6audio_aio *)priv;
+
+	pr_debug("%s:opcde = %d token = 0x%x\n", __func__, opcode, token);
+	switch (opcode) {
+	case ASM_DATA_EVENT_WRITE_DONE:
+	case ASM_DATA_EVENT_READ_DONE:
+	case ASM_DATA_CMDRSP_EOS:
+		audio_aio_cb(opcode, token, payload, audio);
+		break;
+	default:
+		pr_debug("%s:Unhandled event = 0x%8x\n", __func__, opcode);
+		break;
+	}
+}
+
+#ifdef CONFIG_DEBUG_FS
+static const struct file_operations audio_amrnb_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+#endif
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		pr_debug("%s[%p]: AUDIO_START session_id[%d]\n", __func__,
+						audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_debug("AUDIO_START success enable[%d]\n", audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_debug("%s[%p]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_ioctl(file, cmd, arg);
+	}
+	return rc;
+}
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+
+#ifdef CONFIG_DEBUG_FS
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_amrnb_" + 5];
+#endif
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (audio == NULL) {
+		pr_err("Could not allocate memory for wma decode driver\n");
+		return -ENOMEM;
+	}
+
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_amrnb_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_AMRNB);
+		if (rc < 0) {
+			pr_err("NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		audio->buf_cfg.frames_per_buf = 0x01;
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_AMRNB);
+		if (rc < 0) {
+			pr_err("T mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+	rc = audio_aio_open(audio, file);
+
+#ifdef CONFIG_DEBUG_FS
+	snprintf(name, sizeof name, "msm_amrnb_%04x", audio->ac->session);
+	audio->dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
+					    NULL, (void *)audio,
+					    &audio_amrnb_debug_fops);
+
+	if (IS_ERR(audio->dentry))
+		pr_debug("debugfs_create_file failed\n");
+#endif
+	pr_info("%s:amrnb decoder open success, session_id = %d\n", __func__,
+				audio->ac->session);
+	return rc;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_amrnb_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+};
+
+struct miscdevice audio_amrnb_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_amrnb",
+	.fops = &audio_amrnb_fops,
+};
+
+static int __init audio_amrnb_init(void)
+{
+	return misc_register(&audio_amrnb_misc);
+}
+
+device_initcall(audio_amrnb_init);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c b/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c
new file mode 100644
index 0000000..f95e191
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c
@@ -0,0 +1,182 @@
+/* amrwb audio output device
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 "audio_utils_aio.h"
+
+static void q6_audio_amrwb_cb(uint32_t opcode, uint32_t token,
+		uint32_t *payload, void *priv)
+{
+	struct q6audio_aio *audio = (struct q6audio_aio *)priv;
+
+	pr_debug("%s:opcde = %d token = 0x%x\n", __func__, opcode, token);
+	switch (opcode) {
+	case ASM_DATA_EVENT_WRITE_DONE:
+	case ASM_DATA_EVENT_READ_DONE:
+	case ASM_DATA_CMDRSP_EOS:
+		audio_aio_cb(opcode, token, payload, audio);
+		break;
+	default:
+		pr_debug("%s:Unhandled event = 0x%8x\n", __func__, opcode);
+		break;
+	}
+}
+
+#ifdef CONFIG_DEBUG_FS
+static const struct file_operations audio_amrwb_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+#endif
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		pr_debug("%s[%p]: AUDIO_START session_id[%d]\n", __func__,
+						audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_debug("%s: AUDIO_START sessionid[%d]enable[%d]\n", __func__,
+						audio->ac->session,
+						audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_debug("%s[%p]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_ioctl(file, cmd, arg);
+	}
+	return rc;
+}
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+
+#ifdef CONFIG_DEBUG_FS
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_amrwb_" + 5];
+#endif
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (audio == NULL) {
+		pr_err("Could not allocate memory for aac decode driver\n");
+		return -ENOMEM;
+	}
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_amrwb_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_AMRWB);
+		if (rc < 0) {
+			pr_err("NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		audio->buf_cfg.frames_per_buf = 0x01;
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_AMRWB);
+		if (rc < 0) {
+			pr_err("T mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+	rc = audio_aio_open(audio, file);
+
+#ifdef CONFIG_DEBUG_FS
+	snprintf(name, sizeof name, "msm_amrwb_%04x", audio->ac->session);
+	audio->dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
+					    NULL, (void *)audio,
+					    &audio_amrwb_debug_fops);
+
+	if (IS_ERR(audio->dentry))
+		pr_debug("debugfs_create_file failed\n");
+#endif
+	pr_info("%s: AMRWB dec success mode[%d]session[%d]\n", __func__,
+						audio->feedback,
+						audio->ac->session);
+	return 0;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_amrwb_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+};
+
+struct miscdevice audio_amrwb_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_amrwb",
+	.fops = &audio_amrwb_fops,
+};
+
+static int __init audio_amrwb_init(void)
+{
+	return misc_register(&audio_amrwb_misc);
+}
+
+device_initcall(audio_amrwb_init);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_evrc.c b/arch/arm/mach-msm/qdsp6v2/audio_evrc.c
new file mode 100644
index 0000000..12c815d
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/audio_evrc.c
@@ -0,0 +1,186 @@
+/* evrc audio output device
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 "audio_utils_aio.h"
+
+static void q6_audio_evrc_cb(uint32_t opcode, uint32_t token,
+		uint32_t *payload, void *priv)
+{
+	struct q6audio_aio *audio = (struct q6audio_aio *)priv;
+
+	pr_debug("%s:opcde = %d token = 0x%x\n", __func__, opcode, token);
+	switch (opcode) {
+	case ASM_DATA_EVENT_WRITE_DONE:
+	case ASM_DATA_EVENT_READ_DONE:
+	case ASM_DATA_CMDRSP_EOS:
+		audio_aio_cb(opcode, token, payload, audio);
+		break;
+	default:
+		pr_debug("%s:Unhandled event = 0x%8x\n", __func__, opcode);
+		break;
+	}
+}
+
+#ifdef CONFIG_DEBUG_FS
+static const struct file_operations audio_evrc_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+#endif
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		pr_debug("%s[%p]: AUDIO_START session_id[%d]\n", __func__,
+						audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_debug("%s: AUDIO_START sessionid[%d]enable[%d]\n", __func__,
+						audio->ac->session,
+						audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_debug("%s[%p]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_ioctl(file, cmd, arg);
+	}
+	return rc;
+}
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+
+#ifdef CONFIG_DEBUG_FS
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_evrc_" + 5];
+#endif
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (audio == NULL) {
+		pr_err("Could not allocate memory for aac decode driver\n");
+		return -ENOMEM;
+	}
+
+	/* Settings will be re-config at AUDIO_SET_CONFIG,
+	 * but at least we need to have initial config
+	 */
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_evrc_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_EVRC);
+		if (rc < 0) {
+			pr_err("NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		audio->buf_cfg.frames_per_buf = 0x01;
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_EVRC);
+		if (rc < 0) {
+			pr_err("T mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+	rc = audio_aio_open(audio, file);
+
+#ifdef CONFIG_DEBUG_FS
+	snprintf(name, sizeof name, "msm_evrc_%04x", audio->ac->session);
+	audio->dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
+					    NULL, (void *)audio,
+					    &audio_evrc_debug_fops);
+
+	if (IS_ERR(audio->dentry))
+		pr_debug("debugfs_create_file failed\n");
+#endif
+	pr_info("%s:dec success mode[%d]session[%d]\n", __func__,
+						audio->feedback,
+						audio->ac->session);
+	return rc;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_evrc_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+};
+
+struct miscdevice audio_evrc_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_evrc",
+	.fops = &audio_evrc_fops,
+};
+
+static int __init audio_evrc_init(void)
+{
+	return misc_register(&audio_evrc_misc);
+}
+
+device_initcall(audio_evrc_init);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_mp3.c b/arch/arm/mach-msm/qdsp6v2/audio_mp3.c
new file mode 100644
index 0000000..bb5dc96
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/audio_mp3.c
@@ -0,0 +1,177 @@
+/* mp3 audio output device
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 "audio_utils_aio.h"
+
+static void q6_audio_mp3_cb(uint32_t opcode, uint32_t token,
+		uint32_t *payload, void *priv)
+{
+	struct q6audio_aio *audio = (struct q6audio_aio *)priv;
+
+	pr_debug("%s:opcde = %d token = 0x%x\n", __func__, opcode, token);
+	switch (opcode) {
+	case ASM_DATA_EVENT_WRITE_DONE:
+	case ASM_DATA_EVENT_READ_DONE:
+	case ASM_DATA_CMDRSP_EOS:
+		audio_aio_cb(opcode, token, payload, audio);
+		break;
+	default:
+		pr_debug("%s:Unhandled event = 0x%8x\n", __func__, opcode);
+		break;
+	}
+}
+
+#ifdef CONFIG_DEBUG_FS
+static const struct file_operations audio_mp3_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+#endif
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+	switch (cmd) {
+	case AUDIO_START: {
+		pr_debug("%s[%p]: AUDIO_START session_id[%d]\n", __func__,
+						audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_info("%s: AUDIO_START sessionid[%d]enable[%d]\n", __func__,
+						audio->ac->session,
+						audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_debug("%s[%p]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_ioctl(file, cmd, arg);
+	}
+	return rc;
+}
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+
+#ifdef CONFIG_DEBUG_FS
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_mp3_" + 5];
+#endif
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (audio == NULL) {
+		pr_err("Could not allocate memory for mp3 decode driver\n");
+		return -ENOMEM;
+	}
+
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_mp3_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_MP3);
+		if (rc < 0) {
+			pr_err("NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		/* open MP3 decoder, expected frames is always 1
+		audio->buf_cfg.frames_per_buf = 0x01;*/
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		pr_err("%s: Tunnel Mode not supported\n", __func__);
+		return -EACCES;
+	} else {
+		pr_err("Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+	rc = audio_aio_open(audio, file);
+
+#ifdef CONFIG_DEBUG_FS
+	snprintf(name, sizeof name, "msm_mp3_%04x", audio->ac->session);
+	audio->dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
+					    NULL, (void *)audio,
+					    &audio_mp3_debug_fops);
+
+	if (IS_ERR(audio->dentry))
+		pr_debug("debugfs_create_file failed\n");
+#endif
+	pr_info("%s:mp3dec success mode[%d]session[%d]\n", __func__,
+						audio->feedback,
+						audio->ac->session);
+	return rc;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_mp3_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+};
+
+struct miscdevice audio_mp3_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_mp3",
+	.fops = &audio_mp3_fops,
+};
+
+static int __init audio_mp3_init(void)
+{
+	return misc_register(&audio_mp3_misc);
+}
+
+device_initcall(audio_mp3_init);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c b/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c
new file mode 100644
index 0000000..7b72c97
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c
@@ -0,0 +1,192 @@
+/* qcelp(v13k) audio output device
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 "audio_utils_aio.h"
+
+#define FRAME_SIZE_DEC_QCELP  ((32) + sizeof(struct dec_meta_in))
+
+static void q6_audio_qcelp_cb(uint32_t opcode, uint32_t token,
+		uint32_t *payload, void *priv)
+{
+	struct q6audio_aio *audio = (struct q6audio_aio *)priv;
+
+	switch (opcode) {
+	case ASM_DATA_EVENT_WRITE_DONE:
+	case ASM_DATA_EVENT_READ_DONE:
+	case ASM_DATA_CMDRSP_EOS:
+		audio_aio_cb(opcode, token, payload, audio);
+		break;
+	default:
+		pr_debug("%s:Unhandled event = 0x%8x\n", __func__, opcode);
+		break;
+	}
+}
+
+#ifdef CONFIG_DEBUG_FS
+static const struct file_operations audio_qcelp_debug_fops = {
+	.read = audio_aio_debug_read,
+	.open = audio_aio_debug_open,
+};
+#endif
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct q6audio_aio *audio = file->private_data;
+	int rc = 0;
+
+	switch (cmd) {
+	case AUDIO_START: {
+		pr_debug("%s[%p]: AUDIO_START session_id[%d]\n", __func__,
+						audio, audio->ac->session);
+		if (audio->feedback == NON_TUNNEL_MODE) {
+			/* Configure PCM output block */
+			rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+					audio->pcm_cfg.sample_rate,
+					audio->pcm_cfg.channel_count);
+			if (rc < 0) {
+				pr_err("pcm output block config failed\n");
+				break;
+			}
+		}
+
+		rc = audio_aio_enable(audio);
+		audio->eos_rsp = 0;
+		audio->eos_flag = 0;
+		if (!rc) {
+			audio->enabled = 1;
+		} else {
+			audio->enabled = 0;
+			pr_err("Audio Start procedure failed rc=%d\n", rc);
+			break;
+		}
+		pr_debug("%s: AUDIO_START sessionid[%d]enable[%d]\n", __func__,
+						audio->ac->session,
+						audio->enabled);
+		if (audio->stopped == 1)
+			audio->stopped = 0;
+		break;
+	}
+	default:
+		pr_debug("%s[%p]: Calling utils ioctl\n", __func__, audio);
+		rc = audio->codec_ioctl(file, cmd, arg);
+	}
+	return rc;
+}
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct q6audio_aio *audio = NULL;
+	int rc = 0;
+
+#ifdef CONFIG_DEBUG_FS
+	/* 4 bytes represents decoder number, 1 byte for terminate string */
+	char name[sizeof "msm_qcelp_" + 5];
+#endif
+	audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+	if (audio == NULL) {
+		pr_err("Could not allocate memory for aac decode driver\n");
+		return -ENOMEM;
+	}
+
+	/* Settings will be re-config at AUDIO_SET_CONFIG,
+	 * but at least we need to have initial config
+	 */
+	audio->str_cfg.buffer_size = FRAME_SIZE_DEC_QCELP;
+	audio->str_cfg.buffer_count = FRAME_NUM;
+	audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+	audio->pcm_cfg.buffer_count = PCM_BUF_COUNT;
+	audio->pcm_cfg.sample_rate = 8000;
+	audio->pcm_cfg.channel_count = 1;
+
+	audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_qcelp_cb,
+					     (void *)audio);
+
+	if (!audio->ac) {
+		pr_err("Could not allocate memory for audio client\n");
+		kfree(audio);
+		return -ENOMEM;
+	}
+
+	/* open in T/NT mode */
+	if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+					   FORMAT_V13K);
+		if (rc < 0) {
+			pr_err("NT mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = NON_TUNNEL_MODE;
+		audio->buf_cfg.frames_per_buf = 0x01;
+		audio->buf_cfg.meta_info_enable = 0x01;
+	} else if ((file->f_mode & FMODE_WRITE) &&
+			!(file->f_mode & FMODE_READ)) {
+		rc = q6asm_open_write(audio->ac, FORMAT_V13K);
+		if (rc < 0) {
+			pr_err("T mode Open failed rc=%d\n", rc);
+			rc = -ENODEV;
+			goto fail;
+		}
+		audio->feedback = TUNNEL_MODE;
+		audio->buf_cfg.meta_info_enable = 0x00;
+	} else {
+		pr_err("Not supported mode\n");
+		rc = -EACCES;
+		goto fail;
+	}
+	rc = audio_aio_open(audio, file);
+
+#ifdef CONFIG_DEBUG_FS
+	snprintf(name, sizeof name, "msm_qcelp_%04x", audio->ac->session);
+	audio->dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
+					    NULL, (void *)audio,
+					    &audio_qcelp_debug_fops);
+
+	if (IS_ERR(audio->dentry))
+		pr_debug("debugfs_create_file failed\n");
+#endif
+	pr_info("%s:dec success mode[%d]session[%d]\n", __func__,
+						audio->feedback,
+						audio->ac->session);
+	return 0;
+fail:
+	q6asm_audio_client_free(audio->ac);
+	kfree(audio);
+	return rc;
+}
+
+static const struct file_operations audio_qcelp_fops = {
+	.owner = THIS_MODULE,
+	.open = audio_open,
+	.release = audio_aio_release,
+	.unlocked_ioctl = audio_ioctl,
+	.fsync = audio_aio_fsync,
+};
+
+struct miscdevice audio_qcelp_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "msm_qcelp",
+	.fops = &audio_qcelp_fops,
+};
+
+static int __init audio_qcelp_init(void)
+{
+	return misc_register(&audio_qcelp_misc);
+}
+
+device_initcall(audio_qcelp_init);
diff --git a/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c b/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c
index 401c759..135dd03 100644
--- a/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c
+++ b/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c
@@ -297,6 +297,29 @@
 	return 0;
 }
 
+static int config_class_d1_gpio(int enable)
+{
+	int rc;
+
+	if (enable) {
+		rc = gpio_request(SNDDEV_GPIO_CLASS_D1_EN, "CLASSD1_EN");
+
+		if (rc) {
+			pr_err("%s: Right Channel spkr gpio request"
+				" failed\n", __func__);
+			return rc;
+		}
+
+		gpio_direction_output(SNDDEV_GPIO_CLASS_D1_EN, 1);
+		gpio_set_value(SNDDEV_GPIO_CLASS_D1_EN, 1);
+
+	} else {
+		gpio_set_value(SNDDEV_GPIO_CLASS_D1_EN, 0);
+		gpio_free(SNDDEV_GPIO_CLASS_D1_EN);
+	}
+	return 0;
+}
+
 static atomic_t pamp_ref_cnt;
 
 static int msm_snddev_poweramp_on(void)
@@ -312,6 +335,11 @@
 		pr_err("%s: d0 gpio configuration failed\n", __func__);
 		goto config_gpio_fail;
 	}
+	rc = config_class_d1_gpio(1);
+	if (rc) {
+		pr_err("%s: d1 gpio configuration failed\n", __func__);
+		goto config_gpio_fail;
+	}
 config_gpio_fail:
 	return rc;
 }
@@ -321,6 +349,7 @@
 	if (atomic_dec_return(&pamp_ref_cnt) == 0) {
 		pr_debug("%s: disable stereo spkr amp\n", __func__);
 		config_class_d0_gpio(0);
+		config_class_d1_gpio(0);
 		msleep(30);
 	}
 }
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index 37469f8..78a6203 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -445,8 +445,8 @@
 		return -EINVAL;
 	}
 
-	pr_info("Restart sequence requested for %s\n",
-		subsys_name);
+	pr_info("Restart sequence requested for %s, restart_level = %d.\n",
+		subsys_name, restart_level);
 
 	/* List of subsystems is protected by a lock. New subsystems can
 	 * still come in.
@@ -497,7 +497,8 @@
 		break;
 
 	case RESET_SOC:
-		panic("subsys-restart: Resetting the SoC");
+		panic("subsys-restart: Resetting the SoC - %s crashed.",
+			subsys->name);
 		break;
 
 	default:
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index f076a10..90a1c7e 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -240,8 +240,8 @@
 			return t3;
 		if ((t2-t1) <= 1)
 			return t2;
-		if (((t3-t2) == (t2-t1)) && (t3-t2) <= 8)
-			return t3;
+		if ((t2 >= t1) && (t3 >= t2))
+			return t2;
 		if (++loop_count == 5) {
 			pr_err("msm_read_timer_count timer %s did not "
 			       "stabilize: %u -> %u -> %u\n",
diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile
index 56aecab..39a7b04 100644
--- a/drivers/gpu/msm/Makefile
+++ b/drivers/gpu/msm/Makefile
@@ -1,4 +1,4 @@
-ccflags-y := -Iinclude/drm
+ccflags-y := -Iinclude/drm -Idrivers/gpu/msm
 
 msm_kgsl_core-y = \
 	kgsl.o \
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index d7c11db..2681263 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1317,6 +1317,18 @@
 	adreno_dev->gpudev->irq_control(adreno_dev, state);
 }
 
+static unsigned int adreno_gpuid(struct kgsl_device *device)
+{
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+
+	/* Standard KGSL gpuid format:
+	 * top word is 0x0002 for 2D or 0x0003 for 3D
+	 * Bottom word is core specific identifer
+	 */
+
+	return (0x0003 << 16) | ((int) adreno_dev->gpurev);
+}
+
 static const struct kgsl_functable adreno_functable = {
 	/* Mandatory functions */
 	.regread = adreno_regread,
@@ -1335,6 +1347,7 @@
 	.cleanup_pt = adreno_cleanup_pt,
 	.power_stats = adreno_power_stats,
 	.irqctrl = adreno_irqctrl,
+	.gpuid = adreno_gpuid,
 	/* Optional functions */
 	.setstate = adreno_setstate,
 	.drawctxt_create = adreno_drawctxt_create,
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 3043fd2..99c6c52 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -43,6 +43,7 @@
  */
 #define ADRENO_ISTORE_BYTES 12
 #define ADRENO_ISTORE_WORDS 3
+#define ADRENO_ISTORE_START 0x5000
 
 enum adreno_gpurev {
 	ADRENO_REV_UNKNOWN = 0,
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index 2c6cc90..c1b9e4c 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -128,7 +128,6 @@
 	return 0;
 }
 
-#define ADRENO_ISTORE_START 0x5000
 static ssize_t kgsl_istore_read(
 	struct file *file,
 	char __user *buff,
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 1c55199..3ef11ce 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -89,6 +89,7 @@
 	void (*power_stats)(struct kgsl_device *device,
 		struct kgsl_power_stats *stats);
 	void (*irqctrl)(struct kgsl_device *device, int state);
+	unsigned int (*gpuid)(struct kgsl_device *device);
 	/* Optional functions - these functions are not mandatory.  The
 	   driver will check that the function pointer is not NULL before
 	   calling the hook */
@@ -240,6 +241,11 @@
 	return device->ftbl->idle(device, timeout);
 }
 
+static inline unsigned int kgsl_gpuid(struct kgsl_device *device)
+{
+	return device->ftbl->gpuid(device);
+}
+
 static inline int kgsl_create_device_sysfs_files(struct device *root,
 	const struct device_attribute **list)
 {
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 8413fc4..cf74e64 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -888,6 +888,16 @@
 	}
 }
 
+static unsigned int z180_gpuid(struct kgsl_device *device)
+{
+	/* Standard KGSL gpuid format:
+	 * top word is 0x0002 for 2D or 0x0003 for 3D
+	 * Bottom word is core specific identifer
+	 */
+
+	return (0x0002 << 16) | 180;
+}
+
 static const struct kgsl_functable z180_functable = {
 	/* Mandatory functions */
 	.regread = z180_regread,
@@ -905,6 +915,7 @@
 	.cleanup_pt = z180_cleanup_pt,
 	.power_stats = z180_power_stats,
 	.irqctrl = z180_irqctrl,
+	.gpuid = z180_gpuid,
 	/* Optional functions */
 	.drawctxt_create = NULL,
 	.drawctxt_destroy = z180_drawctxt_destroy,
diff --git a/drivers/input/touchscreen/synaptics/rmi_f11.c b/drivers/input/touchscreen/synaptics/rmi_f11.c
index 9a23776..4caaf92 100644
--- a/drivers/input/touchscreen/synaptics/rmi_f11.c
+++ b/drivers/input/touchscreen/synaptics/rmi_f11.c
@@ -188,11 +188,7 @@
 		}
 	}
 	input_report_key(function_device->input,
-			BTN_TOUCH, fingerDownCount);
-	for (finger = 0; finger < (instanceData->sensorInfo->numberOfFingers - 1); finger++) {
-		input_report_key(function_device->input,
-			BTN_2 + finger, fingerDownCount >= (finger + 2));
-	}
+			BTN_TOUCH, !!fingerDownCount);
 
 	for (finger = 0; finger < instanceData->sensorInfo->numberOfFingers; finger++) {
 		int reg;
@@ -269,14 +265,8 @@
 				}
 #ifdef CONFIG_SYNA_MULTI_TOUCH
 				/* Report Multi-Touch events for each finger */
-				/* major axis of touch area ellipse */
-				input_report_abs(function_device->input, ABS_MT_TOUCH_MAJOR, Z);
-				/* minor axis of touch area ellipse */
-				input_report_abs(function_device->input, ABS_MT_WIDTH_MAJOR,
-						max(Wx, Wy));
-				/* Currently only 2 supported - 1 or 0 */
-				input_report_abs(function_device->input, ABS_MT_ORIENTATION,
-					(Wx > Wy ? 1 : 0));
+				input_report_abs(function_device->input,
+							ABS_MT_PRESSURE, Z);
 				input_report_abs(function_device->input, ABS_MT_POSITION_X, X);
 				input_report_abs(function_device->input, ABS_MT_POSITION_Y, Y);
 
@@ -284,7 +274,7 @@
 				/* Could be formed by keeping an id per position and assiging */
 				/* a new id when fingerStatus changes for that position.*/
 				input_report_abs(function_device->input, ABS_MT_TRACKING_ID,
-						finger+1);
+						finger);
 				/* MT sync between fingers */
 				input_mt_sync(function_device->input);
 #endif
@@ -297,17 +287,10 @@
 		instanceData->wasdown = false;
 
 #ifdef CONFIG_SYNA_MULTI_TOUCH
-		input_report_abs(function_device->input, ABS_MT_TOUCH_MAJOR, 0);
-		input_report_abs(function_device->input, ABS_MT_WIDTH_MAJOR, 0);
-		input_report_abs(function_device->input, ABS_MT_POSITION_X, instanceData->oldX);
-		input_report_abs(function_device->input, ABS_MT_POSITION_Y, instanceData->oldY);
-		input_report_abs(function_device->input, ABS_MT_TRACKING_ID, 1);
+		input_report_abs(function_device->input, ABS_MT_PRESSURE, 0);
+		input_report_key(function_device->input, BTN_TOUCH, 0);
 		input_mt_sync(function_device->input);
 #endif
-
-		input_report_abs(function_device->input, ABS_X, instanceData->oldX);
-		input_report_abs(function_device->input, ABS_Y, instanceData->oldY);
-		instanceData->oldX = instanceData->oldY = 0;
 	}
 
 	FN_11_relreport(rmifninfo);
@@ -468,10 +451,11 @@
 	input_set_abs_params(function_device->input, ABS_TOOL_WIDTH, 0, 15, 0, 0);
 
 #ifdef CONFIG_SYNA_MULTI_TOUCH
-	input_set_abs_params(function_device->input, ABS_MT_TOUCH_MAJOR, 0, 15, 0, 0);
-	input_set_abs_params(function_device->input, ABS_MT_TOUCH_MINOR, 0, 15, 0, 0);
+	input_set_abs_params(function_device->input, ABS_MT_PRESSURE,
+							0, 15, 0, 0);
 	input_set_abs_params(function_device->input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
-	input_set_abs_params(function_device->input, ABS_MT_TRACKING_ID, 1, 10, 0, 0);
+	input_set_abs_params(function_device->input, ABS_MT_TRACKING_ID,
+							0, 10, 0, 0);
 	input_set_abs_params(function_device->input, ABS_MT_POSITION_X, xMin, xMax,
 		0, 0);
 	input_set_abs_params(function_device->input, ABS_MT_POSITION_Y, yMin, yMax,
@@ -536,8 +520,8 @@
 	set_bit(EV_ABS, function_device->input->evbit);
 	set_bit(EV_SYN, function_device->input->evbit);
 	set_bit(EV_KEY, function_device->input->evbit);
-    set_bit(BTN_MISC, function_device->input->keybit);
-    set_bit(KEY_OK, function_device->input->keybit);
+	set_bit(BTN_TOUCH, function_device->input->keybit);
+	set_bit(KEY_OK, function_device->input->keybit);
 
 	f11_set_abs_params(function_device);
 
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 9a4a28c..eb0c828 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -2999,7 +2999,14 @@
 		temp_val = ctrl->value;
 		retval = hci_set_notch_filter(&temp_val, radio->fm_hdev);
 		break;
-
+	case V4L2_CID_PRIVATE_IRIS_SRCH_ALGORITHM:
+		/*
+		This private control is a place holder to keep the
+		driver compatible with changes done in the frameworks
+		which are specific to TAVARUA.
+		*/
+		retval = 0;
+		break;
 	default:
 		retval = -EINVAL;
 	}
diff --git a/drivers/net/msm_rmnet_bam.c b/drivers/net/msm_rmnet_bam.c
index 99a2c04..e40edc3 100644
--- a/drivers/net/msm_rmnet_bam.c
+++ b/drivers/net/msm_rmnet_bam.c
@@ -314,14 +314,10 @@
 	if (bam_ret != 0) {
 		pr_err("[%s] %s: write returned error %d",
 			dev->name, __func__, bam_ret);
-		goto xmit_out;
+		return -EAGAIN;
 	}
 
 	return 0;
-xmit_out:
-	/* data xmited, safe to release skb */
-	dev_kfree_skb_any(skb);
-	return 0;
 }
 
 static void bam_write_done(void *dev, struct sk_buff *skb)
@@ -450,6 +446,7 @@
 static int rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct rmnet_private *p = netdev_priv(dev);
+	int ret = 0;
 
 	if (netif_queue_stopped(dev)) {
 		pr_err("[%s]fatal: rmnet_xmit called when "
@@ -462,7 +459,11 @@
 		msm_bam_dmux_kickoff_ul_wakeup();
 		return NETDEV_TX_BUSY;
 	}
-	_rmnet_xmit(skb, dev);
+	ret = _rmnet_xmit(skb, dev);
+	if (ret == -EAGAIN) {
+		netif_start_queue(dev);
+		return NETDEV_TX_BUSY;
+	}
 
 	if (msm_bam_dmux_is_ch_full(p->ch_id)) {
 		netif_stop_queue(dev);
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index f4c86d4..85d8a08 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -1000,7 +1000,8 @@
 }
 
 static int calculate_real_fcc(struct pm8921_bms_chip *chip,
-						int batt_temp, int chargecycles)
+						int batt_temp, int chargecycles,
+						int *ret_fcc)
 {
 	int fcc, unusable_charge;
 	int remaining_charge;
@@ -1014,8 +1015,9 @@
 						&cc_mah);
 
 	real_fcc = remaining_charge - cc_mah;
-	pr_debug("real_fcc = %d, RC = %d CC = %lld\n",
-			real_fcc, remaining_charge, cc_mah);
+	*ret_fcc = fcc;
+	pr_debug("real_fcc = %d, RC = %d CC = %lld fcc = %d\n",
+			real_fcc, remaining_charge, cc_mah, fcc);
 	return real_fcc;
 }
 /*
@@ -1257,11 +1259,13 @@
 }
 EXPORT_SYMBOL_GPL(pm8921_bms_charging_began);
 
+#define DELTA_FCC_PERCENT	3
 void pm8921_bms_charging_end(int is_battery_full)
 {
 	if (is_battery_full && the_chip != NULL) {
 		unsigned long flags;
 		int batt_temp, rc, cc_reading;
+		int fcc, new_fcc, delta_fcc;
 		struct pm8xxx_adc_chan_result result;
 
 		rc = pm8xxx_adc_read(the_chip->batt_temp_channel, &result);
@@ -1273,10 +1277,24 @@
 		pr_debug("batt_temp phy = %lld meas = 0x%llx", result.physical,
 							result.measurement);
 		batt_temp = (int)result.physical;
-		last_real_fcc = calculate_real_fcc(the_chip,
-						batt_temp, last_chargecycles);
-		last_real_fcc_batt_temp = batt_temp;
-		readjust_fcc_table();
+		new_fcc = calculate_real_fcc(the_chip,
+						batt_temp, last_chargecycles,
+						&fcc);
+		delta_fcc = new_fcc - fcc;
+		if (delta_fcc < 0)
+			delta_fcc = -delta_fcc;
+
+		if (delta_fcc * 100  <= (DELTA_FCC_PERCENT * fcc)) {
+			pr_debug("delta_fcc=%d < %d percent of fcc=%d\n",
+					delta_fcc, DELTA_FCC_PERCENT, fcc);
+			last_real_fcc = new_fcc;
+			last_real_fcc_batt_temp = batt_temp;
+			readjust_fcc_table();
+		} else {
+			pr_debug("delta_fcc=%d > %d percent of fcc=%d"
+					"will not update real fcc\n",
+					delta_fcc, DELTA_FCC_PERCENT, fcc);
+		}
 
 		spin_lock_irqsave(&the_chip->bms_output_lock, flags);
 		pm_bms_lock_output_data(the_chip);
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 6b05643..e908799 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -2783,6 +2783,8 @@
 	enable_irq_wake(chip->pmic_chg_irq[USBIN_VALID_IRQ]);
 	enable_irq_wake(chip->pmic_chg_irq[USBIN_OV_IRQ]);
 	enable_irq_wake(chip->pmic_chg_irq[USBIN_UV_IRQ]);
+	enable_irq_wake(chip->pmic_chg_irq[BAT_TEMP_OK_IRQ]);
+	enable_irq_wake(chip->pmic_chg_irq[VBATDET_LOW_IRQ]);
 	/*
 	 * if both the cool_temp and warm_temp are zero the device doesnt
 	 * care for jeita compliance
diff --git a/drivers/usb/gadget/msm72k_udc.c b/drivers/usb/gadget/msm72k_udc.c
index 771ebfc..0c42292 100644
--- a/drivers/usb/gadget/msm72k_udc.c
+++ b/drivers/usb/gadget/msm72k_udc.c
@@ -1103,6 +1103,7 @@
 	struct msm_endpoint *ept = ui->ept + bit;
 	struct msm_request *req;
 	unsigned long flags;
+	int req_dequeue = 1;
 	unsigned info;
 
 	/*
@@ -1111,7 +1112,6 @@
 		ept->req, ept->req ? ept->req->item_dma : 0);
 	*/
 
-	del_timer(&ept->prime_timer);
 	/* expire all requests that are no longer active */
 	spin_lock_irqsave(&ui->lock, flags);
 	while ((req = ept->req)) {
@@ -1123,13 +1123,23 @@
 			break;
 		}
 
+dequeue:
 		/* clean speculative fetches on req->item->info */
 		dma_coherent_post_ops();
 		info = req->item->info;
 		/* if the transaction is still in-flight, stop here */
-		if (info & INFO_ACTIVE)
-			break;
+		if (info & INFO_ACTIVE) {
+			if (req_dequeue) {
+				req_dequeue = 0;
+				udelay(10);
+				goto dequeue;
+			} else {
+				break;
+			}
+		}
+		req_dequeue = 0;
 
+		del_timer(&ept->prime_timer);
 		/* advance ept queue to the next request */
 		ept->req = req->next;
 		if (ept->req == 0)
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index 11f9ef6..00b2ec1 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -97,7 +97,7 @@
 		return -ENODEV;
 	}
 
-	urb = usb_alloc_urb(0, GFP_KERNEL);
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
 	if (!urb) {
 		dev_err(&dev->udev->dev, "unable to allocate urb\n");
 		return -ENOMEM;
@@ -108,7 +108,7 @@
 				diag_bridge_read_cb, dev);
 	usb_anchor_urb(urb, &dev->submitted);
 
-	ret = usb_submit_urb(urb, GFP_KERNEL);
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
 	if (ret) {
 		dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret);
 		usb_unanchor_urb(urb);
@@ -154,7 +154,7 @@
 		return -ENODEV;
 	}
 
-	urb = usb_alloc_urb(0, GFP_KERNEL);
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
 	if (!urb) {
 		err("unable to allocate urb");
 		return -ENOMEM;
@@ -165,7 +165,7 @@
 				diag_bridge_write_cb, dev);
 	usb_anchor_urb(urb, &dev->submitted);
 
-	ret = usb_submit_urb(urb, GFP_KERNEL);
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
 	if (ret) {
 		err("submitting urb failed err:%d", ret);
 		usb_unanchor_urb(urb);
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 989b154..462ede1 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -57,7 +57,7 @@
 struct semaphore mdp_ppp_mutex;
 struct semaphore mdp_pipe_ctrl_mutex;
 
-unsigned long mdp_timer_duration = (HZ/50); /* 20 ms */
+unsigned long mdp_timer_duration = (HZ/20);   /* 50 msecond */
 
 boolean mdp_ppp_waiting = FALSE;
 uint32 mdp_tv_underflow_cnt;
@@ -237,8 +237,10 @@
 static boolean mdp_is_hist_start = FALSE;
 #endif
 static DEFINE_MUTEX(mdp_hist_mutex);
+static boolean mdp_is_hist_data = FALSE;
 
-int mdp_histogram_ctrl(boolean en)
+/*should hold mdp_hist_mutex before calling this function*/
+int _mdp_histogram_ctrl(boolean en)
 {
 	unsigned long flag;
 	unsigned long hist_base;
@@ -250,6 +252,9 @@
 		hist_base = 0x94000;
 
 	if (en == TRUE) {
+		if (mdp_is_hist_start)
+			return -EINVAL;
+
 		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 		mdp_hist_frame_cnt = 1;
 		mdp_enable_irq(MDP_HISTOGRAM_TERM);
@@ -262,7 +267,14 @@
 		MDP_OUTP(MDP_BASE + hist_base + 0x4, mdp_hist_frame_cnt);
 		MDP_OUTP(MDP_BASE + hist_base, 1);
 		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+		mdp_is_hist_data = TRUE;
 	} else {
+		if (!mdp_is_hist_start && !mdp_is_hist_data)
+			return -EINVAL;
+
+		mdp_is_hist_data = FALSE;
+		complete(&mdp_hist_comp);
+
 		if (mdp_rev >= MDP_REV_40) {
 			mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 			status = inpdw(MDP_BASE + hist_base + 0x1C);
@@ -280,6 +292,15 @@
 	return 0;
 }
 
+int mdp_histogram_ctrl(boolean en)
+{
+	int ret = 0;
+	mutex_lock(&mdp_hist_mutex);
+	ret = _mdp_histogram_ctrl(en);
+	mutex_unlock(&mdp_hist_mutex);
+	return ret;
+}
+
 int mdp_start_histogram(struct fb_info *info)
 {
 	unsigned long flag;
@@ -292,7 +313,7 @@
 		goto mdp_hist_start_err;
 	}
 
-	ret = mdp_histogram_ctrl(TRUE);
+	ret = _mdp_histogram_ctrl(TRUE);
 
 	spin_lock_irqsave(&mdp_spin_lock, flag);
 	mdp_is_hist_start = TRUE;
@@ -319,21 +340,21 @@
 	mdp_is_hist_start = FALSE;
 	spin_unlock_irqrestore(&mdp_spin_lock, flag);
 
-	ret = mdp_histogram_ctrl(FALSE);
+	ret = _mdp_histogram_ctrl(FALSE);
 
 mdp_hist_stop_err:
 	mutex_unlock(&mdp_hist_mutex);
 	return ret;
 }
 
-static int mdp_copy_hist_data(struct mdp_histogram *hist)
+/*call from within mdp_hist_mutex*/
+static int _mdp_copy_hist_data(struct mdp_histogram *hist)
 {
 	char *mdp_hist_base;
 	uint32 r_data_offset = 0x100, g_data_offset = 0x200;
 	uint32 b_data_offset = 0x300;
 	int ret = 0;
 
-	mutex_lock(&mdp_hist_mutex);
 	if (mdp_rev >= MDP_REV_42) {
 		mdp_hist_base = MDP_BASE + 0x95000;
 		r_data_offset = 0x400;
@@ -374,7 +395,6 @@
 		MDP_OUTP(mdp_hist_base, 1);
 	}
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-	mutex_unlock(&mdp_hist_mutex);
 	return 0;
 
 hist_err:
@@ -384,6 +404,8 @@
 
 static int mdp_do_histogram(struct fb_info *info, struct mdp_histogram *hist)
 {
+	int ret = 0;
+
 	if (!hist->frame_cnt || (hist->bin_cnt == 0))
 		return -EINVAL;
 
@@ -393,18 +415,29 @@
 		return -EINVAL;
 
 	mutex_lock(&mdp_hist_mutex);
+	if (!mdp_is_hist_data) {
+		ret = -EINVAL;
+		goto error;
+	}
+
 	if (!mdp_is_hist_start) {
 		printk(KERN_ERR "%s histogram not started\n", __func__);
-		mutex_unlock(&mdp_hist_mutex);
-		return -EPERM;
+		ret = -EPERM;
+		goto error;
 	}
-	mutex_unlock(&mdp_hist_mutex);
 
 	INIT_COMPLETION(mdp_hist_comp);
 	mdp_hist_frame_cnt = hist->frame_cnt;
+	mutex_unlock(&mdp_hist_mutex);
+
 	wait_for_completion_killable(&mdp_hist_comp);
 
-	return mdp_copy_hist_data(hist);
+	mutex_lock(&mdp_hist_mutex);
+	if (mdp_is_hist_data)
+		ret =  _mdp_copy_hist_data(hist);
+error:
+	mutex_unlock(&mdp_hist_mutex);
+	return ret;
 }
 #endif
 
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 2eb08b8..2bcac9c 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -139,12 +139,15 @@
 	OVERLAY_PIPE_RGB2,
 	OVERLAY_PIPE_VG1,	/* video/graphic */
 	OVERLAY_PIPE_VG2,
+	OVERLAY_PIPE_RGB3,
+	OVERLAY_PIPE_VG3,
 	OVERLAY_PIPE_MAX
 };
 
 enum {
 	OVERLAY_TYPE_RGB,
-	OVERLAY_TYPE_VIDEO
+	OVERLAY_TYPE_VIDEO,
+	OVERLAY_TYPE_BF
 };
 
 enum {
@@ -216,6 +219,10 @@
 #define MDP4_OP_SCALEX_FIR 		(0 << 2)
 #define MDP4_OP_SCALEX_MN_PHASE 	(1 << 2)
 #define MDP4_OP_SCALEX_PIXEL_RPT 	(2 << 2)
+#define MDP4_OP_SCALE_RGB_PIXEL_RPT	(0 << 3)
+#define MDP4_OP_SCALE_RGB_BILINEAR	(1 << 3)
+#define MDP4_OP_SCALE_ALPHA_PIXEL_RPT	(0 << 2)
+#define MDP4_OP_SCALE_ALPHA_BILINEAR	(1 << 2)
 #define MDP4_OP_SCALEY_EN	BIT(1)
 #define MDP4_OP_SCALEX_EN	BIT(0)
 
@@ -411,6 +418,17 @@
 }
 #endif
 
+static inline int mdp4_overlay_borderfill_supported(void)
+{
+	unsigned int mdp_hw_version;
+	mdp_hw_version = inpdw(MDP_BASE + 0x0); /* MDP_HW_VERSION */
+	return (mdp_hw_version >= 0x0402030b);
+}
+
+int mdp4_overlay_dtv_set(struct msm_fb_data_type *mfd,
+			struct mdp4_overlay_pipe *pipe);
+int mdp4_overlay_dtv_unset(struct msm_fb_data_type *mfd,
+			struct mdp4_overlay_pipe *pipe);
 void mdp4_dtv_overlay(struct msm_fb_data_type *mfd);
 int mdp4_dtv_on(struct platform_device *pdev);
 int mdp4_dtv_off(struct platform_device *pdev);
@@ -561,6 +579,7 @@
 int mdp4_mddi_overlay_blt_offset(int *off);
 void mdp4_mddi_overlay_blt(ulong addr);
 void mdp4_overlay_panel_mode(int mixer_num, uint32 mode);
+void mdp4_overlay_panel_mode_unset(int mixer_num, uint32 mode);
 int mdp4_overlay_mixer_play(int mixer_num);
 uint32 mdp4_overlay_panel_list(void);
 void mdp4_lcdc_overlay_kickoff(struct msm_fb_data_type *mfd,
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 84beb6a..72a11a2 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -71,6 +71,18 @@
 			.pipe_num = OVERLAY_PIPE_VG2,
 			.pipe_ndx = 4,
 		},
+		{
+			.pipe_type = OVERLAY_TYPE_BF,
+			.pipe_num = OVERLAY_PIPE_RGB3,
+			.pipe_ndx = 5,
+			.mixer_num = MDP4_MIXER0,
+		},
+		{
+			.pipe_type = OVERLAY_TYPE_BF,
+			.pipe_num = OVERLAY_PIPE_VG3,
+			.pipe_ndx = 6,
+			.mixer_num = MDP4_MIXER1,
+		},
 	},
 };
 
@@ -108,6 +120,11 @@
 	ctrl->panel_mode |= mode;
 }
 
+void mdp4_overlay_panel_mode_unset(int mixer_num, uint32 mode)
+{
+	ctrl->panel_mode &= ~mode;
+}
+
 uint32 mdp4_overlay_panel_list(void)
 {
 	return ctrl->panel_mode;
@@ -339,11 +356,8 @@
 
 static void mdp4_scale_setup(struct mdp4_overlay_pipe *pipe)
 {
-	int ptype;
-
 	pipe->phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
 	pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
-	ptype = mdp4_overlay_format2type(pipe->src_format);
 
 	if (pipe->dst_h && pipe->src_h != pipe->dst_h) {
 		if (pipe->dst_h > pipe->src_h * 8)	/* too much */
@@ -351,10 +365,15 @@
 		pipe->op_mode |= MDP4_OP_SCALEY_EN;
 
 		if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {
-			if (pipe->dst_h <= (pipe->src_h / 4))
+			if (pipe->alpha_enable)
+				pipe->op_mode |= MDP4_OP_SCALEY_PIXEL_RPT;
+			else if (pipe->dst_h <= (pipe->src_h / 4))
 				pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
 			else
 				pipe->op_mode |= MDP4_OP_SCALEY_FIR;
+		} else { /* RGB pipe */
+			pipe->op_mode |= MDP4_OP_SCALE_RGB_BILINEAR;
+			pipe->op_mode |= MDP4_OP_SCALE_ALPHA_BILINEAR;
 		}
 
 		pipe->phasey_step = mdp4_scale_phase_step(29,
@@ -367,10 +386,15 @@
 		pipe->op_mode |= MDP4_OP_SCALEX_EN;
 
 		if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {
-			if (pipe->dst_w <= (pipe->src_w / 4))
+			if (pipe->alpha_enable)
+				pipe->op_mode |= MDP4_OP_SCALEX_PIXEL_RPT;
+			else if (pipe->dst_w <= (pipe->src_w / 4))
 				pipe->op_mode |= MDP4_OP_SCALEX_MN_PHASE;
 			else
 				pipe->op_mode |= MDP4_OP_SCALEX_FIR;
+		} else { /* RGB pipe */
+			pipe->op_mode |= MDP4_OP_SCALE_RGB_BILINEAR;
+			pipe->op_mode |= MDP4_OP_SCALE_ALPHA_BILINEAR;
 		}
 
 		pipe->phasex_step = mdp4_scale_phase_step(29,
@@ -1212,7 +1236,9 @@
 	if (mixer == MDP4_MIXER1)
 		stage += 8;
 
-	if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {/* VG1 and VG2 */
+	if (pipe->pipe_type == OVERLAY_TYPE_BF) {
+		snum = 16 + (4 * mixer);
+	} else if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {/* VG1 and VG2 */
 		pnum -= OVERLAY_PIPE_VG1; /* start from 0 */
 		snum = 0;
 		snum += (4 * pnum);
@@ -1256,7 +1282,9 @@
 	if (mixer == MDP4_MIXER1)
 		stage += 8;
 
-	if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {/* VG1 and VG2 */
+	if (pipe->pipe_type == OVERLAY_TYPE_BF) {
+		snum = 16 + (4 * mixer);
+	} else if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {
 		pnum -= OVERLAY_PIPE_VG1; /* start from 0 */
 		snum = 0;
 		snum += (4 * pnum);
@@ -1283,8 +1311,12 @@
 	struct mdp4_overlay_pipe *bg_pipe;
 	unsigned char *overlay_base, *rgb_base;
 	uint32 c0, c1, c2, blend_op, constant_color = 0, rgb_src_format;
+	uint32 fg_color3_out;
 	int off;
 
+	if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE)
+		return;
+
 	if (pipe->mixer_num) 	/* mixer number, /dev/fb0, /dev/fb1 */
 		overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
 	else
@@ -1294,7 +1326,7 @@
 	off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0);
 
 	bg_pipe = mdp4_overlay_stage_pipe(pipe->mixer_num,
-					MDP4_MIXER_STAGE_BASE);
+					  MDP4_MIXER_STAGE_BASE);
 	if (bg_pipe == NULL) {
 		pr_err("%s: Error: no bg_pipe\n", __func__);
 		return;
@@ -1302,14 +1334,15 @@
 
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 
-	blend_op = 0;
+	blend_op = (MDP4_BLEND_FG_ALPHA_FG_CONST |
+		    MDP4_BLEND_BG_ALPHA_BG_CONST);
+	outpdw(overlay_base + off + 0x108, pipe->alpha);
+	outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha);
+	fg_color3_out = 0; /* keep bg alpha by default */
 
 	if (pipe->is_fg) {
-		blend_op |= (MDP4_BLEND_FG_ALPHA_FG_CONST |
-				MDP4_BLEND_BG_ALPHA_BG_CONST);
-		outpdw(overlay_base + off + 0x108, pipe->alpha);
-		outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha);
-		if (pipe->alpha == 0xff) {
+		if (pipe->alpha == 0xff &&
+		    bg_pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
 			rgb_base = MDP_BASE + MDP4_RGB_BASE;
 			rgb_base += MDP4_RGB_OFF * bg_pipe->pipe_num;
 			rgb_src_format = inpdw(rgb_base + 0x50);
@@ -1317,21 +1350,20 @@
 			outpdw(rgb_base + 0x50, rgb_src_format);
 			outpdw(rgb_base + 0x1008, constant_color);
 		}
-	} else {
-		if (bg_pipe->alpha_enable && pipe->alpha_enable) {
-			/* both pipe have alpha */
-			blend_op |= (MDP4_BLEND_FG_ALPHA_BG_PIXEL |
-				MDP4_BLEND_FG_INV_ALPHA |
-				MDP4_BLEND_BG_ALPHA_BG_PIXEL);
-		} else if (bg_pipe->alpha_enable && pipe->alpha_enable == 0) {
-			/* no alpha on both pipe */
-			blend_op = (MDP4_BLEND_BG_ALPHA_BG_PIXEL |
-				MDP4_BLEND_FG_ALPHA_BG_PIXEL |
-				MDP4_BLEND_FG_INV_ALPHA);
-		}
+	} else if (pipe->alpha_enable) {
+		/* pick fg alpha */
+		blend_op = (MDP4_BLEND_BG_ALPHA_FG_PIXEL |
+			    MDP4_BLEND_FG_ALPHA_FG_PIXEL |
+			    MDP4_BLEND_BG_INV_ALPHA);
+		fg_color3_out = 1; /* keep fg alpha */
+	} else if (bg_pipe->alpha_enable) {
+		/* pick bg alpha */
+		blend_op = (MDP4_BLEND_BG_ALPHA_BG_PIXEL |
+			    MDP4_BLEND_FG_ALPHA_BG_PIXEL |
+			    MDP4_BLEND_FG_INV_ALPHA);
+		fg_color3_out = 0; /* keep bg alpha */
 	}
 
-
 	if (pipe->transp != MDP_TRANSP_NOP) {
 		if (pipe->is_fg) {
 			transp_color_key(pipe->src_format, pipe->transp,
@@ -1363,6 +1395,7 @@
 	}
 
 	outpdw(overlay_base + off + 0x104, blend_op);
+	outpdw(overlay_base + (off << 5) + 0x1004, fg_color3_out);
 
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 }
@@ -1377,7 +1410,7 @@
 	else
 		bits |= 0x01;
 
-	if (all) {
+	if (all && pipe->pipe_type != OVERLAY_TYPE_BF) {
 		if (pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
 			if (pipe->pipe_num == OVERLAY_PIPE_RGB2)
 				bits |= 0x20;
@@ -1438,6 +1471,9 @@
 		if ((pipe->pipe_used == 0) && ((pipe->pipe_type == ptype) ||
 		    (ptype == OVERLAY_TYPE_RGB &&
 		     pipe->pipe_type == OVERLAY_TYPE_VIDEO))) {
+			if (ptype == OVERLAY_TYPE_BF &&
+			    mixer != pipe->mixer_num)
+				continue;
 			init_completion(&pipe->comp);
 			init_completion(&pipe->dmas_comp);
 			pr_info("%s: pipe=%x ndx=%d num=%d\n", __func__,
@@ -1454,19 +1490,21 @@
 
 void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe)
 {
-	uint32 ptype, num, ndx;
+	uint32 ptype, num, ndx, mixer;
 
 	pr_info("%s: pipe=%x ndx=%d\n", __func__, (int)pipe, pipe->pipe_ndx);
 
 	ptype = pipe->pipe_type;
 	num = pipe->pipe_num;
 	ndx = pipe->pipe_ndx;
+	mixer = pipe->mixer_num;
 
 	memset(pipe, 0, sizeof(*pipe));
 
 	pipe->pipe_type = ptype;
 	pipe->pipe_num = num;
 	pipe->pipe_ndx = ndx;
+	pipe->mixer_num = mixer;
 }
 
 int mdp4_overlay_req_check(uint32 id, uint32 z_order, uint32 mixer)
@@ -1681,17 +1719,9 @@
 		return -ENOMEM;
 	}
 
-	/* no down scale at rgb pipe */
-	if (pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
-		if ((req->src_rect.h > req->dst_rect.h) ||
-			(req->src_rect.w > req->dst_rect.w)) {
-				pr_err("%s: h>h || w>w!\n", __func__);
-				return -ERANGE;
-			}
-	}
-
 	pipe->src_format = req->src.format;
 	ret = mdp4_overlay_format2pipe(pipe);
+
 	if (ret < 0) {
 		pr_err("%s: mdp4_overlay_format2pipe!\n", __func__);
 		return ret;
@@ -1886,6 +1916,9 @@
 
 	*req = pipe->req_data;
 
+	if (mdp4_overlay_borderfill_supported())
+		req->flags |= MDP_BORDERFILL_SUPPORTED;
+
 	return 0;
 }
 
@@ -2088,6 +2121,10 @@
 			mdp4_overlay_status_write(MDP4_OVERLAY_TYPE_SET, true);
 	}
 
+	if (ctrl->panel_mode & MDP4_PANEL_DTV &&
+	    pipe->mixer_num == MDP4_MIXER1)
+		mdp4_overlay_dtv_set(mfd, pipe);
+
 	if (new_perf_level != perf_level) {
 		mdp4_update_perf_level(perf_level);
 
@@ -2110,10 +2147,8 @@
 				mdp4_overlay_dtv_vsync_push(mfd, pipe);
 		}
 	}
-
 	mutex_unlock(&mfd->dma->ov_mutex);
 
-
 #ifdef CONFIG_MSM_BUS_SCALING
 	if (pipe->mixer_num == MDP4_MIXER0) {
 		mdp_bus_scale_update_request(OVERLAY_BUS_SCALE_TABLE_BASE
@@ -2205,18 +2240,10 @@
 		mfd->ov0_blt_state = mfd->use_ov0_blt;
 
 	}
-#ifdef CONFIG_FB_MSM_DTV
 	else {	/* mixer1, DTV, ATV */
-		if (ctrl->panel_mode & MDP4_PANEL_DTV) {
-			if (mfd->panel_power_on) {
-				flags = pipe->flags;
-				pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
-				mdp4_overlay_dtv_vsync_push(mfd, pipe);
-				pipe->flags = flags;
-			}
-		}
+		if (ctrl->panel_mode & MDP4_PANEL_DTV)
+			mdp4_overlay_dtv_unset(mfd, pipe);
 	}
-#endif
 
 	/* Reset any HSIC settings to default */
 	if (pipe->flags & MDP_DPP_HSIC) {
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index d76e252..4479ece 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -430,6 +430,7 @@
 			mdp_intr_mask &= ~INTR_DMA_P_DONE;
 			outp32(MDP_INTR_ENABLE, mdp_intr_mask);
 		}
+		mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
 		mdp_disable_irq_nosync(MDP_DMA2_TERM);  /* disable intr */
 		return;
 	}
@@ -449,6 +450,8 @@
 	mdp4_stat.kickoff_dmap++;
 	/* trigger dsi cmd engine */
 	mipi_dsi_cmd_mdp_start();
+
+	mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
 }
 
 
@@ -460,6 +463,7 @@
 	int diff;
 
 	if (dsi_pipe->blt_addr == 0) {
+		mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
 		spin_lock(&mdp_spin_lock);
 		dma->busy = FALSE;
 		spin_unlock(&mdp_spin_lock);
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index d0c86d0..c8135d4 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -54,7 +54,7 @@
 
 static struct mdp4_overlay_pipe *dtv_pipe;
 
-int mdp4_dtv_on(struct platform_device *pdev)
+static int mdp4_dtv_start(struct msm_fb_data_type *mfd)
 {
 	int dtv_width;
 	int dtv_height;
@@ -86,16 +86,8 @@
 	int data_en_polarity;
 	int hsync_start_x;
 	int hsync_end_x;
-	uint8 *buf;
-	int bpp, ptype;
-	uint32 format;
 	struct fb_info *fbi;
 	struct fb_var_screeninfo *var;
-	struct msm_fb_data_type *mfd;
-	struct mdp4_overlay_pipe *pipe;
-	int ret;
-
-	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
 
 	if (!mfd)
 		return -ENODEV;
@@ -103,50 +95,12 @@
 	if (mfd->key != MFD_KEY)
 		return -EINVAL;
 
+	if (dtv_pipe == NULL)
+		return -EINVAL;
+
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
-	bpp = fbi->var.bits_per_pixel / 8;
-	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
-
-	if (bpp == 2)
-		format = MDP_RGB_565;
-	else if (bpp == 3)
-		format = MDP_RGB_888;
-	else {
-#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
-		format = MSMFB_DEFAULT_TYPE;
-#else
-		format = MDP_ARGB_8888;
-#endif
-	}
-
-	if (dtv_pipe == NULL) {
-		ptype = mdp4_overlay_format2type(format);
-		if (ptype < 0)
-			printk(KERN_INFO "%s: format2type failed\n", __func__);
-		pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER1);
-		if (pipe == NULL) {
-			printk(KERN_INFO "%s: pipe_alloc failed\n", __func__);
-			return -EBUSY;
-		}
-		pipe->pipe_used++;
-		pipe->mixer_stage  = MDP4_MIXER_STAGE_BASE;
-		pipe->mixer_num  = MDP4_MIXER1;
-		pipe->src_format = format;
-		mdp4_overlay_panel_mode(pipe->mixer_num, MDP4_PANEL_DTV);
-		ret = mdp4_overlay_format2pipe(pipe);
-		if (ret < 0)
-			printk(KERN_INFO "%s: format2type failed\n", __func__);
-
-		dtv_pipe = pipe; /* keep it */
-	} else {
-		pipe = dtv_pipe;
-	}
-
-	/* MDP cmd block enable */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 #ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
 	if (is_mdp4_hw_reset()) {
@@ -154,24 +108,8 @@
 		outpdw(MDP_BASE + 0x0038, mdp4_display_intf);
 	}
 #endif
-	pipe->src_height = fbi->var.yres;
-	pipe->src_width = fbi->var.xres;
-	pipe->src_h = fbi->var.yres;
-	pipe->src_w = fbi->var.xres;
-	pipe->src_y = 0;
-	pipe->src_x = 0;
-	pipe->srcp0_addr = (uint32) buf;
-	pipe->srcp0_ystride = fbi->fix.line_length;
-
-	mdp4_overlay_dmae_xy(pipe);	/* dma_e */
 	mdp4_overlay_dmae_cfg(mfd, 0);
 
-	mdp4_overlay_rgb_setup(pipe);
-
-	mdp4_mixer_stage_up(pipe);
-
-	mdp4_overlayproc_cfg(pipe);
-
 	/*
 	 * DTV timing setting
 	 */
@@ -255,24 +193,19 @@
 	/* Test pattern 8 x 8 pixel */
 	/* MDP_OUTP(MDP_BASE + DTV_BASE + 0x4C, 0x80000808); */
 
-	ret = panel_next_on(pdev);
-	if (ret == 0) {
-		/* enable DTV block */
-		MDP_OUTP(MDP_BASE + DTV_BASE, 1);
-		mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-		dev_info(&pdev->dev, "mdp4_overlay_dtv: on");
-	} else {
-		dev_warn(&pdev->dev, "mdp4_overlay_dtv: panel_next_on failed");
-	}
+	/* enable DTV block */
+	MDP_OUTP(MDP_BASE + DTV_BASE, 1);
+	mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	/* MDP cmd block disable */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 
-	return ret;
+	return 0;
 }
 
-int mdp4_dtv_off(struct platform_device *pdev)
+static int mdp4_dtv_stop(struct msm_fb_data_type *mfd)
 {
-	int ret = 0;
+	if (dtv_pipe == NULL)
+		return -EINVAL;
 
 	/* MDP cmd block enable */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
@@ -286,24 +219,56 @@
 	 * the last frame finishes
 	*/
 	msleep(20);
-	pr_info("%s\n", __func__);
 
-	ret = panel_next_off(pdev);
+	return 0;
+}
 
-	/* dis-engage rgb2 from mixer1 */
-	if (dtv_pipe)
+int mdp4_dtv_on(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+	int ret = 0;
+
+	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	mdp4_overlay_panel_mode(MDP4_MIXER1, MDP4_PANEL_DTV);
+	if (dtv_pipe != NULL)
+		ret = mdp4_dtv_start(mfd);
+
+	ret = panel_next_on(pdev);
+	if (ret != 0)
+		dev_warn(&pdev->dev, "mdp4_overlay_dtv: panel_next_on failed");
+
+	dev_info(&pdev->dev, "mdp4_overlay_dtv: on");
+
+	return ret;
+}
+
+int mdp4_dtv_off(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+	int ret = 0;
+
+	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+	if (dtv_pipe != NULL) {
 		mdp4_mixer_stage_down(dtv_pipe);
-
-	/*
-	 * wait for another vsync == 16.6 ms to make sure
-	 * rgb2 dis-engaged
-	*/
-	msleep(20);
-	if (dtv_pipe) {
+		mdp4_dtv_stop(mfd);
 		mdp4_overlay_pipe_free(dtv_pipe);
 		dtv_pipe = NULL;
 	}
+	mdp4_overlay_panel_mode_unset(MDP4_MIXER1, MDP4_PANEL_DTV);
 
+	ret = panel_next_off(pdev);
+
+	msleep(20);
+
+	dev_info(&pdev->dev, "mdp4_overlay_dtv: off");
 	return ret;
 }
 
@@ -327,7 +292,6 @@
 void mdp4_overlay_dtv_vsync_push(struct msm_fb_data_type *mfd,
 			struct mdp4_overlay_pipe *pipe)
 {
-
 	mdp4_overlay_reg_flush(pipe, 1);
 	if (pipe->flags & MDP_OV_PLAY_NOWAIT)
 		return;
@@ -338,6 +302,114 @@
 	mdp4_set_perf_level();
 }
 
+static void mdp4_overlay_dtv_alloc_pipe(struct msm_fb_data_type *mfd,
+		int32 ptype)
+{
+	int ret = 0;
+	struct fb_info *fbi = mfd->fbi;
+	struct mdp4_overlay_pipe *pipe;
+
+	if (dtv_pipe != NULL)
+		return;
+
+	pr_debug("%s: ptype=%d\n", __func__, ptype);
+
+	pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER1);
+	if (pipe == NULL) {
+		pr_err("%s: pipe_alloc failed\n", __func__);
+		return;
+	}
+	pipe->pipe_used++;
+	pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
+	pipe->mixer_num = MDP4_MIXER1;
+
+	if (ptype == OVERLAY_TYPE_BF) {
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+		/* LSP_BORDER_COLOR */
+		MDP_OUTP(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x5004,
+			((0x0 & 0xFFF) << 16) |	/* 12-bit B */
+			(0x0 & 0xFFF));		/* 12-bit G */
+		/* MSP_BORDER_COLOR */
+		MDP_OUTP(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x5008,
+			(0x0 & 0xFFF));		/* 12-bit R */
+		mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+		pipe->src_format = MDP_ARGB_8888;
+	} else {
+		switch (mfd->ibuf.bpp) {
+		case 2:
+			pipe->src_format = MDP_RGB_565;
+			break;
+		case 3:
+			pipe->src_format = MDP_RGB_888;
+			break;
+		case 4:
+		default:
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+			pipe->src_format = MSMFB_DEFAULT_TYPE;
+#else
+			pipe->src_format = MDP_ARGB_8888;
+#endif
+			break;
+		}
+	}
+
+	pipe->src_height = fbi->var.yres;
+	pipe->src_width = fbi->var.xres;
+	pipe->src_h = fbi->var.yres;
+	pipe->src_w = fbi->var.xres;
+	pipe->src_y = 0;
+	pipe->src_x = 0;
+	pipe->srcp0_ystride = fbi->fix.line_length;
+
+	ret = mdp4_overlay_format2pipe(pipe);
+	if (ret < 0)
+		pr_warn("%s: format2type failed\n", __func__);
+
+	mdp4_overlay_dmae_xy(pipe);	/* dma_e */
+	mdp4_overlayproc_cfg(pipe);
+	mdp4_mixer_stage_up(pipe);
+
+	dtv_pipe = pipe; /* keep it */
+}
+
+int mdp4_overlay_dtv_set(struct msm_fb_data_type *mfd,
+			struct mdp4_overlay_pipe *pipe)
+{
+	if (dtv_pipe != NULL)
+		return 0;
+
+	if (pipe != NULL && pipe->mixer_stage == MDP4_MIXER_STAGE_BASE &&
+			pipe->pipe_type == OVERLAY_TYPE_RGB)
+		dtv_pipe = pipe; /* keep it */
+	else if (mdp4_overlay_borderfill_supported())
+		mdp4_overlay_dtv_alloc_pipe(mfd, OVERLAY_TYPE_BF);
+	else
+		mdp4_overlay_dtv_alloc_pipe(mfd, OVERLAY_TYPE_RGB);
+	if (dtv_pipe == NULL)
+		return -ENODEV;
+	return mdp4_dtv_start(mfd);
+}
+
+int mdp4_overlay_dtv_unset(struct msm_fb_data_type *mfd,
+			struct mdp4_overlay_pipe *pipe)
+{
+	unsigned int flags;
+	int result = 0;
+
+	flags = pipe->flags;
+	pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
+	mdp4_overlay_dtv_vsync_push(mfd, pipe);
+	pipe->flags = flags;
+
+	if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE &&
+			pipe->pipe_type == OVERLAY_TYPE_RGB) {
+		result = mdp4_dtv_stop(mfd);
+		dtv_pipe = NULL;
+	}
+	return result;
+}
+
 static void mdp4_overlay_dtv_ov_start(struct msm_fb_data_type *mfd)
 {
 	unsigned long flag;
@@ -370,7 +442,6 @@
 void mdp4_overlay_dtv_ov_done_push(struct msm_fb_data_type *mfd,
 			struct mdp4_overlay_pipe *pipe)
 {
-
 	mdp4_overlay_reg_flush(pipe, 1);
 	mdp4_overlay_dtv_ov_start(mfd);
 
@@ -439,26 +510,25 @@
 
 void mdp4_dtv_overlay(struct msm_fb_data_type *mfd)
 {
-	struct fb_info *fbi = mfd->fbi;
-	uint8 *buf;
-	int bpp;
 	struct mdp4_overlay_pipe *pipe;
 
 	if (!mfd->panel_power_on)
 		return;
 
-	/* no need to power on cmd block since it's lcdc mode */
-	bpp = fbi->var.bits_per_pixel / 8;
-	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
-
 	mutex_lock(&mfd->dma->ov_mutex);
+	if (dtv_pipe == NULL) {
+		if (mdp4_overlay_dtv_set(mfd, NULL)) {
+			pr_warn("%s: dtv_pipe == NULL\n", __func__);
+			mutex_unlock(&mfd->dma->ov_mutex);
+			return;
+		}
+	}
 
 	pipe = dtv_pipe;
-	pipe->srcp0_addr = (uint32) buf;
-	mdp4_overlay_rgb_setup(pipe);
-
+	if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
+		pipe->srcp0_addr = (uint32) mfd->ibuf.buf;
+		mdp4_overlay_rgb_setup(pipe);
+	}
 	if (mfd->ov_start) {
 		mdp4_overlay_dtv_wait4_ov_done(mfd, pipe);
 		mfd->ov_end = true;
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
index a177976..35af84d 100644
--- a/drivers/video/msm/mipi_dsi_host.c
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -1491,7 +1491,6 @@
 
 	if (isr & DSI_INTR_CMD_MDP_DONE) {
 		mipi_dsi_mdp_stat_inc(STAT_DSI_MDP);
-		mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
 		spin_lock(&dsi_mdp_lock);
 		dsi_mdp_busy = FALSE;
 		spin_unlock(&dsi_mdp_lock);
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index e1b9e73..4900e9c 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -430,3 +430,4 @@
 header-y += qcedev.h
 header-y += idle_stats_device.h
 header-y += genlock.h
+header-y += msm_audio_amrwb.h
diff --git a/include/linux/msm_audio_amrwb.h b/include/linux/msm_audio_amrwb.h
new file mode 100644
index 0000000..2383743
--- /dev/null
+++ b/include/linux/msm_audio_amrwb.h
@@ -0,0 +1,18 @@
+#ifndef __MSM_AUDIO_AMRWB_H
+#define __MSM_AUDIO_AMRWB_H
+
+#include <linux/msm_audio.h>
+
+#define AUDIO_GET_AMRWB_ENC_CONFIG _IOW(AUDIO_IOCTL_MAGIC, \
+	(AUDIO_MAX_COMMON_IOCTL_NUM+0), \
+	struct msm_audio_amrwb_enc_config)
+#define AUDIO_SET_AMRWB_ENC_CONFIG  _IOR(AUDIO_IOCTL_MAGIC, \
+	(AUDIO_MAX_COMMON_IOCTL_NUM+1), \
+	struct msm_audio_amrwb_enc_config)
+
+struct msm_audio_amrwb_enc_config {
+	uint32_t band_mode;
+	uint32_t dtx_enable;
+	uint32_t frame_format;
+};
+#endif /* __MSM_AUDIO_AMRWB_H */
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 5c67471..0c09799 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -139,6 +139,7 @@
 #define MDP_DEINTERLACE_ODD		0x00400000
 #define MDP_OV_PLAY_NOWAIT		0x00200000
 #define MDP_SOURCE_ROTATED_90		0x00100000
+#define MDP_BORDERFILL_SUPPORTED	0x00010000
 #define MDP_MEMORY_ID_TYPE_FB		0x00001000
 #define MDP_DPP_HSIC			0x00080000
 
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index 130bc3d..489c248 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -544,17 +544,18 @@
 	V4L2_CID_PRIVATE_IRIS_SSBI_POKE,
 	V4L2_CID_PRIVATE_IRIS_TX_TONE,
 	V4L2_CID_PRIVATE_IRIS_RDS_GRP_COUNTERS,
-	V4L2_CID_PRIVATE_IRIS_SET_NOTCH_FILTER,/*0x8000028*/
-	/*0x8000029 is used for tavarua specific ioctl*/
-	V4L2_CID_PRIVATE_IRIS_DO_CALIBRATION = 0x800002a,
-	V4L2_CID_PRIVATE_IRIS_READ_DEFAULT = 0x00980928,/*using private CIDs
-							under userclass*/
+	V4L2_CID_PRIVATE_IRIS_SET_NOTCH_FILTER, /* 0x8000028 */
+	V4L2_CID_PRIVATE_IRIS_SET_AUDIO_PATH, /* TAVARUA specific command */
+	V4L2_CID_PRIVATE_IRIS_DO_CALIBRATION,
+	V4L2_CID_PRIVATE_IRIS_SRCH_ALGORITHM, /* TAVARUA specific command */
+
+	/*using private CIDs under userclass*/
+	V4L2_CID_PRIVATE_IRIS_READ_DEFAULT = 0x00980928,
 	V4L2_CID_PRIVATE_IRIS_WRITE_DEFAULT,
 	V4L2_CID_PRIVATE_IRIS_SET_CALIBRATION,
 };
 
 
-
 enum iris_evt_t {
 	IRIS_EVT_RADIO_READY,
 	IRIS_EVT_TUNE_SUCC,
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 5a15cec..ca15ed0 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -576,7 +576,7 @@
 {
 	atomic_inc(&chan->refcnt);
 }
-void hci_chan_put(struct hci_chan *chan);
+int hci_chan_put(struct hci_chan *chan);
 
 struct hci_chan *hci_chan_accept(struct hci_conn *hcon,
 				struct hci_ext_fs *tx_fs,
diff --git a/mm/Kconfig b/mm/Kconfig
index 8ca47a5..9f30530 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -136,7 +136,7 @@
 	bool "Allow for memory hot-add"
 	depends on SPARSEMEM || X86_64_ACPI_NUMA
 	depends on HOTPLUG && ARCH_ENABLE_MEMORY_HOTPLUG
-	depends on (IA64 || X86 || PPC_BOOK3S_64 || SUPERH || S390)
+	depends on (IA64 || X86 || PPC_BOOK3S_64 || SUPERH || S390 || ARM)
 
 config MEMORY_HOTPLUG_SPARSE
 	def_bool y
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 5e67829..95718bb 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -505,13 +505,13 @@
 	return 0;
 }
 
-void hci_chan_put(struct hci_chan *chan)
+int hci_chan_put(struct hci_chan *chan)
 {
 	struct hci_cp_disconn_logical_link cp;
 
 	BT_DBG("chan %p refcnt %d", chan, atomic_read(&chan->refcnt));
 	if (!atomic_dec_and_test(&chan->refcnt))
-		return;
+		return 0;
 
 	BT_DBG("chan->conn->state %d", chan->conn->state);
 	if (chan->conn->state == BT_CONNECTED) {
@@ -520,6 +520,8 @@
 				sizeof(cp), &cp);
 	} else
 		hci_chan_del(chan);
+
+	return 1;
 }
 EXPORT_SYMBOL(hci_chan_put);
 
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 4c50713..a3f3563 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -549,8 +549,7 @@
 		l2cap_pi(sk)->ampcon->l2cap_data = NULL;
 		l2cap_pi(sk)->ampcon = NULL;
 		if (l2cap_pi(sk)->ampchan) {
-			hci_chan_put(l2cap_pi(sk)->ampchan);
-			if (atomic_read(&l2cap_pi(sk)->ampchan->refcnt))
+			if (!hci_chan_put(l2cap_pi(sk)->ampchan))
 				l2cap_deaggregate(l2cap_pi(sk)->ampchan,
 							l2cap_pi(sk));
 		}
@@ -1445,6 +1444,9 @@
 		 */
 		tx_skb = skb_clone(skb, GFP_ATOMIC);
 
+		if (!tx_skb)
+			break;
+
 		sock_hold(sk);
 		tx_skb->sk = sk;
 		tx_skb->destructor = l2cap_skb_destructor;
@@ -3084,8 +3086,9 @@
 			if (new->sdu_arr_time)
 				new_rate = div_u64(new_rate, new->sdu_arr_time);
 			cur_rate = cur_rate + new_rate;
-			agg->sdu_arr_time = div64_u64(agg->max_sdu * 1000000ULL,
-				cur_rate);
+			if (cur_rate)
+				agg->sdu_arr_time = div64_u64(
+					agg->max_sdu * 1000000ULL, cur_rate);
 		}
 	}
 }
@@ -3126,8 +3129,9 @@
 		if (old->sdu_arr_time)
 			old_rate = div_u64(old_rate, old->sdu_arr_time);
 		cur_rate = cur_rate - old_rate;
-		agg->sdu_arr_time = div64_u64(agg->max_sdu * 1000000ULL,
-								cur_rate);
+		if (cur_rate)
+			agg->sdu_arr_time = div64_u64(
+				agg->max_sdu * 1000000ULL, cur_rate);
 	}
 }
 
@@ -5056,8 +5060,7 @@
 			if ((!l2cap_pi(sk)->amp_id) &&
 						(l2cap_pi(sk)->ampchan)) {
 				/* Have moved off of AMP, free the channel */
-				hci_chan_put(l2cap_pi(sk)->ampchan);
-				if (atomic_read(&l2cap_pi(sk)->ampchan->refcnt))
+				if (!hci_chan_put(l2cap_pi(sk)->ampchan))
 					l2cap_deaggregate(l2cap_pi(sk)->ampchan,
 								l2cap_pi(sk));
 				l2cap_pi(sk)->ampchan = NULL;
@@ -5115,8 +5118,7 @@
 			/* Have moved off of AMP, free the channel */
 			l2cap_pi(sk)->ampcon = NULL;
 			if (l2cap_pi(sk)->ampchan) {
-				hci_chan_put(l2cap_pi(sk)->ampchan);
-				if (atomic_read(&l2cap_pi(sk)->ampchan->refcnt))
+				if (!hci_chan_put(l2cap_pi(sk)->ampchan))
 					l2cap_deaggregate(l2cap_pi(sk)->ampchan,
 								l2cap_pi(sk));
 			}
@@ -5831,6 +5833,11 @@
 			tx_skb = skb_clone(skb, GFP_ATOMIC);
 		}
 
+		if (!tx_skb) {
+			l2cap_seq_list_clear(&pi->retrans_list);
+			break;
+		}
+
 		/* Update skb contents */
 		if (pi->extended_control) {
 			put_unaligned_le32(__pack_extended_control(&control),
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index de6f8e1..1f4b2f8 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2784,6 +2784,13 @@
 			     $herecurr);
 		}
 
+# MSM - check if a non board-gpiomux file has any gpiomux declarations
+	if ($realfile =~ /\/mach-msm\/board-[0-9]+/ &&
+	    $realfile !~ /camera/ && $realfile !~ /gpiomux/ &&
+	    $line =~ /\s*struct msm_gpiomux_config\s*/ ) {
+		WARN("Non gpiomux board file cannot have a gpiomux config declarations. Please declare gpiomux configs in board-*-gpiomux.c file.\n" . $herecurr);
+	}
+
 # unbounded string functions are overflow risks
 		my %str_fns = (
 			"sprintf" => "snprintf",
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index ba59920..5003ab5 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -3358,7 +3358,7 @@
 		 */
 		if (priv->mbhc_micbias_switched)
 			tabla_codec_switch_micbias(codec, 0);
-		priv->hph_status &= ~SND_JACK_HEADSET;
+		priv->hph_status &= ~SND_JACK_HEADPHONE;
 		if (priv->headset_jack) {
 			pr_debug("%s: Reporting removal\n", __func__);
 			snd_soc_jack_report(priv->headset_jack,
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 0082339..bfc004e 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -919,6 +919,15 @@
 		.platform_name  = "msm-pcm-afe",
 		.ignore_suspend = 1,
 	},
+	{
+		.name = "MSM8960 Compr",
+		.stream_name = "COMPR",
+		.cpu_dai_name	= "MultiMedia4",
+		.platform_name  = "msm-compr-dsp",
+		.dynamic = 1,
+		.dsp_link = &lpa_fe_media,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
+	},
 	/* Backend DAI Links */
 	{
 		.name = LPASS_BE_SLIMBUS_0_RX,