Merge changes I5359aee9,Ia2e526aa into msm-3.0

* changes:
  msm_serial_hs_lite: Use new clock framework apis
  msm_serial_hs_lite: Cleanup regarding usage of clock enable/disable apis
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 0455878..bb4d971 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -65,6 +65,7 @@
 	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 saved_dist_pri[DIV_ROUND_UP(1020, 4)];
 	u32 __percpu *saved_ppi_enable;
 	u32 __percpu *saved_ppi_conf;
 #endif
@@ -79,6 +80,10 @@
 
 static DEFINE_RAW_SPINLOCK(irq_controller_lock);
 
+#ifdef CONFIG_CPU_PM
+static unsigned int saved_dist_ctrl, saved_cpu_ctrl;
+#endif
+
 /* Address of GIC 0 CPU interface */
 void __iomem *gic_cpu_base_addr __read_mostly;
 
@@ -151,6 +156,26 @@
 	return d->hwirq;
 }
 
+#ifdef CONFIG_CPU_V7
+static const inline bool is_cpu_secure(void)
+{
+	unsigned int dscr;
+
+	asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (dscr));
+
+	/* BIT(18) - NS bit; 1 = NS; 0 = S */
+	if (BIT(18) & dscr)
+		return false;
+	else
+		return true;
+}
+#else
+static const inline bool is_cpu_secure(void)
+{
+	return false;
+}
+#endif
+
 /*
  * Routines to acknowledge, disable and enable interrupts
  */
@@ -506,6 +531,14 @@
 		writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
 
 	/*
+	 * Set NS/S.
+	 */
+	if (is_cpu_secure())
+		for (i = 32; i < gic_irqs; i += 32)
+			writel_relaxed(0xFFFFFFFF,
+					base + GIC_DIST_ISR + i * 4 / 32);
+
+	/*
 	 * Set priority on all global interrupts.
 	 */
 	for (i = 32; i < gic_irqs; i += 4)
@@ -537,7 +570,11 @@
 
 	gic->max_irq = gic_irqs;
 
-	writel_relaxed(1, base + GIC_DIST_CTRL);
+	if (is_cpu_secure())
+		writel_relaxed(3, base + GIC_DIST_CTRL);
+	else
+		writel_relaxed(1, base + GIC_DIST_CTRL);
+
 	mb();
 }
 
@@ -554,6 +591,10 @@
 	writel_relaxed(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
 	writel_relaxed(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
 
+	/* Set NS/S */
+	if (is_cpu_secure())
+		writel_relaxed(0xFFFFFFFF, dist_base + GIC_DIST_ISR);
+
 	/*
 	 * Set priority on PPI and SGI interrupts
 	 */
@@ -561,7 +602,11 @@
 		writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
 
 	writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
-	writel_relaxed(1, base + GIC_CPU_CTRL);
+
+	if (is_cpu_secure())
+		writel_relaxed(0xF, base + GIC_CPU_CTRL);
+	else
+		writel_relaxed(1, base + GIC_CPU_CTRL);
     mb();
 }
 
@@ -587,6 +632,8 @@
 	if (!dist_base)
 		return;
 
+	saved_dist_ctrl = readl_relaxed(dist_base + GIC_DIST_CTRL);
+
 	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);
@@ -595,6 +642,10 @@
 		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, 4); i++)
+		gic_data[gic_nr].saved_dist_pri[i] =
+			readl_relaxed(dist_base + GIC_DIST_PRI + 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);
@@ -629,7 +680,7 @@
 			dist_base + GIC_DIST_CONFIG + i * 4);
 
 	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
-		writel_relaxed(0xa0a0a0a0,
+		writel_relaxed(gic_data[gic_nr].saved_dist_pri[i],
 			dist_base + GIC_DIST_PRI + i * 4);
 
 	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
@@ -640,7 +691,7 @@
 		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);
+	writel_relaxed(saved_dist_ctrl, dist_base + GIC_DIST_CTRL);
 }
 
 static void gic_cpu_save(unsigned int gic_nr)
@@ -659,6 +710,12 @@
 	if (!dist_base || !cpu_base)
 		return;
 
+	saved_cpu_ctrl = readl_relaxed(cpu_base + GIC_CPU_CTRL);
+
+	for (i = 0; i < DIV_ROUND_UP(32, 4); i++)
+		gic_data[gic_nr].saved_dist_pri[i] = readl_relaxed(dist_base +
+							GIC_DIST_PRI + i * 4);
+
 	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);
@@ -694,10 +751,11 @@
 		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(gic_data[gic_nr].saved_dist_pri[i],
+			dist_base + GIC_DIST_PRI + i * 4);
 
 	writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
-	writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
+	writel_relaxed(saved_cpu_ctrl, cpu_base + GIC_CPU_CTRL);
 }
 
 static int gic_notifier(struct notifier_block *self, unsigned long cmd,	void *v)
@@ -884,12 +942,17 @@
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 {
 	int cpu;
+	unsigned long sgir;
 	unsigned long map = 0;
 
 	/* Convert our logical CPU mask into a physical one. */
 	for_each_cpu(cpu, mask)
 		map |= 1 << cpu_logical_map(cpu);
 
+	sgir = (map << 16) | irq;
+	if (is_cpu_secure())
+		sgir |= (1 << 15);
+
 	/*
 	 * Ensure that stores to Normal memory are visible to the
 	 * other CPUs before issuing the IPI.
@@ -897,11 +960,40 @@
 	dsb();
 
 	/* this always happens on GIC0 */
-	writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
+	writel_relaxed(sgir,
+			gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
 	mb();
 }
 #endif
 
+void gic_set_irq_secure(unsigned int irq)
+{
+	unsigned int gicd_isr_reg, gicd_pri_reg;
+	unsigned int mask = 0xFFFFFF00;
+	struct gic_chip_data *gic_data = &gic_data[0];
+	struct irq_data *d = irq_get_irq_data(irq);
+
+	if (is_cpu_secure()) {
+		raw_spin_lock(&irq_controller_lock);
+		gicd_isr_reg = readl_relaxed(gic_dist_base(d) +
+				GIC_DIST_ISR + gic_irq(d) / 32 * 4);
+		gicd_isr_reg &= ~BIT(gic_irq(d) % 32);
+		writel_relaxed(gicd_isr_reg, gic_dist_base(d) +
+				GIC_DIST_ISR + gic_irq(d) / 32 * 4);
+		/* Also increase the priority of that irq */
+		gicd_pri_reg = readl_relaxed(gic_dist_base(d) +
+					GIC_DIST_PRI + (gic_irq(d) * 4 / 4));
+		gicd_pri_reg &= mask;
+		gicd_pri_reg |= 0x80; /* Priority of 0x80 > 0xA0 */
+		writel_relaxed(gicd_pri_reg, gic_dist_base(d) + GIC_DIST_PRI +
+				gic_irq(d) * 4 / 4);
+		mb();
+		raw_spin_unlock(&irq_controller_lock);
+	} else {
+		WARN(1, "Trying to run secure operation from Non-secure mode");
+	}
+}
+
 /* before calling this function the interrupts should be disabled
  * and the irq must be disabled at gic to avoid spurious interrupts */
 bool gic_is_spi_pending(unsigned int irq)
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 76ff09c..3c87f8d 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -54,6 +54,7 @@
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
 CONFIG_CP_ACCESS=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 3ddb0c9..cc33b8f 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -54,6 +54,7 @@
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
 CONFIG_CP_ACCESS=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index eca2ffac..22cf652 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -74,6 +74,7 @@
 CONFIG_MSM_TZ_LOG=y
 CONFIG_MSM_RPM_LOG=y
 CONFIG_MSM_RPM_STATS_LOG=y
+CONFIG_MSM_IOMMU=y
 CONFIG_MSM_BUS_SCALING=y
 CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y
 CONFIG_MSM_WATCHDOG=y
@@ -266,9 +267,7 @@
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PMIC8XXX_PWRKEY=y
 # CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_HS=y
-# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
 CONFIG_SERIAL_MSM_HSL=y
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
 CONFIG_DIAG_CHAR=y
@@ -329,9 +328,10 @@
 CONFIG_FB_MSM_MDP40=y
 CONFIG_FB_MSM_OVERLAY=y
 CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y
-CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
+CONFIG_FB_MSM_OVERLAY1_WRITEBACK=y
 CONFIG_FB_MSM_MIPI_PANEL_DETECT=y
 CONFIG_FB_MSM_HDMI_MSM_PANEL=y
+CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_SOUND=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 18e9085..c38c161 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -74,6 +74,7 @@
 CONFIG_MSM_TZ_LOG=y
 CONFIG_MSM_RPM_LOG=y
 CONFIG_MSM_RPM_STATS_LOG=y
+CONFIG_MSM_IOMMU=y
 CONFIG_MSM_BUS_SCALING=y
 CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y
 CONFIG_MSM_WATCHDOG=y
@@ -267,9 +268,7 @@
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_PMIC8XXX_PWRKEY=y
 # CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_HS=y
-# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
 CONFIG_SERIAL_MSM_HSL=y
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
 CONFIG_DIAG_CHAR=y
@@ -330,6 +329,7 @@
 CONFIG_FB_MSM_MDP40=y
 CONFIG_FB_MSM_OVERLAY=y
 CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y
+CONFIG_FB_MSM_OVERLAY1_WRITEBACK=y
 CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
 CONFIG_FB_MSM_MIPI_PANEL_DETECT=y
 CONFIG_FB_MSM_HDMI_MSM_PANEL=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index d34f5dfb..543a4f9f 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -47,12 +47,13 @@
 # CONFIG_MSM_SYSMON_COMM is not set
 CONFIG_MSM_MODEM_8960=y
 CONFIG_MSM_LPASS_8960=y
+CONFIG_MSM_RPM_LOG=y
+CONFIG_MSM_RPM_STATS_LOG=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_MSM_BUS_SCALING=y
 CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y
 CONFIG_MSM_WATCHDOG=y
 CONFIG_MSM_DLOAD_MODE=y
-# CONFIG_MSM_JTAG_V7 is not set
 CONFIG_SWP_EMULATE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -73,6 +74,8 @@
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
 # CONFIG_INET_XFRM_MODE_TRANSPORT is not set
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
@@ -83,7 +86,62 @@
 # CONFIG_INET6_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET6_XFRM_MODE_BEET is not set
 # CONFIG_IPV6_SIT is not set
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
 # CONFIG_ANDROID_PARANOID_NETWORK is not set
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+CONFIG_NETFILTER_NETLINK_QUEUE=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NETFILTER_XT_MARK=y
+CONFIG_NETFILTER_XT_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_IP_SET=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_IP_NF_TARGET_ULOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_ECN=y
+CONFIG_IP_NF_TARGET_TTL=y
+CONFIG_IP_NF_RAW=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_AH=y
+CONFIG_IP6_NF_MATCH_FRAG=y
+CONFIG_IP6_NF_MATCH_OPTS=y
+CONFIG_IP6_NF_MATCH_HL=y
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+CONFIG_IP6_NF_MATCH_MH=y
+CONFIG_IP6_NF_MATCH_RT=y
+CONFIG_IP6_NF_TARGET_LOG=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
 CONFIG_CFG80211=y
 CONFIG_MTD=y
 CONFIG_MTD_TESTS=m
@@ -137,6 +195,8 @@
 CONFIG_SLIMBUS_MSM_CTRL=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_BATTERY_MSM is not set
 CONFIG_SENSORS_PM8XXX_ADC=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8960=y
@@ -168,8 +228,6 @@
 CONFIG_USB_G_ANDROID=y
 CONFIG_RMNET_SMD_CTL_CHANNEL="DATA36_CNTL"
 CONFIG_RMNET_SMD_DATA_CHANNEL="DATA36"
-CONFIG_POWER_SUPPLY=y
-# CONFIG_BATTERY_MSM is not set
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_UNSAFE_RESUME=y
@@ -230,5 +288,3 @@
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
-CONFIG_MSM_RPM_LOG=y
-CONFIG_MSM_RPM_STATS_LOG=y
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 8bfbcfa..5bb5139 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -22,6 +22,7 @@
 
 #define GIC_DIST_CTRL			0x000
 #define GIC_DIST_CTR			0x004
+#define GIC_DIST_ISR			0x080
 #define GIC_DIST_ENABLE_SET		0x100
 #define GIC_DIST_ENABLE_CLEAR		0x180
 #define GIC_DIST_PENDING_SET		0x200
@@ -49,6 +50,7 @@
 void gic_enable_ppi(unsigned int);
 bool gic_is_spi_pending(unsigned int irq);
 void gic_clear_spi_pending(unsigned int irq);
+void gic_set_irq_secure(unsigned int irq);
 
 static inline void gic_init(unsigned int nr, int start,
 			    void __iomem *dist , void __iomem *cpu)
diff --git a/arch/arm/kernel/perf_event_msm.c b/arch/arm/kernel/perf_event_msm.c
index a55ce3f..0ca5164 100644
--- a/arch/arm/kernel/perf_event_msm.c
+++ b/arch/arm/kernel/perf_event_msm.c
@@ -21,6 +21,8 @@
 #define SCORPION_EVT_PREFIX 1
 #define SCORPION_MAX_L1_REG 4
 
+#define SCORPION_EVTYPE_EVENT 0xfffff
+
 static u32 scorpion_evt_type_base[] = {0x4c, 0x50, 0x54, 0x58, 0x5c};
 
 enum scorpion_perf_common {
@@ -380,12 +382,14 @@
 		evtinfo->group_setval = 0x80000000 | (code << (group * 8));
 		evtinfo->groupcode = reg;
 		evtinfo->armv7_evt_type = scorpion_evt_type_base[reg] | group;
+
 		return evtinfo->armv7_evt_type;
 	}
 
 	if (scorpion_evt_type < SCORPION_EVT_START_IDX || scorpion_evt_type >=
 		(ARRAY_SIZE(scorpion_event) + SCORPION_EVT_START_IDX))
 		return -EINVAL;
+
 	idx = scorpion_evt_type - SCORPION_EVT_START_IDX;
 	if (scorpion_event[idx].scorpion_evt_type == scorpion_evt_type) {
 		evtinfo->group_setval = scorpion_event[idx].group_setval;
@@ -594,7 +598,7 @@
 	 */
 	if (idx != ARMV7_CYCLE_COUNTER) {
 		val = hwc->config_base;
-		val &= ARMV7_EVTYPE_EVENT;
+		val &= SCORPION_EVTYPE_EVENT;
 
 		if (val > 0x40) {
 			event = get_scorpion_evtinfo(val, &evtinfo);
@@ -636,7 +640,7 @@
 	 */
 	if (idx != ARMV7_CYCLE_COUNTER) {
 		val = hwc->config_base;
-		val &= ARMV7_EVTYPE_EVENT;
+		val &= SCORPION_EVTYPE_EVENT;
 
 		if (val < 0x40) {
 			armv7_pmnc_write_evtsel(idx, hwc->config_base);
@@ -676,7 +680,7 @@
 {
 	int irq = *(unsigned int *)info;
 
-	enable_percpu_irq(irq, 0);
+	enable_percpu_irq(irq, IRQ_TYPE_EDGE_RISING);
 }
 
 static void disable_irq_callback(void *info)
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 4328ac3..ea64ba6 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -468,9 +468,7 @@
 static void ipi_timer(void)
 {
 	struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
-	irq_enter();
 	evt->event_handler(evt);
-	irq_exit();
 }
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
@@ -624,7 +622,9 @@
 		/* Wake up from WFI/WFE using SGI */
 		break;
 	case IPI_TIMER:
+		irq_enter();
 		ipi_timer();
+		irq_exit();
 		break;
 
 	case IPI_RESCHEDULE:
@@ -632,15 +632,21 @@
 		break;
 
 	case IPI_CALL_FUNC:
+		irq_enter();
 		generic_smp_call_function_interrupt();
+		irq_exit();
 		break;
 
 	case IPI_CALL_FUNC_SINGLE:
+		irq_enter();
 		generic_smp_call_function_single_interrupt();
+		irq_exit();
 		break;
 
 	case IPI_CPU_STOP:
+		irq_enter();
 		ipi_cpu_stop(cpu);
+		irq_exit();
 		break;
 
 	case IPI_CPU_BACKTRACE:
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 904839b9..0b0f733 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -126,6 +126,7 @@
 	select MSM_SPM_V1
 	select MSM_SCM if SMP
 	select MULTI_IRQ_HANDLER
+	select MSM_MULTIMEDIA_USE_ION
 	select MSM_PM8X60 if PM
 
 config ARCH_MSM8960
@@ -257,6 +258,7 @@
 	select MSM_RPM_REGULATOR
 	select MULTI_IRQ_HANDLER
 	select MSM_PM8X60 if PM
+	select MSM_XO
 
 config ARCH_MSM8625
 	bool "MSM8625"
@@ -449,7 +451,15 @@
         default y
         bool "MSM7627A QRD1"
         help
-          Support for the Qualcomm MSM7627A Refrence Design.
+          Support for the Qualcomm MSM7627A Reference Design.
+
+config MACH_MSM7627A_QRD3
+        depends on ARCH_MSM7X27A
+        depends on !MSM_STACKED_MEMORY
+        default y
+        bool "MSM7627A QRD3"
+        help
+          Support for the Qualcomm MSM7627A Reference Design.
 
 config MACH_MSM7627A_EVB
         depends on ARCH_MSM7X27A
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 19a316e..b2f7c84d 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -172,6 +172,7 @@
 obj-$(CONFIG_ARCH_MSM8960) += rpm-regulator-8960.o
 obj-$(CONFIG_ARCH_MSM9615) += rpm-regulator-9615.o
 obj-$(CONFIG_ARCH_MSM8930) += rpm-regulator-8930.o
+obj-$(CONFIG_ARCH_APQ8064) += rpm-regulator-8960.o
 endif
 
 ifdef CONFIG_MSM_SUBSYSTEM_RESTART
@@ -217,6 +218,7 @@
 obj-$(CONFIG_MACH_MSM7X27A_SURF) += board-msm7x27a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
 obj-$(CONFIG_MACH_MSM7X27A_FFA) += board-msm7x27a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
 obj-$(CONFIG_MACH_MSM7627A_QRD1) += board-qrd7627a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
+obj-$(CONFIG_MACH_MSM7627A_QRD3) += board-qrd7627a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
 obj-$(CONFIG_MACH_MSM7627A_EVB) += board-qrd7627a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
 obj-$(CONFIG_ARCH_MSM8625) += devices-msm7x27a.o clock-pcom-lookup.o
 obj-$(CONFIG_MACH_MSM8625_RUMI3) += board-msm7x27a.o
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 61c742d..470e836 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -463,81 +463,81 @@
 static struct acpu_level acpu_freq_tbl_8960_kraitv2_slow[] = {
 	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   950000 },
 	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   950000 },
-	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   975000 },
-	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(6),   975000 },
-	{ 1, {   540000, HFPLL, 2, 0, 0x28 }, L2(6),  1000000 },
-	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(6),  1000000 },
-	{ 1, {   648000, HFPLL, 1, 0, 0x18 }, L2(6),  1025000 },
-	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(6),  1025000 },
-	{ 1, {   756000, HFPLL, 1, 0, 0x1C }, L2(11), 1075000 },
-	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(11), 1075000 },
-	{ 1, {   864000, HFPLL, 1, 0, 0x20 }, L2(11), 1100000 },
-	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(11), 1100000 },
-	{ 1, {   972000, HFPLL, 1, 0, 0x24 }, L2(16), 1125000 },
-	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1125000 },
-	{ 1, {  1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1175000 },
+	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(7),   975000 },
+	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(7),   975000 },
+	{ 0, {   540000, HFPLL, 2, 0, 0x28 }, L2(7),  1000000 },
+	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(7),  1000000 },
+	{ 0, {   648000, HFPLL, 1, 0, 0x18 }, L2(7),  1025000 },
+	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(7),  1025000 },
+	{ 0, {   756000, HFPLL, 1, 0, 0x1C }, L2(7),  1075000 },
+	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(7),  1075000 },
+	{ 0, {   864000, HFPLL, 1, 0, 0x20 }, L2(7),  1100000 },
+	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(7),  1100000 },
+	{ 0, {   972000, HFPLL, 1, 0, 0x24 }, L2(7),  1125000 },
+	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(7),  1125000 },
+	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1175000 },
 	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1175000 },
-	{ 1, {  1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1200000 },
-	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(19), 1200000 },
-	{ 1, {  1296000, HFPLL, 1, 0, 0x30 }, L2(19), 1225000 },
-	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(19), 1225000 },
-	{ 1, {  1404000, HFPLL, 1, 0, 0x34 }, L2(19), 1237500 },
-	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(19), 1237500 },
-	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(19), 1250000 },
+	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1200000 },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1200000 },
+	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1225000 },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1225000 },
+	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1237500 },
+	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(16), 1237500 },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(16), 1250000 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_8960_kraitv2_nom[] = {
 	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   900000 },
 	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   900000 },
-	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   925000 },
-	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(6),   925000 },
-	{ 1, {   540000, HFPLL, 2, 0, 0x28 }, L2(6),   950000 },
-	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(6),   950000 },
-	{ 1, {   648000, HFPLL, 1, 0, 0x18 }, L2(6),   975000 },
-	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(6),   975000 },
-	{ 1, {   756000, HFPLL, 1, 0, 0x1C }, L2(11), 1025000 },
-	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(11), 1025000 },
-	{ 1, {   864000, HFPLL, 1, 0, 0x20 }, L2(11), 1050000 },
-	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(11), 1050000 },
-	{ 1, {   972000, HFPLL, 1, 0, 0x24 }, L2(16), 1075000 },
-	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1075000 },
-	{ 1, {  1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1125000 },
+	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(7),   925000 },
+	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(7),   925000 },
+	{ 0, {   540000, HFPLL, 2, 0, 0x28 }, L2(7),   950000 },
+	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(7),   950000 },
+	{ 0, {   648000, HFPLL, 1, 0, 0x18 }, L2(7),   975000 },
+	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(7),   975000 },
+	{ 0, {   756000, HFPLL, 1, 0, 0x1C }, L2(7),  1025000 },
+	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(7),  1025000 },
+	{ 0, {   864000, HFPLL, 1, 0, 0x20 }, L2(7),  1050000 },
+	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(7),  1050000 },
+	{ 0, {   972000, HFPLL, 1, 0, 0x24 }, L2(7),  1075000 },
+	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(7),  1075000 },
+	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1125000 },
 	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1125000 },
-	{ 1, {  1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1150000 },
-	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(19), 1150000 },
-	{ 1, {  1296000, HFPLL, 1, 0, 0x30 }, L2(19), 1175000 },
-	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(19), 1175000 },
-	{ 1, {  1404000, HFPLL, 1, 0, 0x34 }, L2(19), 1187500 },
-	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(19), 1187500 },
-	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(19), 1200000 },
+	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1150000 },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1150000 },
+	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1175000 },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1175000 },
+	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1187500 },
+	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(16), 1187500 },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(16), 1200000 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_8960_kraitv2_fast[] = {
 	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   850000 },
 	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   850000 },
-	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   875000 },
-	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(6),   875000 },
-	{ 1, {   540000, HFPLL, 2, 0, 0x28 }, L2(6),   900000 },
-	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(6),   900000 },
-	{ 1, {   648000, HFPLL, 1, 0, 0x18 }, L2(6),   925000 },
-	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(6),   925000 },
-	{ 1, {   756000, HFPLL, 1, 0, 0x1C }, L2(11),  975000 },
-	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(11),  975000 },
-	{ 1, {   864000, HFPLL, 1, 0, 0x20 }, L2(11), 1000000 },
-	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(11), 1000000 },
-	{ 1, {   972000, HFPLL, 1, 0, 0x24 }, L2(16), 1025000 },
-	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1025000 },
-	{ 1, {  1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1075000 },
+	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(7),   875000 },
+	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(7),   875000 },
+	{ 0, {   540000, HFPLL, 2, 0, 0x28 }, L2(7),   900000 },
+	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(7),   900000 },
+	{ 0, {   648000, HFPLL, 1, 0, 0x18 }, L2(7),   925000 },
+	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(7),   925000 },
+	{ 0, {   756000, HFPLL, 1, 0, 0x1C }, L2(7),   975000 },
+	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(7),   975000 },
+	{ 0, {   864000, HFPLL, 1, 0, 0x20 }, L2(7),  1000000 },
+	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(7),  1000000 },
+	{ 0, {   972000, HFPLL, 1, 0, 0x24 }, L2(7),  1025000 },
+	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(7),  1025000 },
+	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1075000 },
 	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1075000 },
-	{ 1, {  1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1100000 },
-	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(19), 1100000 },
-	{ 1, {  1296000, HFPLL, 1, 0, 0x30 }, L2(19), 1125000 },
-	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(19), 1125000 },
-	{ 1, {  1404000, HFPLL, 1, 0, 0x34 }, L2(19), 1137500 },
-	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(19), 1137500 },
-	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(19), 1150000 },
+	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1100000 },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1100000 },
+	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1125000 },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1125000 },
+	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1137500 },
+	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(16), 1137500 },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(16), 1150000 },
 	{ 0, { 0 } }
 };
 
@@ -1298,10 +1298,10 @@
 	case CPU_DYING:
 	case CPU_DYING_FROZEN:
 		/*
-		 * On Krait v1, the primary and secondary muxes must be set
-		 * to QSB before L2 power collapse and restored after.
+		 * On Krait v1 and 8064v1, the primary and secondary muxes must
+		 * be set to QSB before L2 power collapse and restored after.
 		 */
-		if (cpu_is_krait_v1()) {
+		if (cpu_is_krait_v1() || cpu_is_apq8064()) {
 			prev_sec_src[cpu] = get_sec_clk_src(&scalable[cpu]);
 			prev_pri_src[cpu] = get_pri_clk_src(&scalable[cpu]);
 			set_sec_clk_src(&scalable[cpu], SEC_SRC_SEL_QSB);
@@ -1324,7 +1324,7 @@
 		break;
 	case CPU_STARTING:
 	case CPU_STARTING_FROZEN:
-		if (cpu_is_krait_v1()) {
+		if (cpu_is_krait_v1() || cpu_is_apq8064()) {
 			set_sec_clk_src(&scalable[cpu], prev_sec_src[cpu]);
 			set_pri_clk_src(&scalable[cpu], prev_pri_src[cpu]);
 		}
diff --git a/arch/arm/mach-msm/acpuclock-9615.c b/arch/arm/mach-msm/acpuclock-9615.c
index 35eb52b..8882f41 100644
--- a/arch/arm/mach-msm/acpuclock-9615.c
+++ b/arch/arm/mach-msm/acpuclock-9615.c
@@ -323,6 +323,11 @@
 		if (clocks[i].name) {
 			clocks[i].clk = clk_get_sys("acpu", clocks[i].name);
 			BUG_ON(IS_ERR(clocks[i].clk));
+			/*
+			 * Prepare the PLLs because we enable/disable them
+			 * in atomic context during power collapse/restore.
+			 */
+			BUG_ON(clk_prepare(clocks[i].clk));
 		}
 	}
 
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index 73758d0..5ead88c 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -28,10 +28,10 @@
 
 #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
 /* prim = 1366 x 768 x 3(bpp) x 3(pages) */
-#define MSM_FB_PRIM_BUF_SIZE roundup(1366 * 768 * 3 * 3, 0x10000)
+#define MSM_FB_PRIM_BUF_SIZE roundup(1376 * 768 * 4 * 3, 0x10000)
 #else
 /* prim = 1366 x 768 x 3(bpp) x 2(pages) */
-#define MSM_FB_PRIM_BUF_SIZE roundup(1366 * 768 * 3 * 2, 0x10000)
+#define MSM_FB_PRIM_BUF_SIZE roundup(1376 * 768 * 4 * 2, 0x10000)
 #endif
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
@@ -58,22 +58,52 @@
 #define MSM_FB_OVERLAY1_WRITEBACK_SIZE (0)
 #endif  /* CONFIG_FB_MSM_OVERLAY1_WRITEBACK */
 
+
 static struct resource msm_fb_resources[] = {
 	{
 		.flags = IORESOURCE_DMA,
 	}
 };
 
-#define SIMULATOR_PANAL_NAME "mipi_video_simulator"
-#define SIMULATOR_PANAL_NAME_LEN 20
+#define PANEL_NAME_MAX_LEN 30
 #define LVDS_CHIMEI_PANEL_NAME "lvds_chimei_wxga"
-#define LVDS_CHIMEI_PANEL_NAME_LEN 16
+#define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME "mipi_video_toshiba_wsvga"
+#define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
+#define HDMI_PANEL_NAME "hdmi_msm"
+#define TVOUT_PANEL_NAME "tvout_msm"
 
 static int msm_fb_detect_panel(const char *name)
 {
-	if (!strncmp(name, LVDS_CHIMEI_PANEL_NAME,
-		LVDS_CHIMEI_PANEL_NAME_LEN))
+	if (machine_is_apq8064_liquid()) {
+		if (!strncmp(name, LVDS_CHIMEI_PANEL_NAME,
+			strnlen(LVDS_CHIMEI_PANEL_NAME,
+				PANEL_NAME_MAX_LEN)))
+			return 0;
+
+#if !defined(CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT) && \
+	!defined(CONFIG_FB_MSM_MIPI_PANEL_DETECT)
+		if (!strncmp(name, MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
+			strnlen(MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
+				PANEL_NAME_MAX_LEN)))
+			return 0;
+#endif
+	} else if (machine_is_apq8064_mtp()) {
+		if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
+			strnlen(MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
+				PANEL_NAME_MAX_LEN)))
+			return 0;
+	} else if (machine_is_apq8064_cdp()) {
+		if (!strncmp(name, LVDS_CHIMEI_PANEL_NAME,
+			strnlen(LVDS_CHIMEI_PANEL_NAME,
+				PANEL_NAME_MAX_LEN)))
+			return 0;
+	}
+
+	if (!strncmp(name, HDMI_PANEL_NAME,
+		strnlen(HDMI_PANEL_NAME,
+			PANEL_NAME_MAX_LEN)))
 		return 0;
+
 	return -ENODEV;
 }
 
@@ -105,15 +135,15 @@
 #define MDP_VSYNC_GPIO 0
 
 static int mdp_core_clk_rate_table[] = {
-	266667000,
-	266667000,
-	266667000,
-	266667000,
+	200000000,
+	200000000,
+	200000000,
+	200000000,
 };
 
 static struct msm_panel_common_pdata mdp_pdata = {
 	.gpio = MDP_VSYNC_GPIO,
-	.mdp_core_clk_rate = 266667000,
+	.mdp_core_clk_rate = 200000000,
 	.mdp_core_clk_table = mdp_core_clk_rate_table,
 	.num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
 	.mdp_rev = MDP_REV_44,
@@ -136,9 +166,337 @@
 #endif
 }
 
+static bool dsi_power_on;
+static int mipi_dsi_panel_power(int on)
+{
+	static struct regulator *reg_lvs7, *reg_l2, *reg_l11, *reg_ext_3p3v;
+	static int gpio36, gpio25, gpio26, mpp3;
+	int rc;
+
+	pr_debug("%s: on=%d\n", __func__, on);
+
+	if (!dsi_power_on) {
+		reg_lvs7 = regulator_get(&msm_mipi_dsi1_device.dev,
+				"dsi1_vddio");
+		if (IS_ERR_OR_NULL(reg_lvs7)) {
+			pr_err("could not get 8921_lvs7, rc = %ld\n",
+				PTR_ERR(reg_lvs7));
+			return -ENODEV;
+		}
+
+		reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
+				"dsi1_pll_vdda");
+		if (IS_ERR_OR_NULL(reg_l2)) {
+			pr_err("could not get 8921_l2, rc = %ld\n",
+				PTR_ERR(reg_l2));
+			return -ENODEV;
+		}
+
+		rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
+		if (rc) {
+			pr_err("set_voltage l2 failed, rc=%d\n", rc);
+			return -EINVAL;
+		}
+		reg_l11 = regulator_get(&msm_mipi_dsi1_device.dev,
+						"dsi1_avdd");
+		if (IS_ERR(reg_l11)) {
+				pr_err("could not get 8921_l11, rc = %ld\n",
+						PTR_ERR(reg_l11));
+				return -ENODEV;
+		}
+		rc = regulator_set_voltage(reg_l11, 3000000, 3000000);
+		if (rc) {
+				pr_err("set_voltage l11 failed, rc=%d\n", rc);
+				return -EINVAL;
+		}
+
+		if (machine_is_apq8064_liquid()) {
+			reg_ext_3p3v = regulator_get(&msm_mipi_dsi1_device.dev,
+				"dsi1_vccs_3p3v");
+			if (IS_ERR_OR_NULL(reg_ext_3p3v)) {
+				pr_err("could not get reg_ext_3p3v, rc = %ld\n",
+					PTR_ERR(reg_ext_3p3v));
+				reg_ext_3p3v = NULL;
+				return -ENODEV;
+			}
+			mpp3 = PM8921_MPP_PM_TO_SYS(3);
+			rc = gpio_request(mpp3, "backlight_en");
+			if (rc) {
+				pr_err("request mpp3 failed, rc=%d\n", rc);
+				return -ENODEV;
+			}
+		}
+
+		gpio25 = PM8921_GPIO_PM_TO_SYS(25);
+		rc = gpio_request(gpio25, "disp_rst_n");
+		if (rc) {
+			pr_err("request gpio 25 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+
+		gpio26 = PM8921_GPIO_PM_TO_SYS(26);
+		rc = gpio_request(gpio26, "pwm_backlight_ctrl");
+		if (rc) {
+			pr_err("request gpio 26 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+
+		gpio36 = PM8921_GPIO_PM_TO_SYS(36); /* lcd1_pwr_en_n */
+		rc = gpio_request(gpio36, "lcd1_pwr_en_n");
+		if (rc) {
+			pr_err("request gpio 36 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+
+		dsi_power_on = true;
+	}
+
+	if (on) {
+		rc = regulator_enable(reg_lvs7);
+		if (rc) {
+			pr_err("enable lvs7 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+
+		rc = regulator_set_optimum_mode(reg_l11, 110000);
+		if (rc < 0) {
+			pr_err("set_optimum_mode l11 failed, rc=%d\n", rc);
+			return -EINVAL;
+		}
+		rc = regulator_enable(reg_l11);
+		if (rc) {
+			pr_err("enable l11 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+
+		rc = regulator_set_optimum_mode(reg_l2, 100000);
+		if (rc < 0) {
+			pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
+			return -EINVAL;
+		}
+		rc = regulator_enable(reg_l2);
+		if (rc) {
+			pr_err("enable l2 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+
+		if (machine_is_apq8064_liquid()) {
+			rc = regulator_enable(reg_ext_3p3v);
+			if (rc) {
+				pr_err("enable reg_ext_3p3v failed, rc=%d\n",
+					rc);
+				return -ENODEV;
+			}
+			gpio_set_value_cansleep(mpp3, 1);
+		}
+
+		gpio_set_value_cansleep(gpio36, 0);
+		gpio_set_value_cansleep(gpio25, 1);
+	} else {
+		gpio_set_value_cansleep(gpio25, 0);
+		gpio_set_value_cansleep(gpio36, 1);
+
+		if (machine_is_apq8064_liquid()) {
+			gpio_set_value_cansleep(mpp3, 0);
+
+			rc = regulator_disable(reg_ext_3p3v);
+			if (rc) {
+				pr_err("disable reg_ext_3p3v failed, rc=%d\n",
+					rc);
+				return -ENODEV;
+			}
+		}
+
+		rc = regulator_disable(reg_lvs7);
+		if (rc) {
+			pr_err("disable reg_lvs7 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+		rc = regulator_disable(reg_l2);
+		if (rc) {
+			pr_err("disable reg_l2 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
+static struct mipi_dsi_platform_data mipi_dsi_pdata = {
+	.dsi_power_save = mipi_dsi_panel_power,
+};
+
+static bool lvds_power_on;
+static int lvds_panel_power(int on)
+{
+	static struct regulator *reg_lvs7, *reg_l2, *reg_ext_3p3v;
+	static int gpio36, gpio26, mpp3;
+	int rc;
+
+	pr_debug("%s: on=%d\n", __func__, on);
+
+	if (!lvds_power_on) {
+		reg_lvs7 = regulator_get(&msm_lvds_device.dev,
+				"lvds_vdda");
+		if (IS_ERR_OR_NULL(reg_lvs7)) {
+			pr_err("could not get 8921_lvs7, rc = %ld\n",
+				PTR_ERR(reg_lvs7));
+			return -ENODEV;
+		}
+
+		reg_l2 = regulator_get(&msm_lvds_device.dev,
+				"lvds_pll_vdda");
+		if (IS_ERR_OR_NULL(reg_l2)) {
+			pr_err("could not get 8921_l2, rc = %ld\n",
+				PTR_ERR(reg_l2));
+			return -ENODEV;
+		}
+
+		rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
+		if (rc) {
+			pr_err("set_voltage l2 failed, rc=%d\n", rc);
+			return -EINVAL;
+		}
+
+		reg_ext_3p3v = regulator_get(&msm_lvds_device.dev,
+			"lvds_vccs_3p3v");
+		if (IS_ERR_OR_NULL(reg_ext_3p3v)) {
+			pr_err("could not get reg_ext_3p3v, rc = %ld\n",
+			       PTR_ERR(reg_ext_3p3v));
+		    return -ENODEV;
+		}
+
+		gpio26 = PM8921_GPIO_PM_TO_SYS(26);
+		rc = gpio_request(gpio26, "pwm_backlight_ctrl");
+		if (rc) {
+			pr_err("request gpio 26 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+
+		gpio36 = PM8921_GPIO_PM_TO_SYS(36); /* lcd1_pwr_en_n */
+		rc = gpio_request(gpio36, "lcd1_pwr_en_n");
+		if (rc) {
+			pr_err("request gpio 36 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+
+		mpp3 = PM8921_MPP_PM_TO_SYS(3);
+		rc = gpio_request(mpp3, "backlight_en");
+		if (rc) {
+			pr_err("request mpp3 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+
+		lvds_power_on = true;
+	}
+
+	if (on) {
+		rc = regulator_enable(reg_lvs7);
+		if (rc) {
+			pr_err("enable lvs7 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+
+		rc = regulator_set_optimum_mode(reg_l2, 100000);
+		if (rc < 0) {
+			pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
+			return -EINVAL;
+		}
+		rc = regulator_enable(reg_l2);
+		if (rc) {
+			pr_err("enable l2 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+
+		rc = regulator_enable(reg_ext_3p3v);
+		if (rc) {
+			pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+
+		gpio_set_value_cansleep(gpio36, 0);
+		gpio_set_value_cansleep(mpp3, 1);
+	} else {
+		gpio_set_value_cansleep(mpp3, 0);
+		gpio_set_value_cansleep(gpio36, 1);
+
+		rc = regulator_disable(reg_lvs7);
+		if (rc) {
+			pr_err("disable reg_lvs7 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+		rc = regulator_disable(reg_l2);
+		if (rc) {
+			pr_err("disable reg_l2 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+		rc = regulator_disable(reg_ext_3p3v);
+		if (rc) {
+			pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
+static struct lcdc_platform_data lvds_pdata = {
+	.lcdc_power_save = lvds_panel_power,
+};
+
+#define LPM_CHANNEL 2
+static int lvds_chimei_gpio[] = {LPM_CHANNEL};
+
+static struct lvds_panel_platform_data lvds_chimei_pdata = {
+	.gpio = lvds_chimei_gpio,
+};
+
+static struct platform_device lvds_chimei_panel_device = {
+	.name = "lvds_chimei_wxga",
+	.id = 0,
+	.dev = {
+		.platform_data = &lvds_chimei_pdata,
+	}
+};
+
+static int dsi2lvds_gpio[2] = {
+	LPM_CHANNEL,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
+	0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
+};
+static struct msm_panel_common_pdata mipi_dsi2lvds_pdata = {
+	.gpio_num = dsi2lvds_gpio,
+};
+
+static struct platform_device mipi_dsi2lvds_bridge_device = {
+	.name = "mipi_tc358764",
+	.id = 0,
+	.dev.platform_data = &mipi_dsi2lvds_pdata,
+};
+
+static int toshiba_gpio[] = {LPM_CHANNEL};
+static struct mipi_dsi_panel_platform_data toshiba_pdata = {
+	.gpio = toshiba_gpio,
+};
+
+static struct platform_device mipi_dsi_toshiba_panel_device = {
+	.name = "mipi_toshiba",
+	.id = 0,
+	.dev = {
+			.platform_data = &toshiba_pdata,
+	}
+};
+
 void __init apq8064_init_fb(void)
 {
 	platform_device_register(&msm_fb_device);
+	platform_device_register(&lvds_chimei_panel_device);
+
+	if (machine_is_apq8064_liquid())
+		platform_device_register(&mipi_dsi2lvds_bridge_device);
+	if (machine_is_apq8064_mtp())
+		platform_device_register(&mipi_dsi_toshiba_panel_device);
+
 	msm_fb_register_device("mdp", &mdp_pdata);
-	msm_fb_register_device("lvds", NULL);
+	msm_fb_register_device("lvds", &lvds_pdata);
+	msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
 }
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index de80a3e..62b7f17 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -104,6 +104,30 @@
 	.dir = GPIOMUX_OUT_LOW,
 };
 
+static struct gpiomux_setting gsbi7_func1_cfg = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gsbi7_func2_cfg = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gsbi3_suspended_cfg = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_KEEPER,
+};
+
+static struct gpiomux_setting gsbi3_active_cfg = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
 #ifdef CONFIG_USB_EHCI_MSM_HSIC
 static struct gpiomux_setting hsic_act_cfg = {
 	.func = GPIOMUX_FUNC_1,
@@ -118,6 +142,66 @@
 	.dir = GPIOMUX_OUT_LOW,
 };
 
+static struct gpiomux_setting cyts_resout_sus_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting cyts_resout_act_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting cyts_sleep_sus_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting cyts_sleep_act_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting cyts_int_act_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting cyts_int_sus_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct msm_gpiomux_config cyts_gpio_configs[] __initdata = {
+	{	/* TS INTERRUPT */
+		.gpio = 6,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cyts_int_act_cfg,
+			[GPIOMUX_SUSPENDED] = &cyts_int_sus_cfg,
+		},
+	},
+	{	/* TS SLEEP */
+		.gpio = 33,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cyts_sleep_act_cfg,
+			[GPIOMUX_SUSPENDED] = &cyts_sleep_sus_cfg,
+		},
+	},
+	{	/* TS RESOUT */
+		.gpio = 7,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cyts_resout_act_cfg,
+			[GPIOMUX_SUSPENDED] = &cyts_resout_sus_cfg,
+		},
+	},
+};
+
 static struct msm_gpiomux_config apq8064_hsic_configs[] = {
 	{
 		.gpio = 88,               /*HSIC_STROBE */
@@ -136,8 +220,46 @@
 };
 #endif
 
+static struct gpiomux_setting mxt_reset_sus_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting mxt_reset_act_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting mxt_int_sus_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting mxt_int_act_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
 static struct msm_gpiomux_config apq8064_gsbi_configs[] __initdata = {
 	{
+		.gpio      = 8,			/* GSBI3 I2C QUP SDA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
+			[GPIOMUX_ACTIVE] = &gsbi3_active_cfg,
+		},
+	},
+	{
+		.gpio      = 9,			/* GSBI3 I2C QUP SCL */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
+			[GPIOMUX_ACTIVE] = &gsbi3_active_cfg,
+		},
+	},
+	{
 		.gpio      = 18,		/* GSBI1 UART TX */
 		.settings = {
 			[GPIOMUX_SUSPENDED] = &gsbi1_uart_config,
@@ -199,6 +321,18 @@
 			[GPIOMUX_SUSPENDED] = &gpio_spi_cs_config,
 		},
 	},
+	{
+		.gpio      = 82,	/* GSBI7 UART2 TX */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi7_func2_cfg,
+		},
+	},
+	{
+		.gpio      = 83,	/* GSBI7 UART2 RX */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi7_func1_cfg,
+		},
+	},
 };
 
 static struct msm_gpiomux_config apq8064_slimbus_config[] __initdata = {
@@ -328,6 +462,23 @@
 	}
 };
 
+static struct msm_gpiomux_config apq8064_mxt_configs[] __initdata = {
+	{	/* TS INTERRUPT */
+		.gpio = 6,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &mxt_int_act_cfg,
+			[GPIOMUX_SUSPENDED] = &mxt_int_sus_cfg,
+		},
+	},
+	{	/* TS RESET */
+		.gpio = 33,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &mxt_reset_act_cfg,
+			[GPIOMUX_SUSPENDED] = &mxt_reset_sus_cfg,
+		},
+	},
+};
+
 void __init apq8064_init_gpiomux(void)
 {
 	int rc;
@@ -362,8 +513,16 @@
 		msm_gpiomux_install(mdm_configs,
 			ARRAY_SIZE(mdm_configs));
 
+	if (machine_is_apq8064_mtp())
+		msm_gpiomux_install(cyts_gpio_configs,
+				ARRAY_SIZE(cyts_gpio_configs));
+
 #ifdef CONFIG_USB_EHCI_MSM_HSIC
 	msm_gpiomux_install(apq8064_hsic_configs,
 			ARRAY_SIZE(apq8064_hsic_configs));
 #endif
+
+	if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
+		msm_gpiomux_install(apq8064_mxt_configs,
+			ARRAY_SIZE(apq8064_mxt_configs));
 }
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index a8c5d48..0357c40 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -125,14 +125,14 @@
 static struct kgsl_device_platform_data kgsl_3d0_pdata = {
 	.pwrlevel = {
 		{
-			.gpu_freq = 400000000,
-			.bus_freq = 4,
-			.io_fraction = 0,
+			.gpu_freq = 192000000,
+			.bus_freq = 2,
+			.io_fraction = 100,
 		},
 		{
-			.gpu_freq = 320000000,
-			.bus_freq = 3,
-			.io_fraction = 33,
+			.gpu_freq = 192000000,
+			.bus_freq = 2,
+			.io_fraction = 100,
 		},
 		{
 			.gpu_freq = 1920000000,
@@ -140,8 +140,9 @@
 			.io_fraction = 100,
 		},
 		{
-			.gpu_freq = 27000000,
-			.bus_freq = 0,
+			.gpu_freq = 192000000,
+			.bus_freq = 2,
+			.io_fraction = 100,
 		},
 	},
 	.init_level = 0,
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 5204e48..02dfc5e 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -86,6 +86,13 @@
 			PM_GPIO_STRENGTH_##_strength, \
 			PM_GPIO_FUNC_NORMAL, 0, 0)
 
+#define PM8921_GPIO_OUTPUT_BUFCONF(_gpio, _val, _strength, _bufconf) \
+	PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT,\
+			PM_GPIO_OUT_BUF_##_bufconf, _val, \
+			PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+			PM_GPIO_STRENGTH_##_strength, \
+			PM_GPIO_FUNC_NORMAL, 0, 0)
+
 #define PM8921_GPIO_INPUT(_gpio, _pull) \
 	PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, PM_GPIO_OUT_BUF_CMOS, 0, \
 			_pull, PM_GPIO_VIN_S4, \
@@ -106,12 +113,18 @@
 
 /* Initial PM8921 GPIO configurations */
 static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
+	PM8921_GPIO_OUTPUT(23, 0, HIGH),	/* touchscreen power FET */
+	PM8921_GPIO_OUTPUT_BUFCONF(25, 0, LOW, CMOS), /* DISP_RESET_N */
+	PM8921_GPIO_OUTPUT_FUNC(26, 0, PM_GPIO_FUNC_2), /* Bl: Off, PWM mode */
+	PM8921_GPIO_OUTPUT_BUFCONF(36, 1, LOW, OPEN_DRAIN),
 };
 
 /* Initial PM8XXX MPP configurations */
 static struct pm8xxx_mpp_init pm8xxx_mpps[] __initdata = {
+	PM8921_MPP_INIT(3, D_OUTPUT, PM8921_MPP_DIG_LEVEL_VPH, DOUT_CTRL_LOW),
 	/* External 5V regulator enable; shared by HDMI and USB_OTG switches. */
-	PM8921_MPP_INIT(7, D_INPUT, PM8921_MPP_DIG_LEVEL_VPH, DIN_TO_INT),
+	PM8921_MPP_INIT(7, D_OUTPUT, PM8921_MPP_DIG_LEVEL_VPH, DOUT_CTRL_LOW),
+	PM8921_MPP_INIT(8, D_OUTPUT, PM8921_MPP_DIG_LEVEL_S4, DOUT_CTRL_LOW),
 };
 
 void __init apq8064_pm8xxx_gpio_mpp_init(void)
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index f3eebce..4e29feb 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -29,6 +29,8 @@
 	REGULATOR_SUPPLY("8921_l2",		NULL),
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-001a"),
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-006c"),
+	REGULATOR_SUPPLY("lvds_pll_vdda",	"lvds.0"),
+	REGULATOR_SUPPLY("dsi1_pll_vdda",	"mipi_dsi.1"),
 };
 VREG_CONSUMERS(L3) = {
 	REGULATOR_SUPPLY("8921_l3",		NULL),
@@ -62,6 +64,7 @@
 };
 VREG_CONSUMERS(L9) = {
 	REGULATOR_SUPPLY("8921_l9",		NULL),
+	REGULATOR_SUPPLY("vdd",			"3-0024"),
 };
 VREG_CONSUMERS(L10) = {
 	REGULATOR_SUPPLY("8921_l10",		NULL),
@@ -69,6 +72,7 @@
 };
 VREG_CONSUMERS(L11) = {
 	REGULATOR_SUPPLY("8921_l11",		NULL),
+	REGULATOR_SUPPLY("dsi1_avdd",		"mipi_dsi.1"),
 };
 VREG_CONSUMERS(L12) = {
 	REGULATOR_SUPPLY("cam_vdig",		"4-001a"),
@@ -97,6 +101,9 @@
 };
 VREG_CONSUMERS(L23) = {
 	REGULATOR_SUPPLY("8921_l23",		NULL),
+	REGULATOR_SUPPLY("pll_vdd",		"pil_qdsp6v4.1"),
+	REGULATOR_SUPPLY("pll_vdd",		"pil_qdsp6v4.2"),
+
 };
 VREG_CONSUMERS(L24) = {
 	REGULATOR_SUPPLY("8921_l24",		NULL),
@@ -106,6 +113,8 @@
 	REGULATOR_SUPPLY("8921_l25",		NULL),
 	REGULATOR_SUPPLY("VDDD_CDC_D",		"tabla-slim"),
 	REGULATOR_SUPPLY("CDC_VDDA_A_1P2V",	"tabla-slim"),
+	REGULATOR_SUPPLY("VDDD_CDC_D",		"tabla2x-slim"),
+	REGULATOR_SUPPLY("CDC_VDDA_A_1P2V",	"tabla2x-slim"),
 };
 VREG_CONSUMERS(L26) = {
 	REGULATOR_SUPPLY("8921_l26",		NULL),
@@ -113,9 +122,11 @@
 };
 VREG_CONSUMERS(L27) = {
 	REGULATOR_SUPPLY("8921_l27",		NULL),
+	REGULATOR_SUPPLY("core_vdd",		"pil_qdsp6v4.2"),
 };
 VREG_CONSUMERS(L28) = {
 	REGULATOR_SUPPLY("8921_l28",		NULL),
+	REGULATOR_SUPPLY("core_vdd",		"pil_qdsp6v4.1"),
 };
 VREG_CONSUMERS(S1) = {
 	REGULATOR_SUPPLY("8921_s1",		NULL),
@@ -139,7 +150,13 @@
 	REGULATOR_SUPPLY("CDC_VDD_CP",		"tabla-slim"),
 	REGULATOR_SUPPLY("CDC_VDDA_TX",		"tabla-slim"),
 	REGULATOR_SUPPLY("CDC_VDDA_RX",		"tabla-slim"),
+	REGULATOR_SUPPLY("VDDIO_CDC",		"tabla2x-slim"),
+	REGULATOR_SUPPLY("CDC_VDD_CP",		"tabla2x-slim"),
+	REGULATOR_SUPPLY("CDC_VDDA_TX",		"tabla2x-slim"),
+	REGULATOR_SUPPLY("CDC_VDDA_RX",		"tabla2x-slim"),
 	REGULATOR_SUPPLY("riva_vddpx",		"wcnss_wlan.0"),
+	REGULATOR_SUPPLY("vcc_i2c",		"3-005b"),
+	REGULATOR_SUPPLY("vcc_i2c",		"3-0024"),
 };
 VREG_CONSUMERS(S5) = {
 	REGULATOR_SUPPLY("8921_s5",		NULL),
@@ -177,6 +194,8 @@
 VREG_CONSUMERS(LVS7) = {
 	REGULATOR_SUPPLY("8921_lvs7",		NULL),
 	REGULATOR_SUPPLY("pll_vdd",		"pil_riva"),
+	REGULATOR_SUPPLY("lvds_vdda",		"lvds.0"),
+	REGULATOR_SUPPLY("dsi1_vddio",		"mipi_dsi.1"),
 };
 VREG_CONSUMERS(USB_OTG) = {
 	REGULATOR_SUPPLY("8921_usb_otg",	NULL),
@@ -199,10 +218,19 @@
 VREG_CONSUMERS(EXT_5V) = {
 	REGULATOR_SUPPLY("ext_5v",		NULL),
 };
+VREG_CONSUMERS(EXT_MPP8) = {
+	REGULATOR_SUPPLY("ext_mpp8",		NULL),
+};
 VREG_CONSUMERS(EXT_3P3V) = {
 	REGULATOR_SUPPLY("ext_3p3v",		NULL),
 	REGULATOR_SUPPLY("vdd_io",		"spi0.2"),
 	REGULATOR_SUPPLY("mhl_ext_3p3v",	"msm_otg"),
+	REGULATOR_SUPPLY("lvds_vccs_3p3v",      "lvds.0"),
+	REGULATOR_SUPPLY("dsi1_vccs_3p3v",      "mipi_dsi.1"),
+};
+VREG_CONSUMERS(EXT_TS_SW) = {
+	REGULATOR_SUPPLY("ext_ts_sw",		NULL),
+	REGULATOR_SUPPLY("vdd_ana",		"3-005b"),
 };
 
 #define PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
@@ -328,6 +356,97 @@
 		.consumer_supplies	= vreg_consumers_##_id, \
 	}
 
+#define RPM_INIT(_id, _min_uV, _max_uV, _modes, _ops, _apply_uV, _default_uV, \
+		 _peak_uA, _avg_uA, _pull_down, _pin_ctrl, _freq, _pin_fn, \
+		 _force_mode, _power_mode, _state, _sleep_selectable, \
+		 _always_on, _supply_regulator, _system_uA) \
+	{ \
+		.init_data = { \
+			.constraints = { \
+				.valid_modes_mask	= _modes, \
+				.valid_ops_mask		= _ops, \
+				.min_uV			= _min_uV, \
+				.max_uV			= _max_uV, \
+				.input_uV		= _min_uV, \
+				.apply_uV		= _apply_uV, \
+				.always_on		= _always_on, \
+			}, \
+			.num_consumer_supplies	= \
+					ARRAY_SIZE(vreg_consumers_##_id), \
+			.consumer_supplies	= vreg_consumers_##_id, \
+			.supply_regulator	= _supply_regulator, \
+		}, \
+		.id			= RPM_VREG_ID_PM8921_##_id, \
+		.default_uV		= _default_uV, \
+		.peak_uA		= _peak_uA, \
+		.avg_uA			= _avg_uA, \
+		.pull_down_enable	= _pull_down, \
+		.pin_ctrl		= _pin_ctrl, \
+		.freq			= RPM_VREG_FREQ_##_freq, \
+		.pin_fn			= _pin_fn, \
+		.force_mode		= _force_mode, \
+		.power_mode		= _power_mode, \
+		.state			= _state, \
+		.sleep_selectable	= _sleep_selectable, \
+		.system_uA		= _system_uA, \
+	}
+
+#define RPM_LDO(_id, _always_on, _pd, _sleep_selectable, _min_uV, _max_uV, \
+		_supply_regulator, _system_uA, _init_peak_uA) \
+	RPM_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_NORMAL \
+		 | REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE \
+		 | REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE \
+		 | REGULATOR_CHANGE_DRMS, 0, _max_uV, _init_peak_uA, 0, _pd, \
+		 RPM_VREG_PIN_CTRL_NONE, NONE, RPM_VREG_PIN_FN_8960_NONE, \
+		 RPM_VREG_FORCE_MODE_8960_NONE, RPM_VREG_POWER_MODE_8960_PWM, \
+		 RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
+		 _supply_regulator, _system_uA)
+
+#define RPM_SMPS(_id, _always_on, _pd, _sleep_selectable, _min_uV, _max_uV, \
+		 _supply_regulator, _system_uA, _freq) \
+	RPM_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_NORMAL \
+		 | REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE \
+		 | REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE \
+		 | REGULATOR_CHANGE_DRMS, 0, _max_uV, _system_uA, 0, _pd, \
+		 RPM_VREG_PIN_CTRL_NONE, _freq, RPM_VREG_PIN_FN_8960_NONE, \
+		 RPM_VREG_FORCE_MODE_8960_NONE, RPM_VREG_POWER_MODE_8960_PWM, \
+		 RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
+		 _supply_regulator, _system_uA)
+
+#define RPM_VS(_id, _always_on, _pd, _sleep_selectable, _supply_regulator) \
+	RPM_INIT(_id, 0, 0, 0, REGULATOR_CHANGE_STATUS, 0, 0, 1000, 1000, _pd, \
+		 RPM_VREG_PIN_CTRL_NONE, NONE, RPM_VREG_PIN_FN_8960_NONE, \
+		 RPM_VREG_FORCE_MODE_8960_NONE, RPM_VREG_POWER_MODE_8960_PWM, \
+		 RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
+		 _supply_regulator, 0)
+
+#define RPM_NCP(_id, _always_on, _sleep_selectable, _min_uV, _max_uV, \
+		_supply_regulator, _freq) \
+	RPM_INIT(_id, _min_uV, _max_uV, 0, REGULATOR_CHANGE_VOLTAGE \
+		 | REGULATOR_CHANGE_STATUS, 0, _max_uV, 1000, 1000, 0, \
+		 RPM_VREG_PIN_CTRL_NONE, _freq, RPM_VREG_PIN_FN_8960_NONE, \
+		 RPM_VREG_FORCE_MODE_8960_NONE, RPM_VREG_POWER_MODE_8960_PWM, \
+		 RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
+		 _supply_regulator, 0)
+
+/* Pin control initialization */
+#define RPM_PC_INIT(_id, _always_on, _pin_fn, _pin_ctrl, _supply_regulator) \
+	{ \
+		.init_data = { \
+			.constraints = { \
+				.valid_ops_mask	= REGULATOR_CHANGE_STATUS, \
+				.always_on	= _always_on, \
+			}, \
+			.num_consumer_supplies	= \
+					ARRAY_SIZE(vreg_consumers_##_id##_PC), \
+			.consumer_supplies	= vreg_consumers_##_id##_PC, \
+			.supply_regulator	= _supply_regulator, \
+		}, \
+		.id	  = RPM_VREG_ID_PM8921_##_id##_PC, \
+		.pin_fn	  = RPM_VREG_PIN_FN_8960_##_pin_fn, \
+		.pin_ctrl = _pin_ctrl, \
+	}
+
 /* GPIO regulator constraints */
 struct gpio_regulator_platform_data
 apq8064_gpio_regulator_pdata[] __devinitdata = {
@@ -335,6 +454,10 @@
 	GPIO_VREG(EXT_5V, "ext_5v", "ext_5v_en", PM8921_MPP_PM_TO_SYS(7), NULL),
 	GPIO_VREG(EXT_3P3V, "ext_3p3v", "ext_3p3v_en",
 		  APQ8064_EXT_3P3V_REG_EN_GPIO, NULL),
+	GPIO_VREG(EXT_TS_SW, "ext_ts_sw", "ext_ts_sw_en",
+		  PM8921_GPIO_PM_TO_SYS(23), "ext_3p3v"),
+	GPIO_VREG(EXT_MPP8, "ext_mpp8", "ext_mpp8_en",
+			PM8921_MPP_PM_TO_SYS(8), NULL),
 };
 
 /* SAW regulator constraints */
@@ -354,69 +477,71 @@
 struct pm8xxx_regulator_platform_data
 msm8064_pm8921_regulator_pdata[] __devinitdata = {
 	/*
-	 *	   ID   name always_on pd min_uV   max_uV   en_t supply
+	 *		ID   name always_on pd min_uV   max_uV   en_t supply
 	 *	system_uA reg_ID
 	 */
-	PM8XXX_SMPS(S1, "8921_s1",  1, 1, 1225000, 1225000, 500, NULL, 100000,
-		1),
-	PM8XXX_SMPS(S2, "8921_s2",  0, 1, 1300000, 1300000, 500, NULL, 0, 2),
-	PM8XXX_SMPS(S3, "8921_s3",  1, 1, 1150000, 1150000, 500, NULL, 100000,
-		3),
-	PM8XXX_SMPS(S4, "8921_s4",  1, 1, 1800000, 1800000, 500, NULL, 100000,
-		4),
-	PM8XXX_SMPS(S7, "8921_s7",  0, 1, 1300000, 1300000, 500, NULL, 100000,
-		5),
-
-	PM8XXX_LDO(L1,  "8921_l1",  1, 1, 1100000, 1100000, 200, "8921_s4", 0,
-		6),
-	PM8XXX_LDO(L2,  "8921_l2",  0, 1, 1200000, 1200000, 200, "8921_s4", 0,
-		7),
-	PM8XXX_LDO(L3,  "8921_l3",  0, 1, 3075000, 3075000, 200, NULL, 0, 8),
-	PM8XXX_LDO(L4,  "8921_l4",  1, 1, 1800000, 1800000, 200, NULL, 10000,
-		9),
-	PM8XXX_LDO(L5,  "8921_l5",  0, 1, 2950000, 2950000, 200, NULL, 0, 10),
-	PM8XXX_LDO(L6,  "8921_l6",  0, 1, 2950000, 2950000, 200, NULL, 0, 11),
-	PM8XXX_LDO(L7,  "8921_l7",  0, 1, 1850000, 2950000, 200, NULL, 0, 12),
-	PM8XXX_LDO(L8,  "8921_l8",  0, 1, 2800000, 2800000, 200, NULL, 0, 13),
-	PM8XXX_LDO(L9,  "8921_l9",  0, 1, 2850000, 2850000, 200, NULL, 0, 14),
-	PM8XXX_LDO(L10, "8921_l10", 0, 1, 2900000, 2900000, 200, NULL, 0, 15),
-	PM8XXX_LDO(L11, "8921_l11", 0, 1, 3000000, 3000000, 200, NULL, 0, 16),
-	PM8XXX_LDO(L12, "8921_l12", 0, 1, 1200000, 1200000, 200, "8921_s4", 0,
-		17),
-	PM8XXX_LDO(L14, "8921_l14", 0, 1, 1800000, 1800000, 200, NULL, 0, 18),
-	PM8XXX_LDO(L15, "8921_l15", 0, 1, 1800000, 2950000, 200, NULL, 0, 19),
-	PM8XXX_LDO(L16, "8921_l16", 0, 1, 2800000, 2800000, 200, NULL, 0, 20),
-	PM8XXX_LDO(L17, "8921_l17", 0, 1, 2000000, 2000000, 200, NULL, 0, 21),
-	PM8XXX_LDO(L18, "8921_l18", 0, 1, 1300000, 1800000, 200, "8921_s4", 0,
-		22),
-	PM8XXX_LDO(L22, "8921_l22", 0, 1, 2600000, 2600000, 200, NULL, 0, 23),
-	PM8XXX_LDO(L23, "8921_l23", 0, 1, 1800000, 1800000, 200, NULL, 0, 24),
-	PM8XXX_NLDO1200(L24, "8921_l24", 1, 1, 1150000, 1150000, 200, "8921_s1",
-		10000, 25),
-	PM8XXX_NLDO1200(L25, "8921_l25", 1, 1, 1225000, 1225000, 200, "8921_s1",
-		10000, 26),
 	PM8XXX_NLDO1200(L26, "8921_l26", 0, 1, 1050000, 1050000, 200, "8921_s7",
-		0, 27),
-	PM8XXX_NLDO1200(L27, "8921_l27", 0, 1, 1100000, 1100000, 200, "8921_s7",
-		0, 28),
-	PM8XXX_NLDO1200(L28, "8921_l28", 0, 1, 1050000, 1050000, 200, "8921_s7",
-		0, 29),
+		0, 1),
 
-	/*        ID       name  always_on pd              en_t supply reg_ID */
-	PM8XXX_VS(LVS1,	   "8921_lvs1", 0, 1,                 0, "8921_s4", 30),
-	PM8XXX_VS300(LVS2, "8921_lvs2", 0, 1,                 0, "8921_s1", 31),
-	PM8XXX_VS(LVS3,    "8921_lvs3", 0, 1,                 0, "8921_s4", 32),
-	PM8XXX_VS(LVS4,    "8921_lvs4", 0, 1,                 0, "8921_s4", 33),
-	PM8XXX_VS(LVS5,    "8921_lvs5", 0, 1,                 0, "8921_s4", 34),
-	PM8XXX_VS(LVS6,    "8921_lvs6", 0, 1,                 0, "8921_s4", 35),
-	PM8XXX_VS(LVS7,    "8921_lvs7", 1, 1,                 0, "8921_s4", 36),
+	/*           ID        name     always_on pd       en_t supply reg_ID */
+	PM8XXX_VS300(USB_OTG,  "8921_usb_otg",  0, 0,         0, "ext_5v", 2),
+	PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1,         0, "ext_5v", 3),
+};
 
-	PM8XXX_VS300(USB_OTG,  "8921_usb_otg",  0, 0,         0, "ext_5v", 37),
-	PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1,         0, "ext_5v", 38),
+static struct rpm_regulator_init_data
+apq8064_rpm_regulator_init_data[] __devinitdata = {
+	/*	ID a_on pd ss min_uV   max_uV   supply    sys_uA  freq */
+	RPM_SMPS(S1, 1, 1, 0, 1225000, 1225000, NULL,     100000, 3p20),
+	RPM_SMPS(S2, 0, 1, 0, 1300000, 1300000, NULL,          0, 1p60),
+	RPM_SMPS(S3, 0, 1, 1,  500000, 1150000, NULL,     100000, 4p80),
+	RPM_SMPS(S4, 1, 1, 0, 1800000, 1800000, NULL,     100000, 1p60),
+	RPM_SMPS(S7, 0, 1, 0, 1300000, 1300000, NULL,     100000, 3p20),
 
-	/*         ID   name  always_on   min_uV   max_uV  en_t supply reg_ID */
-	PM8XXX_NCP(NCP,	"8921_ncp", 0,    1800000, 1800000, 200, "8921_l6", 39),
+	/*	ID a_on pd ss min_uV   max_uV   supply    sys_uA init_ip */
+	RPM_LDO(L1,  1, 1, 0, 1100000, 1100000, "8921_s4",     0, 10000),
+	RPM_LDO(L2,  0, 1, 0, 1200000, 1200000, "8921_s4",     0,     0),
+	RPM_LDO(L3,  0, 1, 0, 3075000, 3075000, NULL,          0,     0),
+	RPM_LDO(L4,  1, 1, 0, 1800000, 1800000, NULL,      10000, 10000),
+	RPM_LDO(L5,  0, 1, 0, 2950000, 2950000, NULL,          0,     0),
+	RPM_LDO(L6,  0, 1, 0, 2950000, 2950000, NULL,          0,     0),
+	RPM_LDO(L7,  0, 1, 0, 1850000, 2950000, NULL,          0,     0),
+	RPM_LDO(L8,  0, 1, 0, 2800000, 2800000, NULL,          0,     0),
+	RPM_LDO(L9,  0, 1, 0, 2850000, 2850000, NULL,          0,     0),
+	RPM_LDO(L10, 0, 1, 0, 2900000, 2900000, NULL,          0,     0),
+	RPM_LDO(L11, 0, 1, 0, 3000000, 3000000, NULL,          0,     0),
+	RPM_LDO(L12, 0, 1, 0, 1200000, 1200000, "8921_s4",     0,     0),
+	RPM_LDO(L14, 0, 1, 0, 1800000, 1800000, NULL,          0,     0),
+	RPM_LDO(L15, 0, 1, 0, 1800000, 2950000, NULL,          0,     0),
+	RPM_LDO(L16, 0, 1, 0, 2800000, 2800000, NULL,          0,     0),
+	RPM_LDO(L17, 0, 1, 0, 2000000, 2000000, NULL,          0,     0),
+	RPM_LDO(L18, 0, 1, 0, 1300000, 1800000, "8921_s4",     0,     0),
+	RPM_LDO(L22, 0, 1, 0, 2600000, 2600000, NULL,          0,     0),
+	RPM_LDO(L23, 0, 1, 0, 1800000, 1800000, NULL,          0,     0),
+	RPM_LDO(L24, 0, 1, 1,  750000, 1150000, "8921_s1", 10000, 10000),
+	RPM_LDO(L25, 1, 1, 0, 1225000, 1225000, "8921_s1", 10000, 10000),
+	RPM_LDO(L27, 0, 1, 0, 1100000, 1100000, "8921_s7",     0,     0),
+	RPM_LDO(L28, 0, 1, 0, 1050000, 1050000, "8921_s7",     0,     0),
+
+	/*     ID  a_on pd ss                   supply */
+	RPM_VS(LVS1, 0, 1, 0,                   "8921_s4"),
+	RPM_VS(LVS2, 0, 1, 0,                   "8921_s1"),
+	RPM_VS(LVS3, 0, 1, 0,                   "8921_s4"),
+	RPM_VS(LVS4, 0, 1, 0,                   "8921_s4"),
+	RPM_VS(LVS5, 0, 1, 0,                   "8921_s4"),
+	RPM_VS(LVS6, 0, 1, 0,                   "8921_s4"),
+	RPM_VS(LVS7, 1, 1, 1,                   "8921_s4"),
+
+	/*	ID a_on    ss min_uV   max_uV   supply     freq */
+	RPM_NCP(NCP, 0,    0, 1800000, 1800000, "8921_l6", 1p60),
 };
 
 int msm8064_pm8921_regulator_pdata_len __devinitdata =
 	ARRAY_SIZE(msm8064_pm8921_regulator_pdata);
+
+struct rpm_regulator_platform_data apq8064_rpm_regulator_pdata __devinitdata = {
+	.init_data		= apq8064_rpm_regulator_init_data,
+	.num_regulators		= ARRAY_SIZE(apq8064_rpm_regulator_init_data),
+	.version		= RPM_VREG_VERSION_8960,
+	.vreg_id_vdd_mem	= RPM_VREG_ID_PM8921_L24,
+	.vreg_id_vdd_dig	= RPM_VREG_ID_PM8921_S3,
+};
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index 8a3b958..0d187a9 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -230,6 +230,10 @@
 	.sup_clk_cnt	= ARRAY_SIZE(sdc3_sup_clk_rates),
 	.pin_data	= &mmc_slot_pin_data[SDCC3],
 	.vreg_data	= &mmc_slot_vreg_data[SDCC3],
+	.status_gpio	= 26,
+	.status_irq	= MSM_GPIO_TO_INT(26),
+	.irq_flags	= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+	.is_status_gpio_active_low = 1,
 };
 static struct mmc_platform_data *apq8064_sdc3_pdata = &sdc3_data;
 #else
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index febc55d..2afd3cc 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -24,6 +24,8 @@
 #include <linux/platform_data/qcom_crypto_device.h>
 #include <linux/ion.h>
 #include <linux/memory.h>
+#include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/cyttsp.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
@@ -525,6 +527,207 @@
 	},
 };
 
+/* configuration data for mxt1386e using V2.1 firmware */
+static const u8 mxt1386e_config_data_v2_1[] = {
+	/* T6 Object */
+	0, 0, 0, 0, 0, 0,
+	/* T38 Object */
+	14, 0, 0, 24, 1, 12, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0,
+	/* T7 Object */
+	100, 16, 50,
+	/* T8 Object */
+	25, 0, 20, 20, 0, 0, 20, 50, 0, 0,
+	/* T9 Object */
+	131, 0, 0, 26, 42, 0, 32, 80, 2, 5,
+	0, 5, 5, 0, 10, 30, 10, 10, 255, 2,
+	85, 5, 10, 10, 10, 10, 135, 55, 70, 40,
+	10, 5, 0, 0, 0,
+	/* T18 Object */
+	0, 0,
+	/* T24 Object */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0,
+	/* T25 Object */
+	3, 0, 60, 115, 156, 99,
+	/* T27 Object */
+	0, 0, 0, 0, 0, 0, 0,
+	/* T40 Object */
+	0, 0, 0, 0, 0,
+	/* T42 Object */
+	2, 0, 255, 0, 255, 0, 0, 0, 0, 0,
+	/* T43 Object */
+	0, 0, 0, 0, 0, 0, 0, 64, 0, 8,
+	16,
+	/* T46 Object */
+	64, 0, 20, 20, 0, 0, 0, 0, 0,
+	/* T47 Object */
+	0, 0, 0, 0, 0, 0, 3, 64, 66, 0,
+	/* T48 Object */
+	31, 64, 64, 0, 0, 0, 0, 0, 0, 0,
+	48, 40, 0, 10, 10, 0, 0, 100, 10, 80,
+	0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+	52, 0, 12, 0, 17, 0, 1, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0,
+	/* T56 Object */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	2, 99, 33, 0, 149, 24, 193, 255, 255, 255,
+	255,
+};
+
+#define MXT_TS_GPIO_IRQ			6
+#define MXT_TS_PWR_EN_GPIO		PM8921_GPIO_PM_TO_SYS(23)
+#define MXT_TS_RESET_GPIO		33
+
+static struct mxt_config_info mxt_config_array[] = {
+	{
+		.config		= mxt1386e_config_data_v2_1,
+		.config_length	= ARRAY_SIZE(mxt1386e_config_data_v2_1),
+		.family_id	= 0xA0,
+		.variant_id	= 0x7,
+		.version	= 0x21,
+		.build		= 0xAA,
+	},
+};
+
+static struct mxt_platform_data mxt_platform_data = {
+	.config_array		= mxt_config_array,
+	.config_array_size	= ARRAY_SIZE(mxt_config_array),
+	.x_size			= 1365,
+	.y_size			= 767,
+	.irqflags		= IRQF_TRIGGER_FALLING,
+	.i2c_pull_up		= true,
+	.reset_gpio		= MXT_TS_RESET_GPIO,
+	.irq_gpio		= MXT_TS_GPIO_IRQ,
+};
+
+static struct i2c_board_info mxt_device_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("atmel_mxt_ts", 0x5b),
+		.platform_data = &mxt_platform_data,
+		.irq = MSM_GPIO_TO_INT(MXT_TS_GPIO_IRQ),
+	},
+};
+#define CYTTSP_TS_GPIO_IRQ		6
+#define CYTTSP_TS_GPIO_RESOUT		7
+#define CYTTSP_TS_GPIO_SLEEP		33
+
+static ssize_t tma340_vkeys_show(struct kobject *kobj,
+			struct kobj_attribute *attr, char *buf)
+{
+	return snprintf(buf, 200,
+	__stringify(EV_KEY) ":" __stringify(KEY_BACK) ":73:1120:97:97"
+	":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":230:1120:97:97"
+	":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":389:1120:97:97"
+	":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":544:1120:97:97"
+	"\n");
+}
+
+static struct kobj_attribute tma340_vkeys_attr = {
+	.attr = {
+		.mode = S_IRUGO,
+	},
+	.show = &tma340_vkeys_show,
+};
+
+static struct attribute *tma340_properties_attrs[] = {
+	&tma340_vkeys_attr.attr,
+	NULL
+};
+
+static struct attribute_group tma340_properties_attr_group = {
+	.attrs = tma340_properties_attrs,
+};
+
+static int cyttsp_platform_init(struct i2c_client *client)
+{
+	int rc = 0;
+	static struct kobject *tma340_properties_kobj;
+
+	tma340_vkeys_attr.attr.name = "virtualkeys.cyttsp-i2c";
+	tma340_properties_kobj = kobject_create_and_add("board_properties",
+								NULL);
+	if (tma340_properties_kobj)
+		rc = sysfs_create_group(tma340_properties_kobj,
+					&tma340_properties_attr_group);
+	if (!tma340_properties_kobj || rc)
+		pr_err("%s: failed to create board_properties\n",
+				__func__);
+
+	return 0;
+}
+
+static struct cyttsp_regulator cyttsp_regulator_data[] = {
+	{
+		.name = "vdd",
+		.min_uV = CY_TMA300_VTG_MIN_UV,
+		.max_uV = CY_TMA300_VTG_MAX_UV,
+		.hpm_load_uA = CY_TMA300_CURR_24HZ_UA,
+		.lpm_load_uA = CY_TMA300_CURR_24HZ_UA,
+	},
+	{
+		.name = "vcc_i2c",
+		.min_uV = CY_I2C_VTG_MIN_UV,
+		.max_uV = CY_I2C_VTG_MAX_UV,
+		.hpm_load_uA = CY_I2C_CURR_UA,
+		.lpm_load_uA = CY_I2C_CURR_UA,
+	},
+};
+
+static struct cyttsp_platform_data cyttsp_pdata = {
+	.panel_maxx = 634,
+	.panel_maxy = 1166,
+	.disp_maxx = 599,
+	.disp_maxy = 1023,
+	.disp_minx = 0,
+	.disp_miny = 0,
+	.flags = 0x01,
+	.gen = CY_GEN3,
+	.use_st = CY_USE_ST,
+	.use_mt = CY_USE_MT,
+	.use_hndshk = CY_SEND_HNDSHK,
+	.use_trk_id = CY_USE_TRACKING_ID,
+	.use_sleep = CY_USE_DEEP_SLEEP_SEL,
+	.use_gestures = CY_USE_GESTURES,
+	.fw_fname = "cyttsp_8064_mtp.hex",
+	/* change act_intrvl to customize the Active power state
+	 * scanning/processing refresh interval for Operating mode
+	 */
+	.act_intrvl = CY_ACT_INTRVL_DFLT,
+	/* change tch_tmout to customize the touch timeout for the
+	 * Active power state for Operating mode
+	 */
+	.tch_tmout = CY_TCH_TMOUT_DFLT,
+	/* change lp_intrvl to customize the Low Power power state
+	 * scanning/processing refresh interval for Operating mode
+	 */
+	.lp_intrvl = CY_LP_INTRVL_DFLT,
+	.sleep_gpio = CYTTSP_TS_GPIO_SLEEP,
+	.resout_gpio = CYTTSP_TS_GPIO_RESOUT,
+	.irq_gpio = CYTTSP_TS_GPIO_IRQ,
+	.regulator_info = cyttsp_regulator_data,
+	.num_regulators = ARRAY_SIZE(cyttsp_regulator_data),
+	.init = cyttsp_platform_init,
+	.correct_fw_ver = 17,
+};
+
+static struct i2c_board_info cyttsp_info[] __initdata = {
+	{
+		I2C_BOARD_INFO(CY_I2C_NAME, 0x24),
+		.platform_data = &cyttsp_pdata,
+		.irq = MSM_GPIO_TO_INT(CYTTSP_TS_GPIO_IRQ),
+	},
+};
+
 #if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
 		defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \
 		defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
@@ -664,12 +867,6 @@
 	msm_mpm_irq_extn_init(data);
 	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
 						(void *)MSM_QGIC_CPU_BASE);
-
-	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-	writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
-	writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-	mb();
 }
 
 static struct platform_device msm8064_device_saw_regulator_core0 = {
@@ -1091,6 +1288,15 @@
 	},
 };
 
+static struct platform_device apq8064_device_ext_mpp8_vreg __devinitdata = {
+	.name	= GPIO_REGULATOR_DEV_NAME,
+	.id	= PM8921_MPP_PM_TO_SYS(8),
+	.dev	= {
+		.platform_data
+			= &apq8064_gpio_regulator_pdata[GPIO_VREG_ID_EXT_MPP8],
+	},
+};
+
 static struct platform_device apq8064_device_ext_3p3v_vreg __devinitdata = {
 	.name	= GPIO_REGULATOR_DEV_NAME,
 	.id	= APQ8064_EXT_3P3V_REG_EN_GPIO,
@@ -1100,13 +1306,32 @@
 	},
 };
 
+static struct platform_device apq8064_device_ext_ts_sw_vreg __devinitdata = {
+	.name	= GPIO_REGULATOR_DEV_NAME,
+	.id	= PM8921_GPIO_PM_TO_SYS(23),
+	.dev	= {
+		.platform_data
+			= &apq8064_gpio_regulator_pdata[GPIO_VREG_ID_EXT_TS_SW],
+	},
+};
+
+static struct platform_device apq8064_device_rpm_regulator __devinitdata = {
+	.name	= "rpm-regulator",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &apq8064_rpm_regulator_pdata,
+	},
+};
+
 static struct platform_device *common_devices[] __initdata = {
 	&apq8064_device_dmov,
+	&apq8064_device_qup_i2c_gsbi3,
 	&apq8064_device_qup_i2c_gsbi4,
 	&apq8064_device_qup_spi_gsbi5,
-	&apq8064_slim_ctrl,
 	&apq8064_device_ext_5v_vreg,
+	&apq8064_device_ext_mpp8_vreg,
 	&apq8064_device_ext_3p3v_vreg,
+	&apq8064_device_ext_ts_sw_vreg,
 	&apq8064_device_ssbi_pmic1,
 	&apq8064_device_ssbi_pmic2,
 	&msm_device_smd_apq8064,
@@ -1173,7 +1398,7 @@
 	&msm_bus_8064_mm_fabric,
 	&msm_bus_8064_sys_fpb,
 	&msm_bus_8064_cpss_fpb,
-	&msm_device_vidc,
+	&apq8064_msm_device_vidc,
 	&msm_8960_riva,
 	&msm_8960_q6_lpass,
 	&msm_gss,
@@ -1194,6 +1419,7 @@
 
 static struct platform_device *cdp_devices[] __initdata = {
 	&apq8064_device_uart_gsbi1,
+	&apq8064_device_uart_gsbi7,
 	&msm_device_sps_apq8064,
 };
 
@@ -1226,6 +1452,11 @@
 	/* add more slimbus slaves as needed */
 };
 
+static struct msm_i2c_platform_data apq8064_i2c_qup_gsbi3_pdata = {
+	.clk_freq = 100000,
+	.src_clk_rate = 24000000,
+};
+
 static struct msm_i2c_platform_data apq8064_i2c_qup_gsbi4_pdata = {
 	.clk_freq = 100000,
 	.src_clk_rate = 24000000,
@@ -1233,6 +1464,8 @@
 
 static void __init apq8064_i2c_init(void)
 {
+	apq8064_device_qup_i2c_gsbi3.dev.platform_data =
+					&apq8064_i2c_qup_gsbi3_pdata;
 	apq8064_device_qup_i2c_gsbi4.dev.platform_data =
 					&apq8064_i2c_qup_gsbi4_pdata;
 }
@@ -1266,15 +1499,74 @@
 		msm_clock_init(&apq8064_clock_init_data);
 }
 
+#define I2C_SURF 1
+#define I2C_FFA  (1 << 1)
+#define I2C_RUMI (1 << 2)
+#define I2C_SIM  (1 << 3)
+#define I2C_LIQUID (1 << 4)
+
+struct i2c_registry {
+	u8                     machs;
+	int                    bus;
+	struct i2c_board_info *info;
+	int                    len;
+};
+
+static struct i2c_registry apq8064_i2c_devices[] __initdata = {
+	{
+		I2C_SURF | I2C_LIQUID,
+		APQ_8064_GSBI3_QUP_I2C_BUS_ID,
+		mxt_device_info,
+		ARRAY_SIZE(mxt_device_info),
+	},
+	{
+		I2C_FFA,
+		APQ_8064_GSBI3_QUP_I2C_BUS_ID,
+		cyttsp_info,
+		ARRAY_SIZE(cyttsp_info),
+	},
+};
+
+static void __init register_i2c_devices(void)
+{
+	u8 mach_mask = 0;
+	int i;
+
+	/* Build the matching 'supported_machs' bitmask */
+	if (machine_is_apq8064_cdp())
+		mach_mask = I2C_SURF;
+	else if (machine_is_apq8064_mtp())
+		mach_mask = I2C_FFA;
+	else if (machine_is_apq8064_liquid())
+		mach_mask = I2C_LIQUID;
+	else if (machine_is_apq8064_rumi3())
+		mach_mask = I2C_RUMI;
+	else if (machine_is_apq8064_sim())
+		mach_mask = I2C_SIM;
+	else
+		pr_err("unmatched machine ID in register_i2c_devices\n");
+
+	/* Run the array and install devices as appropriate */
+	for (i = 0; i < ARRAY_SIZE(apq8064_i2c_devices); ++i) {
+		if (apq8064_i2c_devices[i].machs & mach_mask)
+			i2c_register_board_info(apq8064_i2c_devices[i].bus,
+						apq8064_i2c_devices[i].info,
+						apq8064_i2c_devices[i].len);
+	}
+}
+
 static void __init apq8064_common_init(void)
 {
 	if (socinfo_init() < 0)
 		pr_err("socinfo_init() failed!\n");
 	BUG_ON(msm_rpm_init(&apq8064_rpm_data));
 	BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
+	regulator_suppress_info_printing();
+	platform_device_register(&apq8064_device_rpm_regulator);
 	apq8064_clock_init();
 	apq8064_init_gpiomux();
 	apq8064_i2c_init();
+	register_i2c_devices();
 
 	apq8064_device_qup_spi_gsbi5.dev.platform_data =
 						&apq8064_qup_spi_gsbi5_pdata;
@@ -1287,6 +1579,12 @@
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
 	apq8064_pm8xxx_gpio_mpp_init();
 	apq8064_init_mmc();
+
+	if (machine_is_apq8064_mtp()) {
+		mdm_8064_device.dev.platform_data = &mdm_platform_data;
+		platform_device_register(&mdm_8064_device);
+	}
+	platform_device_register(&apq8064_slim_ctrl);
 	slim_register_board_info(apq8064_slim_devices,
 		ARRAY_SIZE(apq8064_slim_devices));
 	msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
@@ -1297,11 +1595,6 @@
 	msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
 				msm_pm_data);
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
-
-	if (machine_is_apq8064_mtp()) {
-		mdm_8064_device.dev.platform_data = &mdm_platform_data;
-		platform_device_register(&mdm_8064_device);
-	}
 }
 
 static void __init apq8064_allocate_memory_regions(void)
@@ -1335,7 +1628,10 @@
 	ethernet_init();
 	platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
 	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+	apq8064_init_fb();
 	apq8064_init_gpu();
+	platform_add_devices(msm_footswitch_devices,
+			     msm_num_footswitch_devices);
 }
 
 MACHINE_START(APQ8064_SIM, "QCT APQ8064 SIMULATOR")
@@ -1364,6 +1660,7 @@
 	.handle_irq = gic_handle_irq,
 	.timer = &msm_timer,
 	.init_machine = apq8064_cdp_init,
+	.init_early = apq8064_allocate_memory_regions,
 MACHINE_END
 
 MACHINE_START(APQ8064_MTP, "QCT APQ8064 MTP")
@@ -1373,6 +1670,7 @@
 	.handle_irq = gic_handle_irq,
 	.timer = &msm_timer,
 	.init_machine = apq8064_cdp_init,
+	.init_early = apq8064_allocate_memory_regions,
 MACHINE_END
 
 MACHINE_START(APQ8064_LIQUID, "QCT APQ8064 LIQUID")
@@ -1382,5 +1680,6 @@
 	.handle_irq = gic_handle_irq,
 	.timer = &msm_timer,
 	.init_machine = apq8064_cdp_init,
+	.init_early = apq8064_allocate_memory_regions,
 MACHINE_END
 
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index e1451f5..d401f4c 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -18,6 +18,7 @@
 #include <linux/mfd/pm8xxx/pm8821.h>
 #include <mach/msm_memtypes.h>
 #include <mach/irqs.h>
+#include <mach/rpm-regulator.h>
 
 /* Macros assume PMIC GPIOs and MPPs start at 1 */
 #define PM8921_GPIO_BASE		NR_GPIO_IRQS
@@ -37,12 +38,17 @@
 
 #define GPIO_VREG_ID_EXT_5V		0
 #define GPIO_VREG_ID_EXT_3P3V		1
+#define GPIO_VREG_ID_EXT_TS_SW		2
+#define GPIO_VREG_ID_EXT_MPP8		3
 
 #define APQ8064_EXT_3P3V_REG_EN_GPIO	77
 
 extern struct gpio_regulator_platform_data
 	apq8064_gpio_regulator_pdata[] __devinitdata;
 
+extern struct rpm_regulator_platform_data
+	apq8064_rpm_regulator_pdata __devinitdata;
+
 extern struct regulator_init_data msm8064_saw_regulator_pdata_8921_s5;
 extern struct regulator_init_data msm8064_saw_regulator_pdata_8921_s6;
 extern struct regulator_init_data msm8064_saw_regulator_pdata_8821_s0;
@@ -58,6 +64,7 @@
 
 extern struct msm_camera_board_info apq8064_camera_board_info;
 void apq8064_init_cam(void);
+#define APQ_8064_GSBI3_QUP_I2C_BUS_ID 3
 #define APQ_8064_GSBI4_QUP_I2C_BUS_ID 4
 
 void apq8064_init_fb(void);
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index 30c912e..e0bc723 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -495,6 +495,34 @@
 };
 #endif
 
+static struct camera_vreg_t msm_8930_s5k3l1yx_vreg[] = {
+	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+	{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
+};
+
+static struct msm_camera_sensor_flash_data flash_s5k3l1yx = {
+	.flash_type = MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_s5k3l1yx = {
+	.mount_angle  = 0,
+	.cam_vreg = msm_8930_s5k3l1yx_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8930_s5k3l1yx_vreg),
+	.gpio_conf = &msm_8930_back_cam_gpio_conf,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_s5k3l1yx_data = {
+	.sensor_name          = "s5k3l1yx",
+	.pdata                = &msm_camera_csi_device_data[0],
+	.flash_data           = &flash_s5k3l1yx,
+	.sensor_platform_info = &sensor_board_info_s5k3l1yx,
+	.csi_if               = 1,
+	.camera_type          = BACK_CAMERA_2D,
+};
+
 void __init msm8930_init_cam(void)
 {
 	msm_gpiomux_install(msm8930_cam_common_configs,
@@ -527,6 +555,10 @@
 	I2C_BOARD_INFO("mt9m114", 0x48),
 	.platform_data = &msm_camera_sensor_mt9m114_data,
 	},
+	{
+	I2C_BOARD_INFO("s5k3l1yx", 0x20),
+	.platform_data = &msm_camera_sensor_s5k3l1yx_data,
+	},
 #ifdef CONFIG_MSM_CAMERA_FLASH_SC628A
 	{
 	I2C_BOARD_INFO("sc628a", 0x6E),
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index 262616f..9175c75 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -228,6 +228,11 @@
 			pr_err("enable l2 failed, rc=%d\n", rc);
 			return -ENODEV;
 		}
+		usleep(10000);
+		gpio_set_value(DISP_RST_GPIO, 1);
+		usleep(10);
+		gpio_set_value(DISP_RST_GPIO, 0);
+		usleep(20);
 		gpio_set_value(DISP_RST_GPIO, 1);
 	} else {
 
@@ -412,7 +417,7 @@
 #else
 static int mdp_core_clk_rate_table[] = {
 	85330000,
-	85330000,
+	128000000,
 	160000000,
 	200000000,
 };
diff --git a/arch/arm/mach-msm/board-8930-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
index 2f59d9d..3f9f976 100644
--- a/arch/arm/mach-msm/board-8930-pmic.c
+++ b/arch/arm/mach-msm/board-8930-pmic.c
@@ -225,6 +225,45 @@
 	.thermal_levels		= ARRAY_SIZE(pm8921_therm_mitigation),
 };
 
+#define PM8038_WLED_MAX_CURRENT		25
+
+static struct led_info pm8038_led_info[] = {
+	[0] = {
+		.name			= "wled",
+	},
+};
+
+static struct led_platform_data pm8038_led_core_pdata = {
+	.num_leds = ARRAY_SIZE(pm8038_led_info),
+	.leds = pm8038_led_info,
+};
+
+static struct wled_config_data wled_cfg = {
+	.dig_mod_gen_en = true,
+	.cs_out_en = true,
+	.ctrl_delay_us = 0,
+	.op_fdbck = true,
+	.ovp_val = WLED_OVP_32V,
+	.boost_curr_lim = WLED_CURR_LIMIT_525mA,
+	.num_strings = 1,
+};
+
+static struct pm8xxx_led_config pm8038_led_configs[] = {
+	[0] = {
+		.id = PM8XXX_ID_WLED,
+		.mode = PM8XXX_LED_MODE_MANUAL,
+		.max_current = PM8038_WLED_MAX_CURRENT,
+		.default_state = 1,
+		.wled_cfg = &wled_cfg,
+	},
+};
+
+static struct pm8xxx_led_platform_data pm8xxx_leds_pdata = {
+	.led_core = &pm8038_led_core_pdata,
+	.configs = pm8038_led_configs,
+	.num_configs = ARRAY_SIZE(pm8038_led_configs),
+};
+
 static struct pm8xxx_ccadc_platform_data pm8xxx_ccadc_pdata = {
 	.r_sense		= 10,
 };
@@ -252,6 +291,7 @@
 	.charger_pdata		= &pm8921_chg_pdata,
 	.bms_pdata		= &pm8921_bms_pdata,
 	.adc_pdata		= &pm8xxx_adc_pdata,
+	.leds_pdata		= &pm8xxx_leds_pdata,
 	.ccadc_pdata		= &pm8xxx_ccadc_pdata,
 };
 
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index 0208631..2f9fdcd 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -33,6 +33,7 @@
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-001a"),
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-006c"),
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-0048"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",        "4-0020"),
 };
 VREG_CONSUMERS(L3) = {
 	REGULATOR_SUPPLY("8038_l3",		NULL),
@@ -68,6 +69,8 @@
 	REGULATOR_SUPPLY("cam_vaf",		"4-001a"),
 	REGULATOR_SUPPLY("cam_vaf",		"4-006c"),
 	REGULATOR_SUPPLY("cam_vaf",		"4-0048"),
+	REGULATOR_SUPPLY("cam_vana",            "4-0020"),
+	REGULATOR_SUPPLY("cam_vaf",             "4-0020"),
 };
 VREG_CONSUMERS(L10) = {
 	REGULATOR_SUPPLY("8038_l10",		NULL),
@@ -88,6 +91,7 @@
 	REGULATOR_SUPPLY("cam_vdig",		"4-001a"),
 	REGULATOR_SUPPLY("cam_vdig",		"4-006c"),
 	REGULATOR_SUPPLY("cam_vdig",		"4-0048"),
+	REGULATOR_SUPPLY("cam_vdig",            "4-0020"),
 };
 VREG_CONSUMERS(L14) = {
 	REGULATOR_SUPPLY("8038_l14",		NULL),
@@ -108,6 +112,7 @@
 	REGULATOR_SUPPLY("cam_vio",		"4-001a"),
 	REGULATOR_SUPPLY("cam_vio",		"4-006c"),
 	REGULATOR_SUPPLY("cam_vio",		"4-0048"),
+	REGULATOR_SUPPLY("cam_vio",             "4-0020"),
 };
 VREG_CONSUMERS(L19) = {
 	REGULATOR_SUPPLY("8038_l19",		NULL),
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 3858e63..90cc3c5 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -40,6 +40,7 @@
 #include <linux/ks8851.h>
 #include <linux/i2c/isa1200.h>
 #include <linux/gpio_keys.h>
+#include <linux/memory.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -429,12 +430,9 @@
 
 	if (high - low <= bank_size)
 		return;
-	msm8930_reserve_info.low_unstable_address = low + bank_size;
-	/* To avoid overflow of u32 compute max_unstable_size
-	 * by first subtracting low from mb->start)
-	 * */
-	msm8930_reserve_info.max_unstable_size = (mb->start - low) +
-						mb->size - bank_size;
+	msm8930_reserve_info.low_unstable_address = mb->start -
+					MIN_MEMORY_BLOCK_SIZE + mb->size;
+	msm8930_reserve_info.max_unstable_size = MIN_MEMORY_BLOCK_SIZE;
 
 	msm8930_reserve_info.bank_size = bank_size;
 	pr_info("low unstable address %lx max size %lx bank size %lx\n",
@@ -902,12 +900,6 @@
 	msm_mpm_irq_extn_init(data);
 	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
 						(void *)MSM_QGIC_CPU_BASE);
-
-	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-	writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
-	writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-	mb();
 }
 
 static void __init msm8930_init_buses(void)
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index 2995679..23c4928 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -219,6 +219,18 @@
 		.ab  = 0,
 		.ib  = 0,
 	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 0,
+		.ib  = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 0,
+		.ib  = 0,
+	},
 };
 
 static struct msm_bus_vectors cam_preview_vectors[] = {
@@ -240,6 +252,18 @@
 		.ab  = 0,
 		.ib  = 0,
 	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 0,
+		.ib  = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 0,
+		.ib  = 0,
+	},
 };
 
 static struct msm_bus_vectors cam_video_vectors[] = {
@@ -261,6 +285,18 @@
 		.ab  = 0,
 		.ib  = 0,
 	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 0,
+		.ib  = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 0,
+		.ib  = 0,
+	},
 };
 
 static struct msm_bus_vectors cam_snapshot_vectors[] = {
@@ -282,6 +318,18 @@
 		.ab  = 540000000,
 		.ib  = 1350000000,
 	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 43200000,
+		.ib  = 69120000,
+	},
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 43200000,
+		.ib  = 69120000,
+	},
 };
 
 static struct msm_bus_vectors cam_zsl_vectors[] = {
@@ -303,6 +351,18 @@
 		.ab  = 540000000,
 		.ib  = 1350000000,
 	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 43200000,
+		.ib  = 69120000,
+	},
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 43200000,
+		.ib  = 69120000,
+	},
 };
 
 static struct msm_bus_paths cam_bus_client_config[] = {
@@ -500,6 +560,34 @@
 };
 #endif
 
+static struct camera_vreg_t msm_8960_s5k3l1yx_vreg[] = {
+	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+	{"cam_vio", REG_VS, 0, 0, 0},
+	{"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
+};
+
+static struct msm_camera_sensor_flash_data flash_s5k3l1yx = {
+	.flash_type = MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_s5k3l1yx = {
+	.mount_angle  = 0,
+	.cam_vreg = msm_8960_s5k3l1yx_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8960_s5k3l1yx_vreg),
+	.gpio_conf = &msm_8960_back_cam_gpio_conf,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_s5k3l1yx_data = {
+	.sensor_name          = "s5k3l1yx",
+	.pdata                = &msm_camera_csi_device_data[0],
+	.flash_data           = &flash_s5k3l1yx,
+	.sensor_platform_info = &sensor_board_info_s5k3l1yx,
+	.csi_if               = 1,
+	.camera_type          = BACK_CAMERA_2D,
+};
+
 static struct pm8xxx_mpp_config_data privacy_light_on_config = {
 	.type		= PM8XXX_MPP_TYPE_SINK,
 	.level		= PM8XXX_MPP_CS_OUT_5MA,
@@ -580,6 +668,10 @@
 	I2C_BOARD_INFO("mt9m114", 0x48),
 	.platform_data = &msm_camera_sensor_mt9m114_data,
 	},
+	{
+	I2C_BOARD_INFO("s5k3l1yx", 0x20),
+	.platform_data = &msm_camera_sensor_s5k3l1yx_data,
+	},
 #ifdef CONFIG_MSM_CAMERA_FLASH_SC628A
 	{
 	I2C_BOARD_INFO("sc628a", 0x6E),
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index f9bc8fc..aa8477e 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -81,6 +81,8 @@
 	}
 };
 
+static void set_mdp_clocks_for_liquid_wuxga(void);
+
 static int msm_fb_detect_panel(const char *name)
 {
 	if (machine_is_msm8960_liquid()) {
@@ -88,8 +90,10 @@
 		if (SOCINFO_VERSION_MAJOR(ver) == 3) {
 			if (!strncmp(name, MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME,
 				     strnlen(MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME,
-						PANEL_NAME_MAX_LEN)))
+						PANEL_NAME_MAX_LEN))) {
+				set_mdp_clocks_for_liquid_wuxga();
 				return 0;
+			}
 		} else {
 			if (!strncmp(name, MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
 				     strnlen(MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
@@ -617,7 +621,7 @@
 #else
 static int mdp_core_clk_rate_table[] = {
 	85330000,
-	85330000,
+	128000000,
 	160000000,
 	200000000,
 };
@@ -643,6 +647,24 @@
 #endif
 };
 
+/**
+ * Set MDP clocks to high frequency to avoid DSI underflow
+ * when using high resolution 1200x1920 WUXGA panel.
+ */
+static void set_mdp_clocks_for_liquid_wuxga(void)
+{
+	int i;
+
+	mdp_ui_vectors[0].ab = 2000000000;
+	mdp_ui_vectors[0].ib = 2000000000;
+
+	mdp_pdata.mdp_core_clk_rate = 200000000;
+
+	for (i = 0; i < ARRAY_SIZE(mdp_core_clk_rate_table); i++)
+		mdp_core_clk_rate_table[i] = 200000000;
+
+}
+
 void __init msm8960_mdp_writeback(struct memtype_reserve* reserve_table)
 {
 	mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
@@ -681,9 +703,11 @@
 };
 
 #define FPGA_3D_GPIO_CONFIG_ADDR	0xB5
-static int dsi2lvds_gpio[2] = {
+static int dsi2lvds_gpio[4] = {
 	0,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
-	0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
+	0x1F08, /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
+	GPIO_LIQUID_EXPANDER_BASE+6,	/* TN Enable */
+	GPIO_LIQUID_EXPANDER_BASE+7,	/* TN Mode */
 	};
 
 static struct msm_panel_common_pdata mipi_dsi2lvds_pdata = {
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index 04376bc..744709c 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -95,9 +95,12 @@
 	PM8XXX_GPIO_INPUT(16,	    PM_GPIO_PULL_UP_30), /* SD_CARD_WP */
     /* External regulator shared by display and touchscreen on LiQUID */
 	PM8XXX_GPIO_OUTPUT(17,	    0),			 /* DISP 3.3 V Boost */
+	PM8XXX_GPIO_OUTPUT(18,	1),	/* TABLA SPKR_LEFT_EN */
+	PM8XXX_GPIO_OUTPUT(19,	1),	/* TABLA SPKR_RIGHT_EN */
 	PM8XXX_GPIO_OUTPUT_VIN(21, 1, PM_GPIO_VIN_VPH),	 /* Backlight Enable */
 	PM8XXX_GPIO_DISABLE(22),			 /* Disable NFC */
 	PM8XXX_GPIO_OUTPUT_FUNC(24, 0, PM_GPIO_FUNC_2),	 /* Bl: Off, PWM mode */
+	PM8XXX_GPIO_OUTPUT_FUNC(25, 0, PM_GPIO_FUNC_2),	 /* TN_CLK */
 	PM8XXX_GPIO_INPUT(26,	    PM_GPIO_PULL_UP_30), /* SD_CARD_DET_N */
 	PM8XXX_GPIO_OUTPUT(43,	    PM_GPIO_PULL_UP_30), /* DISP_RESET_N */
 	PM8XXX_GPIO_OUTPUT(42, 0),                      /* USB 5V reg enable */
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 6819d5d..0f05af5 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -33,6 +33,7 @@
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-001a"),
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-006c"),
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-0048"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-0020"),
 };
 VREG_CONSUMERS(L3) = {
 	REGULATOR_SUPPLY("8921_l3",		NULL),
@@ -74,12 +75,14 @@
 	REGULATOR_SUPPLY("cam_vana",		"4-001a"),
 	REGULATOR_SUPPLY("cam_vana",		"4-006c"),
 	REGULATOR_SUPPLY("cam_vana",		"4-0048"),
+	REGULATOR_SUPPLY("cam_vana",		"4-0020"),
 };
 VREG_CONSUMERS(L12) = {
 	REGULATOR_SUPPLY("8921_l12",		NULL),
 	REGULATOR_SUPPLY("cam_vdig",		"4-001a"),
 	REGULATOR_SUPPLY("cam_vdig",		"4-006c"),
 	REGULATOR_SUPPLY("cam_vdig",		"4-0048"),
+	REGULATOR_SUPPLY("cam_vdig",		"4-0020"),
 };
 VREG_CONSUMERS(L14) = {
 	REGULATOR_SUPPLY("8921_l14",		NULL),
@@ -93,6 +96,7 @@
 	REGULATOR_SUPPLY("cam_vaf",		"4-001a"),
 	REGULATOR_SUPPLY("cam_vaf",		"4-006c"),
 	REGULATOR_SUPPLY("cam_vaf",		"4-0048"),
+	REGULATOR_SUPPLY("cam_vaf",		"4-0020"),
 };
 VREG_CONSUMERS(L17) = {
 	REGULATOR_SUPPLY("8921_l17",		NULL),
@@ -207,6 +211,7 @@
 	REGULATOR_SUPPLY("cam_vio",		"4-001a"),
 	REGULATOR_SUPPLY("cam_vio",		"4-006c"),
 	REGULATOR_SUPPLY("cam_vio",		"4-0048"),
+	REGULATOR_SUPPLY("cam_vio",		"4-0020"),
 };
 VREG_CONSUMERS(LVS6) = {
 	REGULATOR_SUPPLY("8921_lvs6",		NULL),
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 9985b32..76a27ff 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -301,10 +301,6 @@
 #endif
 }
 
-static void __init reserve_fmem_memory(void)
-{
-}
-
 static int msm8960_paddr_to_memtype(unsigned int paddr)
 {
 	return MEMTYPE_EBI1;
@@ -315,11 +311,13 @@
 static struct ion_cp_heap_pdata cp_mm_ion_pdata = {
 	.permission_type = IPT_TYPE_MM_CARVEOUT,
 	.align = PAGE_SIZE,
+	.reusable = 1,
 };
 
 static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
 	.permission_type = IPT_TYPE_MFC_SHAREDMEM,
 	.align = PAGE_SIZE,
+	.reusable = 0,
 };
 
 static struct ion_co_heap_pdata co_ion_pdata = {
@@ -411,9 +409,8 @@
 	.dev = { .platform_data = &fmem_pdata },
 };
 
-static void reserve_ion_memory(void)
+static void __init adjust_mem_for_liquid(void)
 {
-#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
 	unsigned int i;
 
 	if (!pmem_param_set && machine_is_msm8960_liquid()) {
@@ -427,12 +424,99 @@
 			}
 		}
 	}
-	msm8960_reserve_table[MEMTYPE_EBI1].size += msm_ion_cp_mm_size;
-	msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_FW_SIZE;
-	msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE;
-	msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MFC_SIZE;
-	msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_QSECOM_SIZE;
-	msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE;
+}
+
+static void __init reserve_mem_for_ion(enum ion_memory_types mem_type,
+				      unsigned long size)
+{
+	msm8960_reserve_table[mem_type].size += size;
+}
+
+static __init const struct ion_platform_heap *find_ion_heap(int heap_id)
+{
+	unsigned int i;
+	for (i = 0; i < ion_pdata.nr; ++i) {
+		const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+		if (heap->id == heap_id)
+			return (const struct ion_platform_heap *) heap;
+	}
+	return 0;
+}
+
+/**
+ * Reserve memory for ION and calculate amount of reusable memory for fmem.
+ * We only reserve memory for heaps that are not reusable. However, we only
+ * support one reusable heap at the moment so we ignore the reusable flag for
+ * other than the first heap with reusable flag set. Also handle special case
+ * for adjacent heap when the adjacent heap is adjacent to a reusable heap.
+ */
+static void __init reserve_ion_memory(void)
+{
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+	unsigned int i;
+	unsigned int reusable_count = 0;
+
+	adjust_mem_for_liquid();
+	fmem_pdata.size = 0;
+	fmem_pdata.reserved_size = 0;
+
+	/* We only support 1 reusable heap. Check if more than one heap
+	 * is specified as reusable and set as non-reusable if found.
+	 */
+	for (i = 0; i < ion_pdata.nr; ++i) {
+		const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+
+		if (heap->type == ION_HEAP_TYPE_CP && heap->extra_data) {
+			struct ion_cp_heap_pdata *data = heap->extra_data;
+
+			reusable_count += (data->reusable) ? 1 : 0;
+
+			if (data->reusable && reusable_count > 1) {
+				pr_err("%s: Too many heaps specified as "
+					"reusable. Heap %s was not configured "
+					"as reusable.\n", __func__, heap->name);
+				data->reusable = 0;
+			}
+		}
+	}
+
+	for (i = 0; i < ion_pdata.nr; ++i) {
+		int reusable = 0;
+		int adjacent_heap_id = INVALID_HEAP_ID;
+		int adj_reusable = 0;
+		const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+
+		if (heap->extra_data) {
+			switch (heap->type) {
+			case ION_HEAP_TYPE_CP:
+				reusable = ((struct ion_cp_heap_pdata *)
+						heap->extra_data)->reusable;
+				break;
+			case ION_HEAP_TYPE_CARVEOUT:
+				adjacent_heap_id = ((struct ion_co_heap_pdata *)
+					heap->extra_data)->adjacent_mem_id;
+				break;
+			default:
+				break;
+			}
+		}
+
+		if (adjacent_heap_id != INVALID_HEAP_ID) {
+			const struct ion_platform_heap *adj_heap =
+						find_ion_heap(adjacent_heap_id);
+			if (adj_heap) {
+				adj_reusable = ((struct ion_cp_heap_pdata *)
+						adj_heap->extra_data)->reusable;
+				if (adj_reusable)
+					fmem_pdata.reserved_size += heap->size;
+			}
+		}
+
+		if (!reusable && !adj_reusable)
+			reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
+		else
+			fmem_pdata.size += heap->size;
+	}
 #endif
 }
 
@@ -446,7 +530,6 @@
 	size_pmem_devices();
 	reserve_pmem_memory();
 	reserve_ion_memory();
-	reserve_fmem_memory();
 	reserve_mdp_memory();
 }
 
@@ -898,12 +981,6 @@
 	msm_mpm_irq_extn_init(data);
 	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
 						(void *)MSM_QGIC_CPU_BASE);
-
-	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-	writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
-	writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-	mb();
 }
 
 static void __init msm8960_init_buses(void)
@@ -945,12 +1022,54 @@
 	0x23, 0x83,/* set source impedance sdjusment */
 	-1};
 
+#ifdef CONFIG_MSM_BUS_SCALING
+/* Bandwidth requests (zero) if no vote placed */
+static struct msm_bus_vectors usb_init_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = 0,
+	},
+};
+
+/* Bus bandwidth requests in Bytes/sec */
+static struct msm_bus_vectors usb_max_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 60000000,		/* At least 480Mbps on bus. */
+		.ib = 960000000,	/* MAX bursts rate */
+	},
+};
+
+static struct msm_bus_paths usb_bus_scale_usecases[] = {
+	{
+		ARRAY_SIZE(usb_init_vectors),
+		usb_init_vectors,
+	},
+	{
+		ARRAY_SIZE(usb_max_vectors),
+		usb_max_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata usb_bus_scale_pdata = {
+	usb_bus_scale_usecases,
+	ARRAY_SIZE(usb_bus_scale_usecases),
+	.name = "usb",
+};
+#endif
+
 static struct msm_otg_platform_data msm_otg_pdata = {
 	.mode			= USB_OTG,
 	.otg_control		= OTG_PMIC_CONTROL,
 	.phy_type		= SNPS_28NM_INTEGRATED_PHY,
 	.pmic_id_irq		= PM8921_USB_ID_IN_IRQ(PM8921_IRQ_BASE),
 	.power_budget		= 750,
+#ifdef CONFIG_MSM_BUS_SCALING
+	.bus_scale_table	= &usb_bus_scale_pdata,
+#endif
 };
 #endif
 
@@ -1839,6 +1958,7 @@
 	&msm_bus_sys_fpb,
 	&msm_bus_cpss_fpb,
 	&msm_pcm,
+	&msm_multi_ch_pcm,
 	&msm_pcm_routing,
 	&msm_cpudai0,
 	&msm_cpudai1,
@@ -1890,6 +2010,7 @@
 	&msm_device_hsusb_host,
 	&android_usb_device,
 	&msm_pcm,
+	&msm_multi_ch_pcm,
 	&msm_pcm_routing,
 	&msm_cpudai0,
 	&msm_cpudai1,
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 84a8a42..1f19bf6 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -31,6 +31,7 @@
 #include <mach/gpio.h>
 #include <mach/msm_spi.h>
 #include <mach/msm_bus_board.h>
+#include <mach/msm_xo.h>
 #include "timer.h"
 #include "devices.h"
 #include "board-9615.h"
@@ -568,6 +569,7 @@
 	msm9615_i2c_init();
 	regulator_suppress_info_printing();
 	platform_device_register(&msm9615_device_rpm_regulator);
+	msm_xo_init();
 	msm_clock_init(&msm9615_clock_init_data);
 	msm9615_init_buses();
 	msm9615_device_qup_spi_gsbi3.dev.platform_data =
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index 1bfb759..b4b0b9a 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -233,12 +233,6 @@
 
 void __init msm_copper_init_irq(void)
 {
-	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-	writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
-	writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-	mb();
-
 	of_irq_init(irq_match);
 }
 
diff --git a/arch/arm/mach-msm/board-msm7627a-bt.c b/arch/arm/mach-msm/board-msm7627a-bt.c
index 5acfcd5b..c70b30e 100644
--- a/arch/arm/mach-msm/board-msm7627a-bt.c
+++ b/arch/arm/mach-msm/board-msm7627a-bt.c
@@ -935,6 +935,9 @@
 	int i, rc = 0;
 	struct device *dev;
 
+	if (machine_is_msm7627a_qrd3())
+		return;
+
 	gpio_bt_config();
 
 	i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index e3f668f..c0b1d16 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -796,6 +796,8 @@
 				ARRAY_SIZE(camera_devices_qrd));
 	} else if (machine_is_msm7627a_evb())
 		return;
+	else if (machine_is_msm7627a_qrd3())
+		return;
 	else
 		platform_add_devices(camera_devices_msm,
 				ARRAY_SIZE(camera_devices_msm));
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index 030c129..011a4d4 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -226,6 +226,9 @@
 	} else if (machine_is_msm7627a_qrd1()) {
 		if (!strncmp(name, "mipi_video_truly_wvga", 21))
 			ret = 0;
+	} else if (machine_is_msm7627a_evb()) {
+		if (!strncmp(name, "mipi_cmd_nt35510_wvga", 21))
+			ret = 0;
 	}
 
 #if !defined(CONFIG_FB_MSM_LCDC_AUTO_DETECT) && \
@@ -303,6 +306,18 @@
 	}
 };
 
+static struct msm_panel_common_pdata mipi_NT35510_pdata = {
+	.pmic_backlight = NULL,/*mipi_NT35510_set_bl,*/
+};
+
+static struct platform_device mipi_dsi_NT35510_panel_device = {
+	.name = "mipi_NT35510",
+	.id   = 0,
+	.dev  = {
+		.platform_data = &mipi_NT35510_pdata,
+	}
+};
+
 static struct platform_device *msm_fb_devices[] __initdata = {
 	&msm_fb_device,
 	&lcdc_toshiba_panel_device,
@@ -317,7 +332,8 @@
 };
 
 static struct platform_device *evb_fb_devices[] __initdata = {
-
+	&msm_fb_device,
+	&mipi_dsi_NT35510_panel_device,
 };
 
 void __init msm_msm7627a_allocate_memory_regions(void)
@@ -487,12 +503,60 @@
 	return rc;
 }
 
+#define GPIO_QRD3_LCD_BRDG_RESET_N	85
+#define GPIO_QRD3_LCD_BACKLIGHT_EN	96
+#define GPIO_QRD3_LCD_EXT_2V85_EN	35
+#define GPIO_QRD3_LCD_EXT_1V8_EN	40
+
+static unsigned qrd3_mipi_dsi_gpio[] = {
+	GPIO_CFG(GPIO_QRD3_LCD_BRDG_RESET_N, 0, GPIO_CFG_OUTPUT,
+			GPIO_CFG_NO_PULL,
+			GPIO_CFG_2MA), /* GPIO_QRD3_LCD_BRDG_RESET_N */
+	GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0, GPIO_CFG_OUTPUT,
+			GPIO_CFG_NO_PULL,
+			GPIO_CFG_2MA), /* GPIO_QRD3_LCD_BACKLIGHT_EN */
+	GPIO_CFG(GPIO_QRD3_LCD_EXT_2V85_EN, 0, GPIO_CFG_OUTPUT,
+			GPIO_CFG_NO_PULL,
+			GPIO_CFG_2MA), /* GPIO_QRD3_LCD_EXT_2V85_EN */
+	GPIO_CFG(GPIO_QRD3_LCD_EXT_1V8_EN, 0, GPIO_CFG_OUTPUT,
+			GPIO_CFG_NO_PULL,
+			GPIO_CFG_2MA), /* GPIO_QRD3_LCD_EXT_1V8_EN */
+};
+
+static int msm_fb_dsi_client_qrd3_reset(void)
+{
+	int rc = 0;
+
+	rc = gpio_request(GPIO_QRD3_LCD_BRDG_RESET_N, "qrd3_lcd_brdg_reset_n");
+	if (rc < 0) {
+		pr_err("failed to request qrd3 lcd brdg reset_n\n");
+		return rc;
+	}
+
+	rc = gpio_tlmm_config(qrd3_mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
+	if (rc < 0) {
+		pr_err("Failed to enable LCD Bridge reset enable\n");
+		return rc;
+	}
+
+	rc = gpio_direction_output(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
+	if (rc < 0) {
+		pr_err("Failed GPIO bridge Reset\n");
+		gpio_free(GPIO_QRD3_LCD_BRDG_RESET_N);
+		return rc;
+	}
+
+	return rc;
+}
+
 static int msm_fb_dsi_client_reset(void)
 {
 	int rc = 0;
 
 	if (machine_is_msm7627a_qrd1())
 		rc = msm_fb_dsi_client_qrd1_reset();
+	else if (machine_is_msm7627a_evb())
+		rc = msm_fb_dsi_client_qrd3_reset();
 	else
 		rc = msm_fb_dsi_client_msm_reset();
 
@@ -650,7 +714,7 @@
 
 	gpio_set_value_cansleep(QRD_GPIO_BACKLIGHT_EN, !!on);
 
-	if (!on) {
+	if (on) {
 		gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
 		msleep(20);
 		gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 0);
@@ -662,12 +726,99 @@
 	return rc;
 }
 
+static int qrd3_dsi_gpio_initialized;
+
+static int mipi_dsi_panel_qrd3_power(int on)
+{
+	int rc = 0;
+
+	if (!qrd3_dsi_gpio_initialized) {
+		rc = gpio_request(GPIO_QRD3_LCD_BACKLIGHT_EN,
+			"qrd3_gpio_bkl_en");
+		if (rc < 0)
+			return rc;
+
+		rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0,
+			GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+			GPIO_CFG_ENABLE);
+		if (rc < 0) {
+			pr_err("failed QRD3 GPIO_BACKLIGHT_EN tlmm config\n");
+			return rc;
+		}
+		rc = gpio_direction_output(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
+		if (rc < 0) {
+			pr_err("failed to enable backlight\n");
+			gpio_free(GPIO_QRD3_LCD_BACKLIGHT_EN);
+			return rc;
+		}
+
+		rc = gpio_request(GPIO_QRD3_LCD_EXT_2V85_EN,
+			"qrd3_gpio_ext_2v85_en");
+		if (rc < 0)
+			return rc;
+
+		rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_EXT_2V85_EN, 0,
+			GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+			GPIO_CFG_ENABLE);
+		if (rc < 0) {
+			pr_err("failed QRD3 GPIO_QRD3_LCD_EXT_2V85_EN tlmm config\n");
+			return rc;
+		}
+
+		rc = gpio_direction_output(GPIO_QRD3_LCD_EXT_2V85_EN, 1);
+		if (rc < 0) {
+			pr_err("failed to enable external 2V85\n");
+			gpio_free(GPIO_QRD3_LCD_EXT_2V85_EN);
+			return rc;
+		}
+
+		rc = gpio_request(GPIO_QRD3_LCD_EXT_1V8_EN,
+			"qrd3_gpio_ext_1v8_en");
+		if (rc < 0)
+			return rc;
+
+		rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_EXT_1V8_EN, 0,
+			GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+			GPIO_CFG_ENABLE);
+		if (rc < 0) {
+			pr_err("failed QRD3 GPIO_QRD3_LCD_EXT_1V8_EN tlmm config\n");
+			return rc;
+		}
+
+		rc = gpio_direction_output(GPIO_QRD3_LCD_EXT_1V8_EN, 1);
+		if (rc < 0) {
+			pr_err("failed to enable external 1v8\n");
+			gpio_free(GPIO_QRD3_LCD_EXT_1V8_EN);
+			return rc;
+		}
+
+			qrd3_dsi_gpio_initialized = 1;
+	}
+
+	gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, !!on);
+	gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_2V85_EN, !!on);
+	gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_1V8_EN, !!on);
+
+	if (on) {
+		gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
+		msleep(20);
+		gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 0);
+		msleep(20);
+		gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
+		msleep(20);
+	}
+
+		return rc;
+}
+
 static int mipi_dsi_panel_power(int on)
 {
 	int rc = 0;
 
 	if (machine_is_msm7627a_qrd1())
 		rc = mipi_dsi_panel_qrd1_power(on);
+	else if (machine_is_msm7627a_evb())
+		rc = mipi_dsi_panel_qrd3_power(on);
 	else
 		rc = mipi_dsi_panel_msm_power(on);
 	return rc;
@@ -692,6 +843,8 @@
 	else if (machine_is_msm7627a_evb())
 		platform_add_devices(evb_fb_devices,
 				ARRAY_SIZE(evb_fb_devices));
+	else if (machine_is_msm7627a_qrd3())
+		return;
 	else
 		platform_add_devices(msm_fb_devices,
 				ARRAY_SIZE(msm_fb_devices));
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index 8eb92a4..d5d8edc 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -1588,15 +1588,17 @@
 
 
 static struct msm_pm_platform_data msm7x25_pm_data[MSM_PM_SLEEP_MODE_NR] = {
-	[MSM_PM_SLEEP_MODE_POWER_COLLAPSE].latency = 16000,
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)].latency = 16000,
 
-	[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN].latency = 12000,
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN)]
+		.latency = 12000,
 
-	[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency = 2000,
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT)]
+		.latency = 2000,
 };
 
 static struct msm_pm_platform_data msm7x27_pm_data[MSM_PM_SLEEP_MODE_NR] = {
-	[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = {
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
 		.idle_supported = 1,
 		.suspend_supported = 1,
 		.idle_enabled = 1,
@@ -1605,7 +1607,7 @@
 		.residency = 20000,
 	},
 
-	[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN] = {
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN)] = {
 		.idle_supported = 1,
 		.suspend_supported = 1,
 		.idle_enabled = 1,
@@ -1614,7 +1616,7 @@
 		.residency = 20000,
 	},
 
-	[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT] = {
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT)] = {
 		.idle_supported = 1,
 		.suspend_supported = 1,
 		.idle_enabled = 1,
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index d2add18..51da14b 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/gpio_event.h>
+#include <linux/memblock.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
@@ -325,7 +326,7 @@
 };
 #endif
 static struct msm_pm_platform_data msm7x27a_pm_data[MSM_PM_SLEEP_MODE_NR] = {
-	[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = {
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
 					.idle_supported = 1,
 					.suspend_supported = 1,
 					.idle_enabled = 1,
@@ -333,7 +334,7 @@
 					.latency = 16000,
 					.residency = 20000,
 	},
-	[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN] = {
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN)] = {
 					.idle_supported = 1,
 					.suspend_supported = 1,
 					.idle_enabled = 1,
@@ -341,7 +342,7 @@
 					.latency = 12000,
 					.residency = 20000,
 	},
-	[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT] = {
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT)] = {
 					.idle_supported = 1,
 					.suspend_supported = 1,
 					.idle_enabled = 0,
@@ -349,7 +350,7 @@
 					.latency = 2000,
 					.residency = 0,
 	},
-	[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT] = {
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
 					.idle_supported = 1,
 					.suspend_supported = 1,
 					.idle_enabled = 1,
@@ -799,6 +800,11 @@
 	msm_reserve();
 }
 
+static void __init msm8625_reserve(void)
+{
+	memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
+}
+
 static void __init msm_device_i2c_init(void)
 {
 	if (machine_is_msm8625_rumi3()) {
@@ -1239,6 +1245,7 @@
 MACHINE_START(MSM8625_RUMI3, "QCT MSM8625 RUMI3")
 	.boot_params    = PHYS_OFFSET + 0x100,
 	.map_io         = msm8625_map_io,
+	.reserve        = msm8625_reserve,
 	.init_irq       = msm8625_init_irq,
 	.init_machine   = msm8625_rumi3_init,
 	.timer          = &msm_timer,
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index e0b3c49..47a4605 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -2907,7 +2907,7 @@
 };
 
 static struct msm_pm_platform_data msm_pm_data[MSM_PM_SLEEP_MODE_NR] = {
-	[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = {
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
 		.idle_supported = 1,
 		.suspend_supported = 1,
 		.idle_enabled = 1,
@@ -2915,7 +2915,7 @@
 		.latency = 8594,
 		.residency = 23740,
 	},
-	[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN] = {
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN)] = {
 		.idle_supported = 1,
 		.suspend_supported = 1,
 		.idle_enabled = 1,
@@ -2923,7 +2923,7 @@
 		.latency = 4594,
 		.residency = 23740,
 	},
-	[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE] = {
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
 #ifdef CONFIG_MSM_STANDALONE_POWER_COLLAPSE
 		.idle_supported = 1,
 		.suspend_supported = 1,
@@ -2938,7 +2938,7 @@
 		.latency = 500,
 		.residency = 6000,
 	},
-	[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT] = {
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT)] = {
 		.idle_supported = 1,
 		.suspend_supported = 1,
 		.idle_enabled = 0,
@@ -2946,7 +2946,7 @@
 		.latency = 443,
 		.residency = 1098,
 	},
-	[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT] = {
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
 		.idle_supported = 1,
 		.suspend_supported = 1,
 		.idle_enabled = 1,
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 29f5fac..74ba1b36 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -2697,7 +2697,7 @@
 #define USER_SMI_SIZE         (MSM_SMI_SIZE - KERNEL_SMI_SIZE)
 #define MSM_PMEM_SMIPOOL_SIZE USER_SMI_SIZE
 
-#define MSM_ION_SF_SIZE		0x1800000 /* 24MB */
+#define MSM_ION_SF_SIZE		0x4000000 /* 64MB */
 #define MSM_ION_CAMERA_SIZE     MSM_PMEM_ADSP_SIZE
 #define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
 #define MSM_ION_MM_SIZE		0x3600000 /* (54MB) */
@@ -9572,7 +9572,7 @@
 #ifdef CONFIG_FB_MSM_MIPI_DSI
 int mdp_core_clk_rate_table[] = {
 	85330000,
-	85330000,
+	128000000,
 	160000000,
 	200000000,
 };
@@ -9586,7 +9586,7 @@
 #else
 int mdp_core_clk_rate_table[] = {
 	59080000,
-	85330000,
+	128000000,
 	128000000,
 	200000000,
 };
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 1222b67..0427632 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -684,6 +684,10 @@
 	&asoc_msm_dai1,
 };
 
+static struct platform_device *qrd3_devices[] __initdata = {
+	&msm_device_nand,
+};
+
 static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE;
 static int __init pmem_kernel_ebi1_size_setup(char *p)
 {
@@ -1016,6 +1020,16 @@
 	return platform_device_register(&msm_wlan_ar6000_pm_device);
 }
 
+static void add_platform_devices(void)
+{
+	platform_add_devices(qrd_common_devices,
+			ARRAY_SIZE(qrd_common_devices));
+
+	if (machine_is_msm7627a_qrd3())
+		platform_add_devices(qrd3_devices,
+				ARRAY_SIZE(qrd3_devices));
+}
+
 #define UART1DM_RX_GPIO		45
 static void __init msm_qrd_init(void)
 {
@@ -1035,8 +1049,7 @@
 	msm_device_gadget_peripheral.dev.platform_data =
 		&msm_gadget_pdata;
 
-	platform_add_devices(qrd_common_devices,
-			ARRAY_SIZE(qrd_common_devices));
+	add_platform_devices();
 
 	/* Ensure ar6000pm device is registered before MMC/SDC */
 	msm_qrd_init_ar6000pm();
@@ -1075,6 +1088,16 @@
 	.init_early	= qrd7627a_init_early,
 	.handle_irq	= vic_handle_irq,
 MACHINE_END
+MACHINE_START(MSM7627A_QRD3, "QRD MSM7627a QRD3")
+	.boot_params	= PHYS_OFFSET + 0x100,
+	.map_io		= msm_common_io_init,
+	.reserve	= msm7627a_reserve,
+	.init_irq	= msm_init_irq,
+	.init_machine	= msm_qrd_init,
+	.timer		= &msm_timer,
+	.init_early	= qrd7627a_init_early,
+	.handle_irq	= vic_handle_irq,
+MACHINE_END
 MACHINE_START(MSM7627A_EVB, "QRD MSM7627a EVB")
 	.boot_params	= PHYS_OFFSET + 0x100,
 	.map_io		= msm_common_io_init,
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 47e51a3..493a210 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -44,6 +44,7 @@
 #define ADM0_PBUS_CLK_CTL_REG			REG(0x2208)
 #define CE1_HCLK_CTL_REG			REG(0x2720)
 #define CE1_CORE_CLK_CTL_REG			REG(0x2724)
+#define PRNG_CLK_NS_REG				REG(0x2E80)
 #define CE3_HCLK_CTL_REG			REG(0x36C4)
 #define CE3_CORE_CLK_CTL_REG			REG(0x36CC)
 #define CE3_CLK_SRC_NS_REG			REG(0x36C0)
@@ -4846,45 +4847,46 @@
 	CLK_LOOKUP("pll4",		pll4_clk.c,	NULL),
 	CLK_LOOKUP("measure",		measure_clk.c,	"debug"),
 
-	CLK_DUMMY("bus_clk",		AFAB_CLK,	"msm_apps_fab", 0),
-	CLK_DUMMY("bus_a_clk",		AFAB_A_CLK,	"msm_apps_fab", 0),
-	CLK_DUMMY("bus_clk",		SFAB_CLK,	"msm_sys_fab", 0),
-	CLK_DUMMY("bus_a_clk",		SFAB_A_CLK,	"msm_sys_fab", 0),
-	CLK_DUMMY("bus_clk",		SFPB_CLK,	"msm_sys_fpb", 0),
-	CLK_DUMMY("bus_a_clk",		SFPB_A_CLK,	"msm_sys_fpb", 0),
-	CLK_DUMMY("bus_clk",		MMFAB_CLK,	"msm_mm_fab", 0),
-	CLK_DUMMY("bus_a_clk",		MMFAB_A_CLK,	"msm_mm_fab", 0),
-	CLK_DUMMY("bus_clk",		CFPB_CLK,	"msm_cpss_fpb", 0),
-	CLK_DUMMY("bus_a_clk",		CFPB_A_CLK,	"msm_cpss_fpb", 0),
-	CLK_LOOKUP("mem_clk",		ebi1_msmbus_clk.c, "msm_bus"),
-	CLK_DUMMY("mem_a_clk",		EBI1_A_CLK,        "msm_bus", 0),
+	CLK_LOOKUP("bus_clk",		afab_clk.c,		"msm_apps_fab"),
+	CLK_LOOKUP("bus_a_clk",		afab_a_clk.c,		"msm_apps_fab"),
+	CLK_LOOKUP("bus_clk",		cfpb_clk.c,		"msm_cpss_fpb"),
+	CLK_LOOKUP("bus_a_clk",		cfpb_a_clk.c,		"msm_cpss_fpb"),
+	CLK_LOOKUP("bus_clk",		sfab_clk.c,		"msm_sys_fab"),
+	CLK_LOOKUP("bus_a_clk",		sfab_a_clk.c,		"msm_sys_fab"),
+	CLK_LOOKUP("bus_clk",		sfpb_clk.c,		"msm_sys_fpb"),
+	CLK_LOOKUP("bus_a_clk",		sfpb_a_clk.c,		"msm_sys_fpb"),
+	CLK_LOOKUP("bus_clk",		mmfab_clk.c,		"msm_mm_fab"),
+	CLK_LOOKUP("bus_a_clk",		mmfab_a_clk.c,		"msm_mm_fab"),
+	CLK_LOOKUP("mem_clk",		ebi1_msmbus_clk.c,	"msm_bus"),
+	CLK_LOOKUP("mem_a_clk",		ebi1_a_clk.c,		"msm_bus"),
 
-	CLK_DUMMY("ebi1_clk",		EBI1_CLK,	NULL, 0),
-	CLK_DUMMY("dfab_clk",		DFAB_CLK,	NULL, 0),
-	CLK_DUMMY("dfab_a_clk",		DFAB_A_CLK,	NULL, 0),
-	CLK_DUMMY("bus_clk",		MMFPB_CLK,	NULL, 0),
-	CLK_DUMMY("bus_a_clk",		MMFPB_A_CLK,	NULL, 0),
+	CLK_LOOKUP("ebi1_clk",		ebi1_clk.c,		""),
+	CLK_LOOKUP("dfab_clk",		dfab_clk.c,		""),
+	CLK_LOOKUP("dfab_a_clk",	dfab_a_clk.c,		""),
+	CLK_LOOKUP("mmfpb_clk",		mmfpb_clk.c,		""),
+	CLK_LOOKUP("mmfpb_a_clk",	mmfpb_a_clk.c,		"clock-8960"),
+	CLK_LOOKUP("cfpb_a_clk",	cfpb_a_clk.c,		"clock-8960"),
 
 	CLK_LOOKUP("core_clk",		gp0_clk.c,		""),
 	CLK_LOOKUP("core_clk",		gp1_clk.c,		""),
 	CLK_LOOKUP("core_clk",		gp2_clk.c,		""),
-	CLK_LOOKUP("core_clk",		gsbi1_uart_clk.c, "msm_serial_hsl.0"),
+	CLK_LOOKUP("core_clk",		gsbi1_uart_clk.c, "msm_serial_hsl.1"),
 	CLK_LOOKUP("core_clk",		gsbi2_uart_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi3_uart_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi4_uart_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi5_uart_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi6_uart_clk.c,	""),
-	CLK_LOOKUP("core_clk",		gsbi7_uart_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi7_uart_clk.c, "msm_serial_hsl.0"),
 	CLK_LOOKUP("core_clk",		gsbi1_qup_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi2_qup_clk.c,	""),
-	CLK_LOOKUP("core_clk",		gsbi3_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi3_qup_clk.c,	"qup_i2c.3"),
 	CLK_LOOKUP("core_clk",		gsbi4_qup_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi5_qup_clk.c,	"spi_qsd.0"),
 	CLK_LOOKUP("core_clk",		gsbi6_qup_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi7_qup_clk.c,	""),
 	CLK_LOOKUP("core_clk",		pdm_clk.c,		""),
 	CLK_LOOKUP("mem_clk",		pmem_clk.c,		"msm_sps"),
-	CLK_DUMMY("core_clk",           PRNG_CLK,	"msm_rng.0", OFF),
+	CLK_LOOKUP("core_clk",          prng_clk.c,		"msm_rng.0"),
 	CLK_LOOKUP("core_clk",		sdc1_clk.c,		"msm_sdcc.1"),
 	CLK_LOOKUP("core_clk",		sdc2_clk.c,		"msm_sdcc.2"),
 	CLK_LOOKUP("core_clk",		sdc3_clk.c,		"msm_sdcc.3"),
@@ -4908,13 +4910,13 @@
 	CLK_LOOKUP("ce3_core_src_clk",	ce3_src_clk.c,		"qce.0"),
 	CLK_LOOKUP("ce3_core_src_clk",	ce3_src_clk.c,		"qcrypto.0"),
 	CLK_LOOKUP("dma_bam_pclk",	dma_bam_p_clk.c,	NULL),
-	CLK_LOOKUP("iface_clk",		gsbi1_p_clk.c,	"msm_serial_hsl.0"),
+	CLK_LOOKUP("iface_clk",		gsbi1_p_clk.c,	"msm_serial_hsl.1"),
 	CLK_LOOKUP("iface_clk",		gsbi2_p_clk.c,		""),
-	CLK_LOOKUP("iface_clk",		gsbi3_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		gsbi3_p_clk.c,		"qup_i2c.3"),
 	CLK_LOOKUP("iface_clk",		gsbi4_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		gsbi5_p_clk.c,		"spi_qsd.0"),
 	CLK_LOOKUP("iface_clk",		gsbi6_p_clk.c,		""),
-	CLK_LOOKUP("iface_clk",		gsbi7_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		gsbi7_p_clk.c,	"msm_serial_hsl.0"),
 	CLK_LOOKUP("iface_clk",		tsif_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		usb_fs1_p_clk.c,	""),
 	CLK_LOOKUP("iface_clk",		usb_hs1_p_clk.c,	"msm_otg"),
@@ -4958,10 +4960,10 @@
 	CLK_LOOKUP("csiphy_timer_clk",	csi0phy_timer_clk.c,	""),
 	CLK_LOOKUP("csiphy_timer_clk",	csi1phy_timer_clk.c,	""),
 	CLK_LOOKUP("csiphy_timer_clk",	csi2phy_timer_clk.c,	""),
-	CLK_LOOKUP("dsi_byte_div_clk",	dsi1_byte_clk.c,	""),
-	CLK_LOOKUP("dsi_byte_div_clk",	dsi2_byte_clk.c,	""),
-	CLK_LOOKUP("dsi_esc_clk",	dsi1_esc_clk.c,		""),
-	CLK_LOOKUP("dsi_esc_clk",	dsi2_esc_clk.c,		""),
+	CLK_LOOKUP("dsi_byte_div_clk",	dsi1_byte_clk.c,	NULL),
+	CLK_LOOKUP("dsi_byte_div_clk",	dsi2_byte_clk.c,	NULL),
+	CLK_LOOKUP("dsi_esc_clk",	dsi1_esc_clk.c,		NULL),
+	CLK_LOOKUP("dsi_esc_clk",	dsi2_esc_clk.c,		NULL),
 	CLK_DUMMY("rgb_tv_clk",		RGB_TV_CLK,		"", OFF),
 	CLK_DUMMY("npl_tv_clk",		NPL_TV_CLK,		"", OFF),
 	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	"kgsl-3d0.0"),
@@ -4978,18 +4980,18 @@
 	CLK_LOOKUP("ijpeg_clk",         ijpeg_clk.c,            ""),
 	CLK_LOOKUP("core_clk",		ijpeg_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("core_clk",		jpegd_clk.c,		""),
-	CLK_LOOKUP("mdp_clk",		mdp_clk.c,		""),
+	CLK_LOOKUP("mdp_clk",		mdp_clk.c,		NULL),
 	CLK_LOOKUP("core_clk",		mdp_clk.c,	 "footswitch-8x60.4"),
-	CLK_LOOKUP("mdp_vsync_clk",	mdp_vsync_clk.c,	""),
+	CLK_LOOKUP("mdp_vsync_clk",	mdp_vsync_clk.c,	NULL),
 	CLK_LOOKUP("vsync_clk",		mdp_vsync_clk.c, "footswitch-8x60.4"),
-	CLK_LOOKUP("lut_mdp",		lut_mdp_clk.c,		""),
+	CLK_LOOKUP("lut_mdp",		lut_mdp_clk.c,		NULL),
 	CLK_LOOKUP("lut_clk",		lut_mdp_clk.c,	"footswitch-8x60.4"),
 	CLK_LOOKUP("core_clk",		rot_clk.c,	"msm_rotator.0"),
 	CLK_LOOKUP("core_clk",		rot_clk.c,	"footswitch-8x60.6"),
-	CLK_DUMMY("tv_src_clk",		TV_SRC_CLK,		"", OFF),
+	CLK_DUMMY("tv_src_clk",		TV_SRC_CLK,		NULL, OFF),
 	CLK_LOOKUP("core_clk",		vcodec_clk.c,		"msm_vidc.0"),
 	CLK_LOOKUP("core_clk",		vcodec_clk.c,	"footswitch-8x60.7"),
-	CLK_DUMMY("mdp_tv_clk",		MDP_TV_CLK,		"", OFF),
+	CLK_DUMMY("mdp_tv_clk",		MDP_TV_CLK,		NULL, OFF),
 	CLK_DUMMY("tv_clk",		MDP_TV_CLK, "footswitch-8x60.4", OFF),
 	CLK_DUMMY("hdmi_clk",		HDMI_TV_CLK,		"", OFF),
 	CLK_LOOKUP("core_clk",		hdmi_app_clk.c,		""),
@@ -5005,12 +5007,12 @@
 	CLK_LOOKUP("bus_a_clk",        vcodec_axi_a_clk.c, "footswitch-8x60.7"),
 	CLK_LOOKUP("bus_b_clk",        vcodec_axi_b_clk.c, "footswitch-8x60.7"),
 	CLK_LOOKUP("bus_clk",		vpe_axi_clk.c,	"footswitch-8x60.9"),
-	CLK_LOOKUP("amp_pclk",		amp_p_clk.c,		""),
+	CLK_LOOKUP("amp_pclk",		amp_p_clk.c,		NULL),
 	CLK_LOOKUP("csi_pclk",		csi_p_clk.c,		""),
-	CLK_LOOKUP("dsi_m_pclk",	dsi1_m_p_clk.c,		""),
-	CLK_LOOKUP("dsi_s_pclk",	dsi1_s_p_clk.c,		""),
-	CLK_LOOKUP("dsi_m_pclk",	dsi2_m_p_clk.c,		""),
-	CLK_LOOKUP("dsi_s_pclk",	dsi2_s_p_clk.c,		""),
+	CLK_LOOKUP("dsi_m_pclk",	dsi1_m_p_clk.c,		NULL),
+	CLK_LOOKUP("dsi_s_pclk",	dsi1_s_p_clk.c,		NULL),
+	CLK_LOOKUP("dsi_m_pclk",	dsi2_m_p_clk.c,		NULL),
+	CLK_LOOKUP("dsi_s_pclk",	dsi2_s_p_clk.c,		NULL),
 	CLK_LOOKUP("iface_clk",		gfx3d_p_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("iface_clk",		gfx3d_p_clk.c,	"footswitch-8x60.2"),
 	CLK_LOOKUP("master_iface_clk",	hdmi_m_p_clk.c,		""),
@@ -5019,7 +5021,7 @@
 	CLK_LOOKUP("iface_clk",		ijpeg_p_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("iface_clk",		jpegd_p_clk.c,		""),
 	CLK_LOOKUP("mem_iface_clk",	imem_p_clk.c,	"kgsl-3d0.0"),
-	CLK_LOOKUP("mdp_pclk",		mdp_p_clk.c,		""),
+	CLK_LOOKUP("mdp_pclk",		mdp_p_clk.c,		NULL),
 	CLK_LOOKUP("iface_clk",		mdp_p_clk.c,	"footswitch-8x60.4"),
 	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,		"msm_iommu"),
 	CLK_LOOKUP("iface_clk",		rot_p_clk.c,	"msm_rotator.0"),
@@ -5030,6 +5032,7 @@
 	CLK_LOOKUP("iface_clk",		vfe_p_clk.c,	"footswitch-8x60.8"),
 	CLK_LOOKUP("vpe_pclk",		vpe_p_clk.c,		""),
 	CLK_LOOKUP("iface_pclk",	vpe_p_clk.c,	"footswitch-8x60.9"),
+
 	CLK_LOOKUP("mi2s_bit_clk",	mi2s_bit_clk.c,		""),
 	CLK_LOOKUP("mi2s_osr_clk",	mi2s_osr_clk.c,		""),
 	CLK_LOOKUP("i2s_mic_bit_clk",	codec_i2s_mic_bit_clk.c, ""),
@@ -5053,16 +5056,19 @@
 	CLK_LOOKUP("core_clk",		vcodec_axi_a_clk.c,	""),
 	CLK_LOOKUP("core_clk",		vcodec_axi_b_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gfx3d_axi_clk.c,	""),
-	CLK_DUMMY("dfab_dsps_clk",	DFAB_DSPS_CLK,		"", 0),
-	CLK_DUMMY("core_clk",		DFAB_USB_HS_CLK,  "msm_otg", 0),
-	CLK_DUMMY("core_clk",		DFAB_USB_HS3_CLK, "msm_ehci_host.0", 0),
-	CLK_DUMMY("core_clk",		DFAB_USB_HS4_CLK, "msm_ehci_host.1", 0),
-	CLK_DUMMY("bus_clk",		DFAB_SDC1_CLK,		"", 0),
-	CLK_DUMMY("bus_clk",		DFAB_SDC2_CLK,		"", 0),
-	CLK_DUMMY("bus_clk",		DFAB_SDC3_CLK,		"", 0),
-	CLK_DUMMY("bus_clk",		DFAB_SDC4_CLK,		"", 0),
-	CLK_DUMMY("dfab_clk",		DFAB_CLK,		"", 0),
-	CLK_DUMMY("bus_clk",		DFAB_SCM_CLK,	"scm", 0),
+
+	CLK_LOOKUP("dfab_dsps_clk",	dfab_dsps_clk.c, NULL),
+	CLK_LOOKUP("core_clk",		dfab_usb_hs_clk.c,	"msm_otg"),
+	CLK_LOOKUP("core_clk",		dfab_usb_hs3_clk.c, "msm_ehci_host.0"),
+	CLK_LOOKUP("core_clk",		dfab_usb_hs3_clk.c, "msm_ehci_host.1"),
+	CLK_LOOKUP("bus_clk",		dfab_sdc1_clk.c, "msm_sdcc.1"),
+	CLK_LOOKUP("bus_clk",		dfab_sdc2_clk.c, "msm_sdcc.2"),
+	CLK_LOOKUP("bus_clk",		dfab_sdc3_clk.c, "msm_sdcc.3"),
+	CLK_LOOKUP("bus_clk",		dfab_sdc4_clk.c, "msm_sdcc.4"),
+	CLK_LOOKUP("dfab_clk",		dfab_sps_clk.c,	"msm_sps"),
+	CLK_LOOKUP("bus_clk",		dfab_bam_dmux_clk.c,	"BAM_RMNT"),
+	CLK_LOOKUP("bus_clk",		dfab_scm_clk.c,	"scm"),
+
 	CLK_LOOKUP("alt_core_clk",    usb_hsic_xcvr_fs_clk.c,  "msm_hsic_host"),
 	CLK_LOOKUP("phy_clk",	      usb_hsic_hsic_clk.c,     "msm_hsic_host"),
 	CLK_LOOKUP("cal_clk",	      usb_hsic_hsio_cal_clk.c, "msm_hsic_host"),
@@ -5211,6 +5217,7 @@
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-006c"),
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-0048"),
 	CLK_LOOKUP("cam_clk",		cam2_clk.c,		NULL),
+	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-0020"),
 	CLK_LOOKUP("csi_src_clk",	csi0_src_clk.c,		"msm_csid.0"),
 	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		"msm_csid.1"),
 	CLK_LOOKUP("csi_clk",		csi0_clk.c,		"msm_csid.0"),
@@ -5243,7 +5250,7 @@
 	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	"footswitch-8x60.2"),
 	CLK_LOOKUP("bus_clk",		ijpeg_axi_clk.c, "footswitch-8x60.3"),
-	CLK_LOOKUP("mem_clk",		imem_axi_clk.c,		""),
+	CLK_LOOKUP("imem_clk",		imem_axi_clk.c,		NULL),
 	CLK_LOOKUP("ijpeg_clk",         ijpeg_clk.c,            NULL),
 	CLK_LOOKUP("core_clk",		ijpeg_clk.c,	"footswitch-8x60.3"),
 	CLK_LOOKUP("core_clk",		jpegd_clk.c,		""),
@@ -5534,134 +5541,38 @@
 		rmwreg(0, SATA_PHY_REF_CLK_CTL_REG, 0x1);
 
 	/*
-	 * TODO: Programming below PLLs is temporary and needs to be removed
-	 *       after bootloaders program them.
+	 * TODO: Programming below PLLs and prng_clk is temporary and
+	 *	 needs to be removed after bootloaders program them.
 	 */
 	if (cpu_is_apq8064()) {
-		u32 regval, is_pll_enabled;
+		u32 is_pll_enabled;
 
 		/* Program pxo_src_clk to source from PXO */
 		rmwreg(0x1, PXO_SRC_CLK_CTL_REG, 0x7);
 
-		/* Check if PLL8 is active */
-		is_pll_enabled = readl_relaxed(BB_PLL8_STATUS_REG) & BIT(16);
-		if (!is_pll_enabled) {
-			/* Ref clk = 27MHz and program pll8 to 384MHz */
-			writel_relaxed(0xE, BB_PLL8_L_VAL_REG);
-			writel_relaxed(0x2, BB_PLL8_M_VAL_REG);
-			writel_relaxed(0x9, BB_PLL8_N_VAL_REG);
-
-			regval = readl_relaxed(BB_PLL8_CONFIG_REG);
-
-			/* Enable the main output and the MN accumulator */
-			regval |= BIT(23) | BIT(22);
-
-			/* Set pre-divider and post-divider values to 1 and 1 */
-			regval &= ~BIT(19);
-			regval &= ~BM(21, 20);
-
-			writel_relaxed(regval, BB_PLL8_CONFIG_REG);
-
-			/* Set VCO frequency */
-			rmwreg(0x10000, BB_PLL8_CONFIG_REG, 0x30000);
-
-			/* Enable AUX output */
-			regval = readl_relaxed(BB_PLL8_TEST_CTL_REG);
-			regval |= BIT(12);
-			writel_relaxed(regval, BB_PLL8_TEST_CTL_REG);
-
-			set_fsm_mode(BB_PLL8_MODE_REG);
-
-			/* Enable PLL8 by voting from RPM */
-			regval = readl_relaxed(BB_PLL_ENA_RPM_REG);
-			regval |= BIT(8);
-			writel_relaxed(regval, BB_PLL_ENA_RPM_REG);
-		}
-		/* Check if PLL3 is active */
-		is_pll_enabled = readl_relaxed(GPLL1_STATUS_REG) & BIT(16);
-		if (!is_pll_enabled) {
-			/* Ref clk = 27MHz and program pll3 to 1200MHz */
-			writel_relaxed(0x2C, GPLL1_L_VAL_REG);
-			writel_relaxed(0x4,  GPLL1_M_VAL_REG);
-			writel_relaxed(0x9,  GPLL1_N_VAL_REG);
-
-			regval = readl_relaxed(GPLL1_CONFIG_REG);
-
-			/* Set pre-divider and post-divider values to 1 and 1 */
-			regval &= ~BIT(15);
-			regval |= BIT(16);
-
-			writel_relaxed(regval, GPLL1_CONFIG_REG);
-
-			/* Set VCO frequency */
-			rmwreg(0x180, GPLL1_CONFIG_REG, 0x180);
-		}
 		/* Check if PLL14 is active */
 		is_pll_enabled = readl_relaxed(BB_PLL14_STATUS_REG) & BIT(16);
 		if (!is_pll_enabled) {
 			/* Ref clk = 27MHz and program pll14 to 480MHz */
-			writel_relaxed(0x11, BB_PLL14_L_VAL_REG);
+			writel_relaxed(0x00031011, BB_PLL14_L_VAL_REG);
 			writel_relaxed(0x7,  BB_PLL14_M_VAL_REG);
 			writel_relaxed(0x9,  BB_PLL14_N_VAL_REG);
 
-			regval = readl_relaxed(BB_PLL14_CONFIG_REG);
-
-			/* Enable the main output and the MN accumulator */
-			regval |= BIT(23) | BIT(22);
-
-			/* Set pre-divider and post-divider values to 1 and 1 */
-			regval &= ~BIT(19);
-			regval &= ~BM(21, 20);
-
-			writel_relaxed(regval, BB_PLL14_CONFIG_REG);
-
-			/* Set VCO frequency */
-			rmwreg(0x10000, BB_PLL14_CONFIG_REG, 0x30000);
+			/*
+			 * Enable the main output and the MN accumulator
+			 * Set pre-divider and post-divider values to 1 and 1
+			 */
+			writel_relaxed(0x00C00000, BB_PLL14_CONFIG_REG);
 
 			set_fsm_mode(BB_PLL14_MODE_REG);
 		}
-		/* Program PLL2 to 800MHz with ref clk = 27MHz */
-		writel_relaxed(0x1D, MM_PLL1_L_VAL_REG);
-		writel_relaxed(0x11, MM_PLL1_M_VAL_REG);
-		writel_relaxed(0x1B, MM_PLL1_N_VAL_REG);
-
-		regval = readl_relaxed(MM_PLL1_CONFIG_REG);
-
-		/* Enable the main output and the MN accumulator */
-		regval |= BIT(23) | BIT(22);
-
-		/* Set pre-divider and post-divider values to 1 and 1 */
-		regval &= ~BIT(19);
-		regval &= ~BM(21, 20);
-
-		writel_relaxed(regval, MM_PLL1_CONFIG_REG);
-
-		/* Set VCO frequency */
-		rmwreg(0x20000, MM_PLL1_CONFIG_REG, 0x30000);
 
 		/* Program PLL15 to 975MHz with ref clk = 27MHz */
-		writel_relaxed(0x24, MM_PLL3_L_VAL_REG);
-		writel_relaxed(0x1,  MM_PLL3_M_VAL_REG);
-		writel_relaxed(0x9,  MM_PLL3_N_VAL_REG);
+		writel_relaxed(0x31024, MM_PLL3_L_VAL_REG);
+		writel_relaxed(0x1,	MM_PLL3_M_VAL_REG);
+		writel_relaxed(0x9,	MM_PLL3_N_VAL_REG);
 
-		regval = readl_relaxed(MM_PLL3_CONFIG_REG);
-
-		/* Enable the main output and the MN accumulator */
-		regval |= BIT(23) | BIT(22);
-
-		/* Set pre-divider and post-divider values to 1 and 1 */
-		regval &= ~BIT(19);
-		regval &= ~BM(21, 20);
-
-		writel_relaxed(regval, MM_PLL3_CONFIG_REG);
-
-		/* Set VCO frequency */
-		rmwreg(0x20000, MM_PLL3_CONFIG_REG, 0x30000);
-
-		/* Enable AUX output */
-		regval = readl_relaxed(MM_PLL3_TEST_CTL_REG);
-		regval |= BIT(12);
-		writel_relaxed(regval, MM_PLL3_TEST_CTL_REG);
+		writel_relaxed(0xC20000, MM_PLL3_CONFIG_REG);
 
 		/* Check if PLL4 is active */
 		is_pll_enabled = readl_relaxed(LCC_PLL0_STATUS_REG) & BIT(16);
@@ -5671,30 +5582,27 @@
 			writel_relaxed(0x27A, LCC_PLL0_M_VAL_REG);
 			writel_relaxed(0x465, LCC_PLL0_N_VAL_REG);
 
-			regval = readl_relaxed(LCC_PLL0_CONFIG_REG);
-
-			/* Enable the main output and the MN accumulator */
-			regval |= BIT(23) | BIT(22);
-
-			/* Set pre-divider and post-divider values to 1 and 1 */
-			regval &= ~BIT(19);
-			regval &= ~BM(21, 20);
-
-			/* Set VCO frequency */
-			regval &= ~BM(17, 16);
-			writel_relaxed(regval, LCC_PLL0_CONFIG_REG);
+			writel_relaxed(0xC00000, LCC_PLL0_CONFIG_REG);
 
 			set_fsm_mode(LCC_PLL0_MODE_REG);
 		}
 
 		/* Enable PLL4 source on the LPASS Primary PLL Mux */
 		writel_relaxed(0x1, LCC_PRI_PLL_CLK_CTL_REG);
+
+		/* Program prng_clk to 64MHz if it isn't configured */
+		if (!readl_relaxed(PRNG_CLK_NS_REG))
+			writel_relaxed(0x2B, PRNG_CLK_NS_REG);
 	}
 }
 
 /* Local clock driver initialization. */
 static void __init msm8960_clock_init(void)
 {
+	/* Copy gfx2d's frequency table because it's modified by both clocks */
+	gfx2d1_clk.freq_tbl = kmemdup(clk_tbl_gfx2d,
+			sizeof(struct clk_freq_tbl) * ARRAY_SIZE(clk_tbl_gfx2d),
+			GFP_KERNEL);
 
 	if (cpu_is_msm8960()) {
 		rpm_vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3;
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 043cdbc..e53d441 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3900,6 +3900,11 @@
 	}
 
 	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+	/* Copy gfx2d's frequency table because it's modified by both clocks */
+	gfx2d1_clk.freq_tbl = kmemdup(clk_tbl_gfx2d,
+			sizeof(struct clk_freq_tbl) * ARRAY_SIZE(clk_tbl_gfx2d),
+			GFP_KERNEL);
+
 	/* Initialize clock registers. */
 	reg_init();
 
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 98d9cb2..ac68d7a 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -384,6 +384,10 @@
 	.enable = rcg_clk_enable,
 	.disable = rcg_clk_disable,
 	.auto_off = rcg_clk_disable,
+	.enable_hwcg = rcg_clk_enable_hwcg,
+	.disable_hwcg = rcg_clk_disable_hwcg,
+	.in_hwcg_mode = rcg_clk_in_hwcg_mode,
+	.handoff = rcg_clk_handoff,
 	.set_rate = rcg_clk_set_rate,
 	.get_rate = rcg_clk_get_rate,
 	.list_rate = rcg_clk_list_rate,
@@ -398,6 +402,10 @@
 	.enable = branch_clk_enable,
 	.disable = branch_clk_disable,
 	.auto_off = branch_clk_disable,
+	.enable_hwcg = branch_clk_enable_hwcg,
+	.disable_hwcg = branch_clk_disable_hwcg,
+	.in_hwcg_mode = branch_clk_in_hwcg_mode,
+	.handoff = branch_clk_handoff,
 	.is_enabled = branch_clk_is_enabled,
 	.reset = branch_clk_reset,
 	.is_local = local_clk_is_local,
@@ -595,6 +603,8 @@
 	.b = {
 		.ctl_reg = PMEM_ACLK_CTL_REG,
 		.en_mask = BIT(4),
+		.hwcg_reg =  PMEM_ACLK_CTL_REG,
+		.hwcg_mask = BIT(6),
 		.halt_reg = CLK_HALT_DFAB_STATE_REG,
 		.halt_bit = 20,
 	},
@@ -846,6 +856,8 @@
 	.b = {
 		.ctl_reg = CE1_CORE_CLK_CTL_REG,
 		.en_mask = BIT(4),
+		.hwcg_reg =  CE1_CORE_CLK_CTL_REG,
+		.hwcg_mask = BIT(6),
 		.halt_reg = CLK_HALT_CFPB_STATEC_REG,
 		.halt_bit = 27,
 	},
@@ -957,6 +969,8 @@
 	.b = {
 		.ctl_reg = USB_HS1_HCLK_CTL_REG,
 		.en_mask = BIT(4),
+		.hwcg_reg =  USB_HS1_HCLK_CTL_REG,
+		.hwcg_mask = BIT(6),
 		.halt_reg = CLK_HALT_DFAB_STATE_REG,
 		.halt_bit = 1,
 	},
@@ -971,6 +985,8 @@
 	.b = {
 		.ctl_reg = USB_HSIC_HCLK_CTL_REG,
 		.en_mask = BIT(4),
+		.hwcg_reg =  USB_HSIC_HCLK_CTL_REG,
+		.hwcg_mask = BIT(6),
 		.halt_reg = CLK_HALT_DFAB_STATE_REG,
 		.halt_bit = 3,
 	},
@@ -985,6 +1001,8 @@
 	.b = {
 		.ctl_reg = SDCn_HCLK_CTL_REG(1),
 		.en_mask = BIT(4),
+		.hwcg_reg =  SDCn_HCLK_CTL_REG(1),
+		.hwcg_mask = BIT(6),
 		.halt_reg = CLK_HALT_DFAB_STATE_REG,
 		.halt_bit = 11,
 	},
@@ -999,6 +1017,8 @@
 	.b = {
 		.ctl_reg = SDCn_HCLK_CTL_REG(2),
 		.en_mask = BIT(4),
+		.hwcg_reg =  SDCn_HCLK_CTL_REG(2),
+		.hwcg_mask = BIT(6),
 		.halt_reg = CLK_HALT_DFAB_STATE_REG,
 		.halt_bit = 10,
 	},
@@ -1807,22 +1827,13 @@
 	regval = readl_relaxed(LCC_PRI_PLL_CLK_CTL_REG);
 	writel_relaxed(regval | BIT(0), LCC_PRI_PLL_CLK_CTL_REG);
 
-	/* Disable hardware clock gating on certain clocks */
-	regval = readl_relaxed(USB_HSIC_HCLK_CTL_REG);
+	/*
+	 * Disable hardware clock gating for pmem_clk. Leaving it enabled
+	 * results in the clock staying on.
+	 */
+	regval = readl_relaxed(PMEM_ACLK_CTL_REG);
 	regval &= ~BIT(6);
-	writel_relaxed(regval, USB_HSIC_HCLK_CTL_REG);
-
-	regval = readl_relaxed(CE1_CORE_CLK_CTL_REG);
-	regval &= ~BIT(6);
-	writel_relaxed(regval, CE1_CORE_CLK_CTL_REG);
-
-	regval = readl_relaxed(USB_HS1_HCLK_CTL_REG);
-	regval &= ~BIT(6);
-	writel_relaxed(regval, USB_HS1_HCLK_CTL_REG);
-
-	regval = readl_relaxed(DMA_BAM_HCLK_CTL);
-	regval &= ~BIT(6);
-	writel_relaxed(regval, DMA_BAM_HCLK_CTL);
+	writel_relaxed(regval, PMEM_ACLK_CTL_REG);
 }
 
 /* Local clock driver initialization. */
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 8ea344b..d312f24 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -106,7 +106,6 @@
 	const uint32_t	ns_val;
 	const uint32_t	ctl_val;
 	uint32_t	mnd_en_mask;
-	const unsigned	sys_vdd;
 	void		*const extra_freq_data;
 };
 
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 81d01c2..56778e2 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -173,6 +173,14 @@
 	struct cpufreq_work_struct *cpu_work = NULL;
 #endif
 
+	/*
+	 * In 8625 both cpu core's frequency can not
+	 * be changed independently. Each cpu is bound to
+	 * same frequency. Hence set the cpumask to all cpu.
+	 */
+	if (cpu_is_msm8625())
+		cpumask_setall(policy->cpus);
+
 	table = cpufreq_frequency_get_table(policy->cpu);
 	if (table == NULL)
 		return -ENODEV;
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index faa9498..9328143 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -28,6 +28,7 @@
 #include <mach/msm_bus_board.h>
 #include <mach/rpm.h>
 #include <mach/mdm2.h>
+#include <linux/ion.h>
 #include "clock.h"
 #include "devices.h"
 #include "msm_watchdog.h"
@@ -46,6 +47,7 @@
 /* GSBI UART devices */
 #define MSM_UART1DM_PHYS	(MSM_GSBI1_PHYS + 0x10000)
 #define MSM_UART3DM_PHYS	(MSM_GSBI3_PHYS + 0x40000)
+#define MSM_UART7DM_PHYS	(MSM_GSBI7_PHYS + 0x40000)
 
 /* GSBI QUP devices */
 #define MSM_GSBI3_QUP_PHYS	(MSM_GSBI3_PHYS + 0x80000)
@@ -68,6 +70,7 @@
 	.pet_time = 10000,
 	.bark_time = 11000,
 	.has_secure = true,
+	.needs_expired_enable = true,
 };
 
 struct platform_device msm8064_device_watchdog = {
@@ -127,7 +130,7 @@
 
 struct platform_device apq8064_device_uart_gsbi1 = {
 	.name	= "msm_serial_hsl",
-	.id	= 0,
+	.id	= 1,
 	.num_resources	= ARRAY_SIZE(resources_uart_gsbi1),
 	.resource	= resources_uart_gsbi1,
 };
@@ -159,6 +162,46 @@
 	.resource	= resources_uart_gsbi3,
 };
 
+static struct resource resources_qup_i2c_gsbi3[] = {
+	{
+		.name	= "gsbi_qup_i2c_addr",
+		.start	= MSM_GSBI3_PHYS,
+		.end	= MSM_GSBI3_PHYS + 4 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "qup_phys_addr",
+		.start	= MSM_GSBI3_QUP_PHYS,
+		.end	= MSM_GSBI3_QUP_PHYS + MSM_QUP_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "qup_err_intr",
+		.start	= GSBI3_QUP_IRQ,
+		.end	= GSBI3_QUP_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "i2c_clk",
+		.start	= 9,
+		.end	= 9,
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.name	= "i2c_sda",
+		.start	= 8,
+		.end	= 8,
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+struct platform_device apq8064_device_qup_i2c_gsbi3 = {
+	.name		= "qup_i2c",
+	.id		= 3,
+	.num_resources	= ARRAY_SIZE(resources_qup_i2c_gsbi3),
+	.resource	= resources_qup_i2c_gsbi3,
+};
+
 static struct resource resources_qup_i2c_gsbi4[] = {
 	{
 		.name	= "gsbi_qup_i2c_addr",
@@ -215,6 +258,33 @@
 	.resource	= resources_qup_spi_gsbi5,
 };
 
+static struct resource resources_uart_gsbi7[] = {
+	{
+		.start	= GSBI7_UARTDM_IRQ,
+		.end	= GSBI7_UARTDM_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= MSM_UART7DM_PHYS,
+		.end	= MSM_UART7DM_PHYS + PAGE_SIZE - 1,
+		.name	= "uartdm_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MSM_GSBI7_PHYS,
+		.end	= MSM_GSBI7_PHYS + PAGE_SIZE - 1,
+		.name	= "gsbi_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device apq8064_device_uart_gsbi7 = {
+	.name	= "msm_serial_hsl",
+	.id	= 0,
+	.num_resources	= ARRAY_SIZE(resources_uart_gsbi7),
+	.resource	= resources_uart_gsbi7,
+};
+
 struct platform_device apq_pcm = {
 	.name	= "msm-pcm-dsp",
 	.id	= -1,
@@ -353,6 +423,7 @@
 
 #define LPASS_SLIMBUS_PHYS	0x28080000
 #define LPASS_SLIMBUS_BAM_PHYS	0x28084000
+#define LPASS_SLIMBUS_SLEW	(MSM8960_TLMM_PHYS + 0x207C)
 /* Board info for the slimbus slave device */
 static struct resource slimbus_res[] = {
 	{
@@ -368,6 +439,12 @@
 		.name	= "slimbus_bam_physical",
 	},
 	{
+		.start	= LPASS_SLIMBUS_SLEW,
+		.end	= LPASS_SLIMBUS_SLEW + 4 - 1,
+		.flags	= IORESOURCE_MEM,
+		.name	= "slimbus_slew_reg",
+	},
+	{
 		.start	= SLIMBUS0_CORE_EE1_IRQ,
 		.end	= SLIMBUS0_CORE_EE1_IRQ,
 		.flags	= IORESOURCE_IRQ,
@@ -514,6 +591,270 @@
 	},
 };
 
+/* MSM Video core device */
+#ifdef CONFIG_MSM_BUS_SCALING
+static struct msm_bus_vectors vidc_init_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 0,
+		.ib  = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_VIDEO_DEC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 0,
+		.ib  = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = 0,
+	},
+};
+static struct msm_bus_vectors vidc_venc_vga_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 54525952,
+		.ib  = 436207616,
+	},
+	{
+		.src = MSM_BUS_MASTER_VIDEO_DEC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 72351744,
+		.ib  = 289406976,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 500000,
+		.ib  = 1000000,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 500000,
+		.ib  = 1000000,
+	},
+};
+static struct msm_bus_vectors vidc_vdec_vga_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 40894464,
+		.ib  = 327155712,
+	},
+	{
+		.src = MSM_BUS_MASTER_VIDEO_DEC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 48234496,
+		.ib  = 192937984,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 500000,
+		.ib  = 2000000,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 500000,
+		.ib  = 2000000,
+	},
+};
+static struct msm_bus_vectors vidc_venc_720p_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 163577856,
+		.ib  = 1308622848,
+	},
+	{
+		.src = MSM_BUS_MASTER_VIDEO_DEC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 219152384,
+		.ib  = 876609536,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 1750000,
+		.ib  = 3500000,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 1750000,
+		.ib  = 3500000,
+	},
+};
+static struct msm_bus_vectors vidc_vdec_720p_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 121634816,
+		.ib  = 973078528,
+	},
+	{
+		.src = MSM_BUS_MASTER_VIDEO_DEC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 155189248,
+		.ib  = 620756992,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 1750000,
+		.ib  = 7000000,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 1750000,
+		.ib  = 7000000,
+	},
+};
+static struct msm_bus_vectors vidc_venc_1080p_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 372244480,
+		.ib  = 2560000000U,
+	},
+	{
+		.src = MSM_BUS_MASTER_VIDEO_DEC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 501219328,
+		.ib  = 2560000000U,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 2500000,
+		.ib  = 5000000,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 2500000,
+		.ib  = 5000000,
+	},
+};
+static struct msm_bus_vectors vidc_vdec_1080p_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 222298112,
+		.ib  = 2560000000U,
+	},
+	{
+		.src = MSM_BUS_MASTER_VIDEO_DEC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 330301440,
+		.ib  = 2560000000U,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 2500000,
+		.ib  = 700000000,
+	},
+	{
+		.src = MSM_BUS_MASTER_AMPSS_M0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 2500000,
+		.ib  = 10000000,
+	},
+};
+
+static struct msm_bus_paths vidc_bus_client_config[] = {
+	{
+		ARRAY_SIZE(vidc_init_vectors),
+		vidc_init_vectors,
+	},
+	{
+		ARRAY_SIZE(vidc_venc_vga_vectors),
+		vidc_venc_vga_vectors,
+	},
+	{
+		ARRAY_SIZE(vidc_vdec_vga_vectors),
+		vidc_vdec_vga_vectors,
+	},
+	{
+		ARRAY_SIZE(vidc_venc_720p_vectors),
+		vidc_venc_720p_vectors,
+	},
+	{
+		ARRAY_SIZE(vidc_vdec_720p_vectors),
+		vidc_vdec_720p_vectors,
+	},
+	{
+		ARRAY_SIZE(vidc_venc_1080p_vectors),
+		vidc_venc_1080p_vectors,
+	},
+	{
+		ARRAY_SIZE(vidc_vdec_1080p_vectors),
+		vidc_vdec_1080p_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata vidc_bus_client_data = {
+	vidc_bus_client_config,
+	ARRAY_SIZE(vidc_bus_client_config),
+	.name = "vidc",
+};
+#endif
+
+
+#define APQ8064_VIDC_BASE_PHYS 0x04400000
+#define APQ8064_VIDC_BASE_SIZE 0x00100000
+
+static struct resource apq8064_device_vidc_resources[] = {
+	{
+		.start	= APQ8064_VIDC_BASE_PHYS,
+		.end	= APQ8064_VIDC_BASE_PHYS + APQ8064_VIDC_BASE_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= VCODEC_IRQ,
+		.end	= VCODEC_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct msm_vidc_platform_data apq8064_vidc_platform_data = {
+#ifdef CONFIG_MSM_BUS_SCALING
+	.vidc_bus_client_pdata = &vidc_bus_client_data,
+#endif
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	.memtype = ION_CP_MM_HEAP_ID,
+	.enable_ion = 1,
+#else
+	.memtype = MEMTYPE_EBI1,
+	.enable_ion = 0,
+#endif
+	.disable_dmx = 0,
+	.disable_fullhd = 0,
+};
+
+struct platform_device apq8064_msm_device_vidc = {
+	.name = "msm_vidc",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(apq8064_device_vidc_resources),
+	.resource = apq8064_device_vidc_resources,
+	.dev = {
+		.platform_data	= &apq8064_vidc_platform_data,
+	},
+};
 #define MSM_SDC1_BASE         0x12400000
 #define MSM_SDC1_DML_BASE     (MSM_SDC1_BASE + 0x800)
 #define MSM_SDC1_BAM_BASE     (MSM_SDC1_BASE + 0x2000)
@@ -856,7 +1197,7 @@
 	CLK_DUMMY("core_clk",		GSBI1_UART_CLK,		NULL, OFF),
 	CLK_DUMMY("core_clk",		GSBI2_UART_CLK,		NULL, OFF),
 	CLK_DUMMY("core_clk",		GSBI3_UART_CLK,
-						  "msm_serial_hsl.0", OFF),
+								NULL, OFF),
 	CLK_DUMMY("core_clk",		GSBI4_UART_CLK,		NULL, OFF),
 	CLK_DUMMY("core_clk",		GSBI5_UART_CLK,		NULL, OFF),
 	CLK_DUMMY("core_clk",		GSBI6_UART_CLK,		NULL, OFF),
@@ -868,7 +1209,7 @@
 	CLK_DUMMY("core_clk",		GSBI12_UART_CLK,	NULL, OFF),
 	CLK_DUMMY("core_clk",		GSBI1_QUP_CLK,		NULL, OFF),
 	CLK_DUMMY("core_clk",		GSBI2_QUP_CLK,		NULL, OFF),
-	CLK_DUMMY("core_clk",		GSBI3_QUP_CLK,		NULL, OFF),
+	CLK_DUMMY("core_clk",		GSBI3_QUP_CLK,   "qup_i2c.3", OFF),
 	CLK_DUMMY("core_clk",		GSBI4_QUP_CLK,   "qup_i2c.4", OFF),
 	CLK_DUMMY("core_clk",		GSBI5_QUP_CLK,	 "spi_qsd.0", OFF),
 	CLK_DUMMY("core_clk",		GSBI6_QUP_CLK,		NULL, OFF),
@@ -900,7 +1241,7 @@
 	CLK_DUMMY("ref_clk",		SATA_PHY_REF_CLK,       NULL, OFF),
 	CLK_DUMMY("iface_clk",		GSBI1_P_CLK,		NULL, OFF),
 	CLK_DUMMY("iface_clk",		GSBI2_P_CLK,		NULL, OFF),
-	CLK_DUMMY("iface_clk",		GSBI3_P_CLK, "msm_serial_hsl.0", OFF),
+	CLK_DUMMY("iface_clk",		GSBI3_P_CLK,	 "qup_i2c.3", OFF),
 	CLK_DUMMY("iface_clk",		GSBI4_P_CLK,	 "qup_i2c.4", OFF),
 	CLK_DUMMY("iface_clk",		GSBI5_P_CLK,	 "spi_qsd.0", OFF),
 	CLK_DUMMY("iface_clk",		GSBI6_P_CLK,		NULL, OFF),
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 872d9d4..4525bab 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1389,6 +1389,11 @@
 	.id	= -1,
 };
 
+struct platform_device msm_multi_ch_pcm = {
+	.name	= "msm-multi-ch-pcm-dsp",
+	.id	= -1,
+};
+
 struct platform_device msm_pcm_routing = {
 	.name	= "msm-pcm-routing",
 	.id	= -1,
@@ -1405,7 +1410,7 @@
 };
 
 struct platform_device msm_cpudai_hdmi_rx = {
-	.name	= "msm-dai-q6",
+	.name	= "msm-dai-q6-hdmi",
 	.id	= 8,
 };
 
@@ -1658,7 +1663,7 @@
 };
 #endif
 
-static struct platform_device msm_lvds_device = {
+struct platform_device msm_lvds_device = {
 	.name   = "lvds",
 	.id     = 0,
 };
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 1f2256f..3944a93 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -1116,12 +1116,6 @@
 	msm_mpm_irq_extn_init(data);
 	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
 						(void *)MSM_QGIC_CPU_BASE);
-
-	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-	writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
-	writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-	mb();
 }
 
 struct platform_device msm_bus_9615_sys_fabric = {
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index f3a95a6..31eee43 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -866,6 +866,24 @@
 	.resource	= gsbi0_msm8625_qup_resources,
 };
 
+static struct resource msm8625_gpio_resources[] = {
+	{
+		.start	= MSM8625_INT_GPIO_GROUP1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= MSM8625_INT_GPIO_GROUP2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device msm8625_device_gpio = {
+	.name		= "msmgpio",
+	.id		= -1,
+	.resource	= msm8625_gpio_resources,
+	.num_resources	= ARRAY_SIZE(msm8625_gpio_resources),
+};
+
 static struct clk_lookup msm_clock_8625_dummy[] = {
 	CLK_DUMMY("core_clk",		adm_clk.c,	"msm_dmov", 0),
 	CLK_DUMMY("adsp_clk",		adsp_clk.c,	NULL, 0),
@@ -987,13 +1005,6 @@
 {
 	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
 			(void *)MSM_QGIC_CPU_BASE);
-
-	/* Edge trigger PPIs
-	 */
-	writel_relaxed(0x555555F5, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
-	writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-	mb();
 }
 
 void __init msm8625_map_io(void)
@@ -1007,7 +1018,10 @@
 
 static int msm7627a_init_gpio(void)
 {
-	platform_device_register(&msm_device_gpio);
+	if (cpu_is_msm8625())
+		platform_device_register(&msm8625_device_gpio);
+	else
+		platform_device_register(&msm_device_gpio);
 	return 0;
 }
 postcore_initcall(msm7627a_init_gpio);
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index db656f3..fc732da 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -581,9 +581,67 @@
 	},
 };
 
+static struct resource smd_resource[] = {
+	{
+		.name   = "a9_m2a_0",
+		.start  = INT_A9_M2A_0,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "a9_m2a_5",
+		.start  = INT_A9_M2A_5,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "adsp_a11_smsm",
+		.start  = INT_ADSP_A11,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct smd_subsystem_config smd_config_list[] = {
+	{
+		.irq_config_id = SMD_MODEM,
+		.subsys_name = "modem",
+		.edge = SMD_APPS_MODEM,
+
+		.smd_int.irq_name = "a9_m2a_0",
+		.smd_int.flags = IRQF_TRIGGER_RISING,
+		.smd_int.irq_id = -1,
+		.smd_int.device_name = "smd_dev",
+		.smd_int.dev_id = 0,
+
+		.smd_int.out_bit_pos =  1 << 0,
+		.smd_int.out_base = (void __iomem *)MSM_GCC_BASE,
+		.smd_int.out_offset = 0x8,
+
+		.smsm_int.irq_name = "a9_m2a_5",
+		.smsm_int.flags = IRQF_TRIGGER_RISING,
+		.smsm_int.irq_id = -1,
+		.smsm_int.device_name = "smd_dev",
+		.smsm_int.dev_id = 0,
+
+		.smsm_int.out_bit_pos =  1 << 5,
+		.smsm_int.out_base = (void __iomem *)MSM_GCC_BASE,
+		.smsm_int.out_offset = 0x8,
+
+	}
+};
+
+static struct smd_platform smd_platform_data = {
+	.num_ss_configs = ARRAY_SIZE(smd_config_list),
+	.smd_ss_configs = smd_config_list,
+};
+
 struct platform_device msm_device_smd = {
 	.name	= "msm_smd",
 	.id	= -1,
+	.resource = smd_resource,
+	.num_resources = ARRAY_SIZE(smd_resource),
+	.dev = {
+		.platform_data = &smd_platform_data,
+	}
+
 };
 
 static struct resource msm_dmov_resource[] = {
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index a433a89..4670ce8 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -179,9 +179,6 @@
 
 	msm_mpm_irq_extn_init(data);
 	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE, (void *)MSM_QGIC_CPU_BASE);
-
-	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-	writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
 }
 
 #define MSM_LPASS_QDSP6SS_PHYS 0x28800000
diff --git a/arch/arm/mach-msm/devices-msm8x60.h b/arch/arm/mach-msm/devices-msm8x60.h
index a2f6a1f..9bfaeee 100644
--- a/arch/arm/mach-msm/devices-msm8x60.h
+++ b/arch/arm/mach-msm/devices-msm8x60.h
@@ -56,6 +56,7 @@
 extern struct platform_device msm_device_smd;
 extern struct platform_device msm_device_gpio;
 extern struct platform_device msm_device_vidc;
+extern struct platform_device apq8064_msm_device_vidc;
 
 extern struct platform_device msm_charm_modem;
 extern struct platform_device msm_device_tz_log;
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 9469de8..c4f57ab 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -69,6 +69,8 @@
 
 extern struct platform_device apq8064_device_uart_gsbi1;
 extern struct platform_device apq8064_device_uart_gsbi3;
+extern struct platform_device apq8064_device_uart_gsbi7;
+extern struct platform_device apq8064_device_qup_i2c_gsbi3;
 extern struct platform_device apq8064_device_qup_i2c_gsbi4;
 extern struct platform_device apq8064_device_qup_spi_gsbi5;
 extern struct platform_device apq8064_slim_ctrl;
@@ -162,6 +164,7 @@
 extern struct platform_device msm_device_vidc_720p;
 
 extern struct platform_device msm_pcm;
+extern struct platform_device msm_multi_ch_pcm;
 extern struct platform_device msm_pcm_routing;
 extern struct platform_device msm_cpudai0;
 extern struct platform_device msm_cpudai1;
@@ -234,6 +237,7 @@
 extern struct platform_device msm_kgsl_2d1;
 
 extern struct platform_device msm_mipi_dsi1_device;
+extern struct platform_device msm_lvds_device;
 
 extern struct clk_lookup msm_clocks_fsm9xxx[];
 extern unsigned msm_num_clocks_fsm9xxx;
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index 296c111..5c10463 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.c
@@ -623,7 +623,7 @@
 	init_data = pdev->dev.platform_data;
 
 	if (pdev->id == FS_MDP) {
-		if (cpu_is_msm8960() || cpu_is_msm8930())
+		if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_apq8064())
 			fs->clk_data = mdp_8960_clks;
 		else if (cpu_is_msm8x60())
 			fs->clk_data = mdp_8660_clks;
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 631d5200..c274899 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -106,12 +106,6 @@
 	sub	r1, r1, r0
 	bl	v7_flush_kern_dcache_area
 
-	mrc     p15, 0, r4, c1, c0, 0    /* read current CR    */
-	bic     r0, r4, #(1 << 2)        /* clear dcache bit   */
-	bic     r0, r0, #(1 << 12)       /* clear icache bit   */
-	mcr     p15, 0, r0, c1, c0, 0    /* disable d/i cache  */
-
-	dsb
 #ifdef CONFIG_ARCH_MSM_KRAIT
 	ldr	r0, =SCM_SVC_BOOT
 	ldr	r1, =SCM_CMD_TERMINATE_PC
@@ -119,10 +113,18 @@
 	ldr	r2, [r2]
 	bl	scm_call_atomic1
 #else
+	mrc     p15, 0, r4, c1, c0, 0    /* read current CR    */
+	bic     r0, r4, #(1 << 2)        /* clear dcache bit   */
+	bic     r0, r0, #(1 << 12)       /* clear icache bit   */
+	mcr     p15, 0, r0, c1, c0, 0    /* disable d/i cache  */
+	dsb
+
 	wfi
-#endif
+
 	mcr     p15, 0, r4, c1, c0, 0    /* restore d/i cache  */
 	isb
+#endif
+
 
 #if defined(CONFIG_MSM_FIQ_SUPPORT)
 	cpsie   f
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 6eceea7..ba9fc70 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -399,6 +399,10 @@
 	char dlane_swap;
 };
 
+struct lvds_panel_platform_data {
+	int *gpio;
+};
+
 struct msm_fb_platform_data {
 	int (*detect_client)(const char *name);
 	int mddi_prescan;
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index bb33289..530d2c1 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -213,6 +213,7 @@
 #define CSI_DECODE_6BIT 0
 #define CSI_DECODE_8BIT 1
 #define CSI_DECODE_10BIT 2
+#define CSI_DECODE_DPCM_10_8_10 5
 
 struct msm_vfe_phy_info {
 	uint32_t sbuf_phy;
@@ -576,6 +577,7 @@
 	CAMIO_CSI0_PHY_CLK,
 	CAMIO_CSI1_PHY_CLK,
 	CAMIO_CSIPHY_TIMER_SRC_CLK,
+	CAMIO_IMEM_CLK,
 
 	CAMIO_MAX_CLK
 };
diff --git a/arch/arm/mach-msm/include/mach/msm_bus_board.h b/arch/arm/mach-msm/include/mach/msm_bus_board.h
index 1a87d9c..fd61c98 100644
--- a/arch/arm/mach-msm/include/mach/msm_bus_board.h
+++ b/arch/arm/mach-msm/include/mach/msm_bus_board.h
@@ -205,7 +205,7 @@
 	MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
 	MSM_BUS_MASTER_VIDEO_ENC,
 	MSM_BUS_MASTER_VIDEO_DEC,
-	MSM_BUS_MASTER_LAST = MSM_BUS_MMSS_MASTER_UNUSED_2,
+	MSM_BUS_MASTER_LAST = MSM_BUS_MASTER_VIDEO_DEC,
 
 	MSM_BUS_SYSTEM_FPB_MASTER_SYSTEM =
 		MSM_BUS_SYSTEM_MASTER_SYSTEM_FPB,
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
index 562a305..57e794f 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,6 +13,15 @@
 #ifndef __MSM_HDMI_AUDIO_H
 #define __MSM_HDMI_AUDIO_H
 
+/* Supported HDMI Audio channels */
+#define MSM_HDMI_AUDIO_CHANNEL_2		0
+#define MSM_HDMI_AUDIO_CHANNEL_4		1
+#define MSM_HDMI_AUDIO_CHANNEL_6		2
+#define MSM_HDMI_AUDIO_CHANNEL_8		3
+
+#define TRUE   1
+#define FALSE  0
+
 enum hdmi_supported_sample_rates {
 	HDMI_SAMPLE_RATE_32KHZ,
 	HDMI_SAMPLE_RATE_44_1KHZ,
@@ -27,5 +36,7 @@
 int hdmi_audio_packet_enable(bool on);
 void hdmi_msm_audio_sample_rate_reset(int rate);
 int hdmi_msm_audio_get_sample_rate(void);
+int hdmi_msm_audio_info_setup(bool enabled, u32 num_of_channels,
+	u32 channel_allocation, u32 level_shift, bool down_mix);
 
 #endif /* __MSM_HDMI_AUDIO_H*/
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h b/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h
index 88bc3c6..4c26d08 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h
@@ -44,9 +44,6 @@
 #define MSM7XXX_TMR_PHYS          MSM7XXX_CSR_PHYS
 #define MSM7XXX_TMR_SIZE          SZ_4K
 
-#define MSM7XXX_TMR0_PHYS         0xC0800000
-#define MSM7XXX_TMR0_SIZE         SZ_4K
-
 #define MSM7XXX_GPIO1_PHYS        0xA9200000
 #define MSM7XXX_GPIO1_SIZE        SZ_4K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index ca8daaa..d53910d 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -47,9 +47,7 @@
 
 #if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064) || \
 	defined(CONFIG_ARCH_MSM8930) || defined(CONFIG_ARCH_MSM9615) || \
-	defined(CONFIG_ARCH_MSMCOPPER) || defined(CONFIG_ARCH_MSM7X27) || \
-	defined(CONFIG_ARCH_MSM7X01A) || defined(CONFIG_ARCH_MSM7X25) || \
-	defined(CONFIG_ARCH_MSM8625)
+	defined(CONFIG_ARCH_MSMCOPPER)
 
 /* Unified iomap */
 
@@ -82,21 +80,8 @@
 #define MSM_APCS_GLB_BASE	IOMEM(0xFA702000)	/*  4K  */
 #define MSM_SAW2_BASE		IOMEM(0xFA703000)	/*  4k  */
 #define MSM_SAW3_BASE		IOMEM(0xFA704000)	/*  4k  */
-#define MSM_VIC_BASE		IOMEM(0xFA705000)	/* 4K */
-#define MSM_CSR_BASE		MSM_TMR_BASE		/* 4K */
-#define MSM_GPIO1_BASE		IOMEM(0xFA706000)	/* 4K */
-#define MSM_GPIO2_BASE		IOMEM(0xFA707000)	/* 4K */
-#define MSM_SCU_BASE		IOMEM(0xFA708000)	/* 4K */
-#define MSM_SPM0_BASE		IOMEM(0xFA709000)	/* 4K */
-#define MSM_SPM1_BASE		IOMEM(0xFA70A000)	/* 4K */
-#define MSM_CFG_CTL_BASE	IOMEM(0xFA70B000)	/* 4K */
-#define MSM_MDC_BASE		IOMEM(0xFA70C000)	/* 4K */
-#define MSM_AD5_BASE		IOMEM(0xFA70D000)	/* 4K */
 
-
-#define MSM_STRONGLY_ORDERED_PAGE	0xFA0F0000
-
-#if defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_MSM7X27)
+#if defined(CONFIG_ARCH_MSM9615)
 #define MSM_SHARED_RAM_SIZE	SZ_1M
 #else
 #define MSM_SHARED_RAM_SIZE	SZ_2M
@@ -107,8 +92,6 @@
 #include "msm_iomap-8064.h"
 #include "msm_iomap-9615.h"
 #include "msm_iomap-copper.h"
-#include "msm_iomap-7xxx.h"
-#include "msm_iomap-8625.h"
 
 #else
 /* Legacy single-target iomap */
@@ -122,7 +105,29 @@
 #elif defined(CONFIG_ARCH_FSM9XXX)
 #include "msm_iomap-fsm9xxx.h"
 #else
-#error "Target compiling without iomap"
+#define MSM_VIC_BASE			IOMEM(0xFA000000)	/* 4K */
+#define MSM_CSR_BASE			IOMEM(0xFA001000)	/* 4K */
+#define MSM_TMR_BASE			MSM_CSR_BASE		/* 4K */
+#define MSM_TMR0_BASE			IOMEM(0xFA002000)	/* 4K */
+#define MSM_GPIO1_BASE			IOMEM(0xFA003000)	/* 4K */
+#define MSM_GPIO2_BASE			IOMEM(0xFA004000)	/* 4K */
+#define MSM_CLK_CTL_BASE		IOMEM(0xFA005000)	/* 4K */
+#define MSM_L2CC_BASE			IOMEM(0xFA006000)	/* 4K */
+#define MSM_QGIC_DIST_BASE		IOMEM(0xFA007000)	/* 4K */
+#define MSM_QGIC_CPU_BASE		IOMEM(0xFA008000)	/* 4K */
+#define MSM_SCU_BASE			IOMEM(0xFA009000)	/* 4K */
+#define MSM_SPM0_BASE			IOMEM(0xFA00A000)	/* 4K */
+#define MSM_SPM1_BASE			IOMEM(0xFA00B000)	/* 4K */
+#define MSM_CFG_CTL_BASE		IOMEM(0xFA00C000)	/* 4K */
+#define MSM_SHARED_RAM_BASE		IOMEM(0xFA100000)	/* 4K */
+#define MSM_MDC_BASE			IOMEM(0xFA200000)	/* 4K */
+#define MSM_AD5_BASE			IOMEM(0xFA300000)	/* 4K */
+#define MSM_STRONGLY_ORDERED_PAGE	0xFA0F0000
+#define MSM8625_SECONDARY_PHYS		0x0FE00000
+#define MSM_SHARED_RAM_SIZE		SZ_1M
+
+#include "msm_iomap-7xxx.h"
+#include "msm_iomap-8625.h"
 #endif
 
 #if defined(CONFIG_DEBUG_MSM_UART1)
diff --git a/arch/arm/mach-msm/include/mach/msm_rtb.h b/arch/arm/mach-msm/include/mach/msm_rtb.h
index a24e892..ac45cbd 100644
--- a/arch/arm/mach-msm/include/mach/msm_rtb.h
+++ b/arch/arm/mach-msm/include/mach/msm_rtb.h
@@ -17,6 +17,7 @@
 	LOGK_NONE = 0,
 	LOGK_READL,
 	LOGK_WRITEL,
+	LOGK_LOGBUF,
 	LOGK_OTHER,
 };
 
diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h
index af47425..4be6d9ea 100644
--- a/arch/arm/mach-msm/include/mach/msm_smd.h
+++ b/arch/arm/mach-msm/include/mach/msm_smd.h
@@ -1,7 +1,7 @@
 /* linux/include/asm-arm/arch-msm/msm_smd.h
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -18,6 +18,9 @@
 #ifndef __ASM_ARCH_MSM_SMD_H
 #define __ASM_ARCH_MSM_SMD_H
 
+#include <linux/io.h>
+#include <mach/msm_smsm.h>
+
 typedef struct smd_channel smd_channel_t;
 
 #define SMD_MAX_CH_NAME_LEN 20 /* includes null char at end */
@@ -28,6 +31,24 @@
 #define SMD_EVENT_STATUS 4
 #define SMD_EVENT_REOPEN_READY 5
 
+/*
+ * SMD Processor ID's.
+ *
+ * For all processors that have both SMSM and SMD clients,
+ * the SMSM Processor ID and the SMD Processor ID will
+ * be the same.  In cases where a processor only supports
+ * SMD, the entry will only exist in this enum.
+ */
+enum {
+	SMD_APPS = SMSM_APPS,
+	SMD_MODEM = SMSM_MODEM,
+	SMD_Q6 = SMSM_Q6,
+	SMD_WCNSS = SMSM_WCNSS,
+	SMD_DSPS = SMSM_DSPS,
+	SMD_MODEM_Q6_FW,
+	NUM_SMD_SUBSYSTEMS,
+};
+
 enum {
 	SMD_APPS_MODEM = 0,
 	SMD_APPS_QDSP,
@@ -49,6 +70,59 @@
 
 };
 
+/*
+ * SMD IRQ Configuration
+ *
+ * Used to initialize IRQ configurations from platform data
+ *
+ * @irq_name: irq_name to query platform data
+ * @irq_id: initialized to -1 in platform data, stores actual irq id on
+ *		successful registration
+ * @out_base: if not null then settings used for outgoing interrupt
+ *		initialied from platform data
+ */
+
+struct smd_irq_config {
+	/* incoming interrupt config */
+	const char *irq_name;
+	unsigned long flags;
+	int irq_id;
+	const char *device_name;
+	const void *dev_id;
+
+	/* outgoing interrupt config */
+	uint32_t out_bit_pos;
+	void __iomem *out_base;
+	uint32_t out_offset;
+};
+
+/*
+ * SMD subsystem configurations
+ *
+ * SMD subsystems configurations for platform data. This contains the
+ * M2A and A2M interrupt configurations for both SMD and SMSM per
+ * subsystem.
+ *
+ * @subsys_name: name of subsystem passed to PIL
+ * @irq_config_id: unique id for each subsystem
+ * @edge: maps to actual remote subsystem edge
+ *
+ */
+struct smd_subsystem_config {
+	unsigned irq_config_id;
+	const char *subsys_name;
+	int edge;
+
+	struct smd_irq_config smd_int;
+	struct smd_irq_config smsm_int;
+
+};
+
+struct smd_platform {
+	uint32_t num_ss_configs;
+	struct smd_subsystem_config *smd_ss_configs;
+};
+
 #ifdef CONFIG_MSM_SMD
 /* warning: notify() may be called before open returns */
 int smd_open(const char *name, smd_channel_t **ch, void *priv,
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator.h b/arch/arm/mach-msm/include/mach/rpm-regulator.h
index 0d113ac..f8f4c87 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator.h
@@ -163,6 +163,10 @@
  *
  * Consumers can vote to disable a regulator with this function by passing
  * min_uV = 0 and max_uV = 0.
+ *
+ * Voltage switch type regulators may be controlled via rpm_vreg_set_voltage
+ * as well.  For this type of regulator, max_uV > 0 is treated as an enable
+ * request and max_uV == 0 is treated as a disable request.
  */
 int rpm_vreg_set_voltage(int vreg_id, enum rpm_vreg_voter voter, int min_uV,
 			 int max_uV, int sleep_also);
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index 600a2e91..c856455 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -43,123 +43,10 @@
 	char *name;
 	int  domain;
 } msm_iommu_ctx_names[] = {
-	/* Camera */
-	{
-		.name = "vpe_src",
-		.domain = GLOBAL_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vpe_dst",
-		.domain = GLOBAL_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_imgwr",
-		.domain = GLOBAL_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_misc",
-		.domain = GLOBAL_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name =	"ijpeg_src",
-		.domain = GLOBAL_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name =	"ijpeg_dst",
-		.domain = GLOBAL_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "jpegd_src",
-		.domain = GLOBAL_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "jpegd_dst",
-		.domain = GLOBAL_DOMAIN,
-	},
-	/* Display */
-	{
-		.name = "mdp_vg1",
-		.domain = GLOBAL_DOMAIN,
-	},
-	/* Display */
-	{
-		.name = "mdp_vg2",
-		.domain = GLOBAL_DOMAIN,
-	},
-	/* Display */
-	{
-		.name = "mdp_rgb1",
-		.domain = GLOBAL_DOMAIN,
-	},
-	/* Display */
-	{
-		.name = "mdp_rgb2",
-		.domain = GLOBAL_DOMAIN,
-	},
-	/* Rotator */
-	{
-		.name = "rot_src",
-		.domain = GLOBAL_DOMAIN,
-	},
-	/* Rotator */
-	{
-		.name = "rot_dst",
-		.domain = GLOBAL_DOMAIN,
-	},
-	/* Video */
-	{
-		.name = "vcodec_a_mm1",
-		.domain = GLOBAL_DOMAIN,
-	},
-	/* Video */
-	{
-		.name = "vcodec_b_mm2",
-		.domain = GLOBAL_DOMAIN,
-	},
-	/* Video */
-	{
-		.name = "vcodec_a_stream",
-		.domain = GLOBAL_DOMAIN,
-	},
-};
-
-static struct mem_pool global_pools[] =  {
-	[VIDEO_FIRMWARE_POOL] =
-	/* Low addresses, intended for video firmware */
-		{
-			.paddr	= SZ_128K,
-			.size	= SZ_16M - SZ_128K,
-		},
-	[LOW_256MB_POOL] =
-	/*
-	 * Video can only access first 256MB of memory
-	 * dedicated pool for such allocations
-	 */
-		{
-			.paddr	= SZ_16M,
-			.size	= SZ_256M - SZ_16M,
-		},
-	[HIGH_POOL] =
-	/* Remaining address space up to 2G */
-		{
-			.paddr	= SZ_256M,
-			.size	= SZ_2G - SZ_256M,
-		}
 };
 
 
 static struct msm_iommu_domain msm_iommu_domains[] = {
-	[GLOBAL_DOMAIN] = {
-		.iova_pools = global_pools,
-		.npools = ARRAY_SIZE(global_pools),
-	}
 };
 
 int msm_iommu_map_extra(struct iommu_domain *domain,
@@ -281,10 +168,8 @@
 
 int msm_use_iommu()
 {
-	/*
-	 * For now, just detect if the iommu is attached.
-	 */
-	return iommu_found();
+	/* Kill use of the iommu by these clients for now. */
+	return 0;
 }
 
 static int __init msm_subsystem_iommu_init(void)
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index 4b0d26a..6e8c99e 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -53,7 +53,7 @@
 	/* Load GNSS for Standalone 8064 but not for Fusion 3 */
 	if (cpu_is_apq8064()) {
 		if (socinfo_get_platform_subtype() == 0x0)
-			pil = pil_get("gnss");
+			pil = pil_get("gss");
 	} else {
 		pil = pil_get("modem");
 	}
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index b672957..7445a61 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -455,6 +455,11 @@
 	mdm_drv->mdm_status_irq = irq;
 
 status_err:
+	/* Perform early powerup of the external modem in order to
+	 * allow tabla devices to be found.
+	 */
+	mdm_drv->ops->power_on_mdm_cb(mdm_drv);
+
 	pr_info("%s: Registering mdm modem\n", __func__);
 	return misc_register(&mdm_modem_misc);
 
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 46695c4..3b064ff 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -315,7 +315,12 @@
 		return 0;
 
 	mb = &meminfo.bank[meminfo.nr_banks - 1];
-	fmem_phys = mb->start + (mb->size - fmem_size);
+	/*
+	 * Placing fmem at the top of memory causes multimedia issues.
+	 * Instead, place it 1 page below the top of memory to prevent
+	 * the issues from occurring.
+	 */
+	fmem_phys = mb->start + (mb->size - fmem_size) - PAGE_SIZE;
 	ret = memblock_remove(fmem_phys, fmem_size);
 	BUG_ON(ret);
 
diff --git a/arch/arm/mach-msm/msm_rtb.c b/arch/arm/mach-msm/msm_rtb.c
index d765f6a..f93a79b 100644
--- a/arch/arm/mach-msm/msm_rtb.c
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -65,6 +65,7 @@
 
 struct msm_rtb_state msm_rtb = {
 	.size = SZ_1M,
+	.filter = 1 << LOGK_LOGBUF,
 };
 
 module_param_named(filter, msm_rtb.filter, uint, 0644);
diff --git a/arch/arm/mach-msm/msm_watchdog.c b/arch/arm/mach-msm/msm_watchdog.c
index 5877fbf..5bff832 100644
--- a/arch/arm/mach-msm/msm_watchdog.c
+++ b/arch/arm/mach-msm/msm_watchdog.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -354,7 +354,7 @@
 		return ret;
 	}
 
-	enable_percpu_irq(WDT0_ACCSCSSNBARK_INT, 0);
+	enable_percpu_irq(WDT0_ACCSCSSNBARK_INT, IRQ_TYPE_EDGE_RISING);
 
 	/*
 	 * This is only temporary till SBLs turn on the XPUs
@@ -363,6 +363,9 @@
 	if (cpu_is_msm9615())
 		__raw_writel(0xF, MSM_TCSR_BASE + TCSR_WDT_CFG);
 
+	if (pdata->needs_expired_enable)
+		__raw_writel(0x1, MSM_CLK_CTL_BASE + 0x3820);
+
 	configure_bark_dump();
 
 	delay_time = msecs_to_jiffies(pdata->pet_time);
diff --git a/arch/arm/mach-msm/msm_watchdog.h b/arch/arm/mach-msm/msm_watchdog.h
index 201c2b1..33e9e0c 100644
--- a/arch/arm/mach-msm/msm_watchdog.h
+++ b/arch/arm/mach-msm/msm_watchdog.h
@@ -19,6 +19,7 @@
 	/* bark timeout in ms */
 	unsigned int bark_time;
 	bool has_secure;
+	bool needs_expired_enable;
 };
 
 #ifdef CONFIG_MSM_WATCHDOG
diff --git a/arch/arm/mach-msm/msm_xo.c b/arch/arm/mach-msm/msm_xo.c
index af272af..74c64c1 100644
--- a/arch/arm/mach-msm/msm_xo.c
+++ b/arch/arm/mach-msm/msm_xo.c
@@ -115,7 +115,7 @@
 static int msm_xo_update_vote(struct msm_xo *xo)
 {
 	int ret;
-	unsigned vote, prev_vote = xo->mode;
+	unsigned vote, prev_vote = xo->mode, ctx_set;
 	struct msm_rpm_iv_pair cmd;
 
 	if (xo->votes[MSM_XO_MODE_ON])
@@ -141,7 +141,11 @@
 	} else if (xo == &msm_xo_sources[MSM_XO_CXO]) {
 		cmd.id = MSM_RPM_ID_CXO_CLK;
 		cmd.value = msm_xo_sources[MSM_XO_CXO].mode ? 1 : 0;
-		ret = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &cmd, 1);
+		if (cpu_is_msm9615())
+			ctx_set = MSM_RPM_CTX_SET_SLEEP;
+		else
+			ctx_set = MSM_RPM_CTX_SET_0;
+		ret = msm_rpmrs_set_noirq(ctx_set, &cmd, 1);
 	} else {
 		cmd.id = MSM_RPM_ID_CXO_BUFFERS;
 		cmd.value = (msm_xo_sources[MSM_XO_TCXO_D0].mode << 0)  |
@@ -235,10 +239,9 @@
 
 	/*
 	 * TODO: Remove early return for 8064 once RPM XO voting support
-	 * is available. Remove early return for 8960 CXO once all voters
-	 * for it are in place.
+	 * is available.
 	 */
-	if (cpu_is_apq8064() || (cpu_is_msm8960() && xo_id == MSM_XO_CXO))
+	if (cpu_is_apq8064())
 		return NULL;
 
 	if (xo_id >= NUM_MSM_XO_IDS) {
@@ -304,12 +307,25 @@
 int __init msm_xo_init(void)
 {
 	int i;
-	int ret;
+	int ret = 0;
 	struct msm_rpm_iv_pair cmd[2];
 
 	for (i = 0; i < ARRAY_SIZE(msm_xo_sources); i++)
 		INIT_LIST_HEAD(&msm_xo_sources[i].voters);
 
+	if (cpu_is_msm9615()) {
+		cmd[0].id = MSM_RPM_ID_CXO_CLK;
+		cmd[0].value = 1;
+		ret = msm_rpmrs_set(MSM_RPM_CTX_SET_0, cmd, 1);
+		if (ret)
+			goto out;
+
+		cmd[0].id = MSM_RPM_ID_CXO_CLK;
+		cmd[0].value = 0;
+		ret = msm_rpmrs_set(MSM_RPM_CTX_SET_SLEEP, cmd, 1);
+		goto out;
+	}
+
 	cmd[0].id = MSM_RPM_ID_PXO_CLK;
 	cmd[0].value = 1;
 	cmd[1].id = MSM_RPM_ID_CXO_BUFFERS;
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 0886975..1004e01 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -288,14 +288,10 @@
 
 	mutex_lock(&pil->lock);
 	WARN(!pil->count, "%s: Reference count mismatch\n", __func__);
-	/* TODO: Peripheral shutdown support */
-	if (pil->count == 1)
-		goto unlock;
 	if (pil->count)
 		pil->count--;
 	if (pil->count == 0)
 		pil->desc->ops->shutdown(pil->desc);
-unlock:
 	mutex_unlock(&pil->lock);
 
 	pil_d = find_peripheral(pil->desc->depends_on);
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index f3e83d9e..6ec9b5d7 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -257,6 +257,49 @@
 	.shutdown = pil_gss_shutdown,
 };
 
+static int pil_gss_init_image_trusted(struct pil_desc *pil,
+		const u8 *metadata, size_t size)
+{
+	return pas_init_image(PAS_GSS, metadata, size);
+}
+
+static int pil_gss_reset_trusted(struct pil_desc *pil)
+{
+	struct gss_data *drv = dev_get_drvdata(pil->dev);
+	int err;
+
+	err = make_gss_proxy_votes(pil->dev);
+	if (err)
+		return err;
+
+	err =  pas_auth_and_reset(PAS_GSS);
+	if (err)
+		remove_gss_proxy_votes_now(drv);
+
+	return err;
+}
+
+static int pil_gss_shutdown_trusted(struct pil_desc *pil)
+{
+	struct gss_data *drv = dev_get_drvdata(pil->dev);
+	int ret;
+
+	ret = pas_shutdown(PAS_GSS);
+	if (ret)
+		return ret;
+
+	remove_gss_proxy_votes_now(drv);
+
+	return ret;
+}
+
+static struct pil_reset_ops pil_gss_ops_trusted = {
+	.init_image = pil_gss_init_image_trusted,
+	.verify_blob = nop_verify_blob,
+	.auth_and_reset = pil_gss_reset_trusted,
+	.shutdown = pil_gss_shutdown_trusted,
+};
+
 static void configure_gss_pll(struct gss_data *drv)
 {
 	u32 regval, is_pll_enabled;
@@ -354,8 +397,13 @@
 	desc->name = "gss";
 	desc->dev = &pdev->dev;
 
-	desc->ops = &pil_gss_ops;
-	dev_info(&pdev->dev, "using non-secure boot\n");
+	if (pas_supported(PAS_GSS) > 0) {
+		desc->ops = &pil_gss_ops_trusted;
+		dev_info(&pdev->dev, "using secure boot\n");
+	} else {
+		desc->ops = &pil_gss_ops;
+		dev_info(&pdev->dev, "using non-secure boot\n");
+	}
 
 	INIT_DELAYED_WORK(&drv->work, remove_gss_proxy_votes);
 
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index 3c422009..6b48d57 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -198,14 +198,5 @@
 
 	trace_hardirqs_off();
 
-	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-	writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
-	/* RUMI does not adhere to GIC spec by enabling STIs by default.
-	 * Enable/clear is supposed to be RO for STIs, but is RW on RUMI.
-	 */
-	if (!machine_is_msm8x60_sim())
-		writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-
 	gic_secondary_init(0);
 }
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index 4cdd7ae..e1934bb 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -3,7 +3,7 @@
  * MSM Power Management Routines
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012 Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -118,18 +118,6 @@
  * Sleep Modes and Parameters
  *****************************************************************************/
 
-static int msm_pm_sleep_mode = CONFIG_MSM7X00A_SLEEP_MODE;
-module_param_named(
-	sleep_mode, msm_pm_sleep_mode,
-	int, S_IRUGO | S_IWUSR | S_IWGRP
-);
-
-static int msm_pm_idle_sleep_mode = CONFIG_MSM7X00A_IDLE_SLEEP_MODE;
-module_param_named(
-	idle_sleep_mode, msm_pm_idle_sleep_mode,
-	int, S_IRUGO | S_IWUSR | S_IWGRP
-);
-
 static int msm_pm_idle_sleep_min_time = CONFIG_MSM7X00A_IDLE_SLEEP_MIN_TIME;
 module_param_named(
 	idle_sleep_min_time, msm_pm_idle_sleep_min_time,
@@ -166,10 +154,20 @@
 
 static struct msm_pm_platform_data *msm_pm_modes;
 
-static struct kobject *msm_pm_mode_kobjs[MSM_PM_SLEEP_MODE_NR];
-static struct attribute_group *msm_pm_mode_attr_group[MSM_PM_SLEEP_MODE_NR];
-static struct attribute **msm_pm_mode_attrs[MSM_PM_SLEEP_MODE_NR];
-static struct kobj_attribute *msm_pm_mode_kobj_attrs[MSM_PM_SLEEP_MODE_NR];
+struct msm_pm_kobj_attribute {
+	unsigned int cpu;
+	struct kobj_attribute ka;
+};
+
+#define GET_CPU_OF_ATTR(attr) \
+	(container_of(attr, struct msm_pm_kobj_attribute, ka)->cpu)
+
+struct msm_pm_sysfs_sleep_mode {
+	struct kobject *kobj;
+	struct attribute_group attr_group;
+	struct attribute *attrs[MSM_PM_MODE_ATTR_NR + 1];
+	struct msm_pm_kobj_attribute kas[MSM_PM_MODE_ATTR_NR];
+};
 
 /*
  * Write out the attribute.
@@ -182,6 +180,8 @@
 
 	for (i = 0; i < MSM_PM_SLEEP_MODE_NR; i++) {
 		struct kernel_param kp;
+		unsigned int cpu;
+		struct msm_pm_platform_data *mode;
 
 		if (msm_pm_sleep_mode_labels[i] == NULL)
 			continue;
@@ -189,23 +189,28 @@
 		if (strcmp(kobj->name, msm_pm_sleep_mode_labels[i]))
 			continue;
 
+		cpu = GET_CPU_OF_ATTR(attr);
+		mode = &msm_pm_modes[MSM_PM_MODE(cpu, i)];
+
 		if (!strcmp(attr->attr.name,
 			msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_SUSPEND])) {
-			u32 arg = msm_pm_modes[i].suspend_enabled;
+			u32 arg = mode->suspend_enabled;
 			kp.arg = &arg;
 			ret = param_get_ulong(buf, &kp);
 		} else if (!strcmp(attr->attr.name,
 			msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_IDLE])) {
-			u32 arg = msm_pm_modes[i].idle_enabled;
+			u32 arg = mode->idle_enabled;
 			kp.arg = &arg;
 			ret = param_get_ulong(buf, &kp);
 		} else if (!strcmp(attr->attr.name,
 			msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_LATENCY])) {
-			kp.arg = &msm_pm_modes[i].latency;
+			u32 arg = mode->latency;
+			kp.arg = &arg;
 			ret = param_get_ulong(buf, &kp);
 		} else if (!strcmp(attr->attr.name,
 			msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_RESIDENCY])) {
-			kp.arg = &msm_pm_modes[i].residency;
+			u32 arg = mode->residency;
+			kp.arg = &arg;
 			ret = param_get_ulong(buf, &kp);
 		}
 
@@ -213,7 +218,7 @@
 	}
 
 	if (ret > 0) {
-		strcat(buf, "\n");
+		strlcat(buf, "\n", PAGE_SIZE);
 		ret++;
 	}
 
@@ -231,6 +236,8 @@
 
 	for (i = 0; i < MSM_PM_SLEEP_MODE_NR; i++) {
 		struct kernel_param kp;
+		unsigned int cpu;
+		struct msm_pm_platform_data *mode;
 
 		if (msm_pm_sleep_mode_labels[i] == NULL)
 			continue;
@@ -238,21 +245,24 @@
 		if (strcmp(kobj->name, msm_pm_sleep_mode_labels[i]))
 			continue;
 
+		cpu = GET_CPU_OF_ATTR(attr);
+		mode = &msm_pm_modes[MSM_PM_MODE(cpu, i)];
+
 		if (!strcmp(attr->attr.name,
 			msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_SUSPEND])) {
-			kp.arg = &msm_pm_modes[i].suspend_enabled;
+			kp.arg = &mode->suspend_enabled;
 			ret = param_set_byte(buf, &kp);
 		} else if (!strcmp(attr->attr.name,
 			msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_IDLE])) {
-			kp.arg = &msm_pm_modes[i].idle_enabled;
+			kp.arg = &mode->idle_enabled;
 			ret = param_set_byte(buf, &kp);
 		} else if (!strcmp(attr->attr.name,
 			msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_LATENCY])) {
-			kp.arg = &msm_pm_modes[i].latency;
+			kp.arg = &mode->latency;
 			ret = param_set_ulong(buf, &kp);
 		} else if (!strcmp(attr->attr.name,
 			msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_RESIDENCY])) {
-			kp.arg = &msm_pm_modes[i].residency;
+			kp.arg = &mode->residency;
 			ret = param_set_ulong(buf, &kp);
 		}
 
@@ -262,6 +272,86 @@
 	return ret ? ret : count;
 }
 
+ /* Add sysfs entries for one cpu. */
+static int __init msm_pm_mode_sysfs_add_cpu(
+	unsigned int cpu, struct kobject *modes_kobj)
+{
+	char cpu_name[8];
+	struct kobject *cpu_kobj;
+	struct msm_pm_sysfs_sleep_mode *mode = NULL;
+	int i, j, k;
+	int ret;
+
+	snprintf(cpu_name, sizeof(cpu_name), "cpu%u", cpu);
+	cpu_kobj = kobject_create_and_add(cpu_name, modes_kobj);
+	if (!cpu_kobj) {
+		pr_err("%s: cannot create %s kobject\n", __func__, cpu_name);
+		ret = -ENOMEM;
+		goto mode_sysfs_add_cpu_exit;
+	}
+
+	for (i = 0; i < MSM_PM_SLEEP_MODE_NR; i++) {
+		int idx = MSM_PM_MODE(cpu, i);
+
+		if ((!msm_pm_modes[idx].suspend_supported) &&
+				(!msm_pm_modes[idx].idle_supported))
+			continue;
+
+		mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+		if (!mode) {
+			pr_err("%s: cannot allocate memory for attributes\n",
+				__func__);
+			ret = -ENOMEM;
+			goto mode_sysfs_add_cpu_exit;
+		}
+
+		mode->kobj = kobject_create_and_add(
+				msm_pm_sleep_mode_labels[i], cpu_kobj);
+		if (!mode->kobj) {
+			pr_err("%s: cannot create kobject\n", __func__);
+			ret = -ENOMEM;
+			goto mode_sysfs_add_cpu_exit;
+		}
+
+		for (k = 0, j = 0; k < MSM_PM_MODE_ATTR_NR; k++) {
+			if ((k == MSM_PM_MODE_ATTR_IDLE) &&
+				!msm_pm_modes[idx].idle_supported)
+				continue;
+			if ((k == MSM_PM_MODE_ATTR_SUSPEND) &&
+			     !msm_pm_modes[idx].suspend_supported)
+				continue;
+			mode->kas[j].cpu = cpu;
+			mode->kas[j].ka.attr.mode = 0644;
+			mode->kas[j].ka.show = msm_pm_mode_attr_show;
+			mode->kas[j].ka.store = msm_pm_mode_attr_store;
+			mode->kas[j].ka.attr.name = msm_pm_mode_attr_labels[k];
+			mode->attrs[j] = &mode->kas[j].ka.attr;
+			j++;
+		}
+		mode->attrs[j] = NULL;
+
+		mode->attr_group.attrs = mode->attrs;
+		ret = sysfs_create_group(mode->kobj, &mode->attr_group);
+		if (ret) {
+			printk(KERN_ERR
+				"%s: cannot create kobject attribute group\n",
+				__func__);
+			goto mode_sysfs_add_cpu_exit;
+		}
+	}
+
+	ret = 0;
+
+mode_sysfs_add_cpu_exit:
+	if (ret) {
+		if (mode && mode->kobj)
+			kobject_del(mode->kobj);
+		kfree(mode);
+	}
+
+	return ret;
+}
+
 /*
  * Add sysfs entries for the sleep modes.
  */
@@ -269,13 +359,7 @@
 {
 	struct kobject *module_kobj = NULL;
 	struct kobject *modes_kobj = NULL;
-
-	struct kobject *kobj;
-	struct attribute_group *attr_group;
-	struct attribute **attrs;
-	struct kobj_attribute *kobj_attrs;
-
-	int i, j, k;
+	unsigned int cpu;
 	int ret;
 
 	module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
@@ -283,98 +367,32 @@
 		printk(KERN_ERR "%s: cannot find kobject for module %s\n",
 			__func__, KBUILD_MODNAME);
 		ret = -ENOENT;
-		goto mode_sysfs_add_cleanup;
+		goto mode_sysfs_add_exit;
 	}
 
 	modes_kobj = kobject_create_and_add("modes", module_kobj);
 	if (!modes_kobj) {
 		printk(KERN_ERR "%s: cannot create modes kobject\n", __func__);
 		ret = -ENOMEM;
-		goto mode_sysfs_add_cleanup;
+		goto mode_sysfs_add_exit;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(msm_pm_mode_kobjs); i++) {
-		if (!msm_pm_modes[i].suspend_supported &&
-				!msm_pm_modes[i].idle_supported)
-			continue;
-
-		kobj = kobject_create_and_add(
-				msm_pm_sleep_mode_labels[i], modes_kobj);
-		attr_group = kzalloc(sizeof(*attr_group), GFP_KERNEL);
-		attrs = kzalloc(sizeof(*attrs) * (MSM_PM_MODE_ATTR_NR + 1),
-				GFP_KERNEL);
-		kobj_attrs = kzalloc(sizeof(*kobj_attrs) * MSM_PM_MODE_ATTR_NR,
-				GFP_KERNEL);
-
-		if (!kobj || !attr_group || !attrs || !kobj_attrs) {
-			printk(KERN_ERR
-				"%s: cannot create kobject or attributes\n",
-				__func__);
-			ret = -ENOMEM;
-			goto mode_sysfs_add_abort;
-		}
-
-		for (k = 0, j = 0; k < MSM_PM_MODE_ATTR_NR; k++) {
-			if ((k == MSM_PM_MODE_ATTR_SUSPEND) &&
-				(!msm_pm_modes[i].suspend_supported))
-				continue;
-			if ((k == MSM_PM_MODE_ATTR_IDLE) &&
-				(!msm_pm_modes[i].idle_supported))
-				continue;
-
-			kobj_attrs[j].attr.mode = 0644;
-			kobj_attrs[j].show = msm_pm_mode_attr_show;
-			kobj_attrs[j].store = msm_pm_mode_attr_store;
-			kobj_attrs[j].attr.name = msm_pm_mode_attr_labels[k];
-			attrs[j] = &kobj_attrs[j].attr;
-			j++;
-		}
-		attrs[j] = NULL;
-
-		attr_group->attrs = attrs;
-		ret = sysfs_create_group(kobj, attr_group);
-		if (ret) {
-			printk(KERN_ERR
-				"%s: cannot create kobject attribute group\n",
-				__func__);
-			goto mode_sysfs_add_abort;
-		}
-
-		msm_pm_mode_kobjs[i] = kobj;
-		msm_pm_mode_attr_group[i] = attr_group;
-		msm_pm_mode_attrs[i] = attrs;
-		msm_pm_mode_kobj_attrs[i] = kobj_attrs;
+	for_each_possible_cpu(cpu) {
+		ret = msm_pm_mode_sysfs_add_cpu(cpu, modes_kobj);
+		if (ret)
+			goto mode_sysfs_add_exit;
 	}
 
-	return 0;
+	ret = 0;
 
-mode_sysfs_add_abort:
-	kfree(kobj_attrs);
-	kfree(attrs);
-	kfree(attr_group);
-	kobject_put(kobj);
-
-mode_sysfs_add_cleanup:
-	for (i = ARRAY_SIZE(msm_pm_mode_kobjs) - 1; i >= 0; i--) {
-		if (!msm_pm_mode_kobjs[i])
-			continue;
-
-		sysfs_remove_group(
-			msm_pm_mode_kobjs[i], msm_pm_mode_attr_group[i]);
-
-		kfree(msm_pm_mode_kobj_attrs[i]);
-		kfree(msm_pm_mode_attrs[i]);
-		kfree(msm_pm_mode_attr_group[i]);
-		kobject_put(msm_pm_mode_kobjs[i]);
-	}
-
+mode_sysfs_add_exit:
 	return ret;
 }
 
 void __init msm_pm_set_platform_data(
 	struct msm_pm_platform_data *data, int count)
 {
-	BUG_ON(MSM_PM_SLEEP_MODE_NR != count);
+	BUG_ON(MSM_PM_SLEEP_MODE_NR * num_possible_cpus() > count);
 	msm_pm_modes = data;
 }
 
@@ -674,7 +692,7 @@
 	MSM_PM_STAT_COUNT
 };
 
-static struct msm_pm_time_stats {
+struct msm_pm_time_stats {
 	const char *name;
 	int64_t first_bucket_time;
 	int bucket[CONFIG_MSM_IDLE_STATS_BUCKET_COUNT];
@@ -682,74 +700,37 @@
 	int64_t max_time[CONFIG_MSM_IDLE_STATS_BUCKET_COUNT];
 	int count;
 	int64_t total_time;
-} msm_pm_stats[MSM_PM_STAT_COUNT] = {
-	[MSM_PM_STAT_REQUESTED_IDLE].name = "idle-request",
-	[MSM_PM_STAT_REQUESTED_IDLE].first_bucket_time =
-		CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
-	[MSM_PM_STAT_IDLE_SPIN].name = "idle-spin",
-	[MSM_PM_STAT_IDLE_SPIN].first_bucket_time =
-		CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
-	[MSM_PM_STAT_IDLE_WFI].name = "idle-wfi",
-	[MSM_PM_STAT_IDLE_WFI].first_bucket_time =
-		CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
-	[MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].name =
-		"idle-standalone-power-collapse",
-	[MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].first_bucket_time =
-		CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
-	[MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE].name =
-		"idle-failed-standalone-power-collapse",
-	[MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE].first_bucket_time =
-		CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
-	[MSM_PM_STAT_IDLE_SLEEP].name = "idle-sleep",
-	[MSM_PM_STAT_IDLE_SLEEP].first_bucket_time =
-		CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
-	[MSM_PM_STAT_IDLE_FAILED_SLEEP].name = "idle-failed-sleep",
-	[MSM_PM_STAT_IDLE_FAILED_SLEEP].first_bucket_time =
-		CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
-	[MSM_PM_STAT_IDLE_POWER_COLLAPSE].name = "idle-power-collapse",
-	[MSM_PM_STAT_IDLE_POWER_COLLAPSE].first_bucket_time =
-		CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
-	[MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE].name =
-		"idle-failed-power-collapse",
-	[MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE].first_bucket_time =
-		CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
-	[MSM_PM_STAT_SUSPEND].name = "suspend",
-	[MSM_PM_STAT_SUSPEND].first_bucket_time =
-		CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET,
-
-	[MSM_PM_STAT_FAILED_SUSPEND].name = "failed-suspend",
-	[MSM_PM_STAT_FAILED_SUSPEND].first_bucket_time =
-		CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
-	[MSM_PM_STAT_NOT_IDLE].name = "not-idle",
-	[MSM_PM_STAT_NOT_IDLE].first_bucket_time =
-		CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
 };
 
+struct msm_pm_cpu_time_stats {
+	struct msm_pm_time_stats stats[MSM_PM_STAT_COUNT];
+};
+
+static DEFINE_PER_CPU_SHARED_ALIGNED(
+		struct msm_pm_cpu_time_stats, msm_pm_stats);
+
 static uint32_t msm_pm_sleep_limit = SLEEP_LIMIT_NONE;
 
+static DEFINE_SPINLOCK(msm_pm_stats_lock);
+
 /*
  * Add the given time data to the statistics collection.
  */
 static void msm_pm_add_stat(enum msm_pm_time_stats_id id, int64_t t)
 {
+	unsigned long flags;
+	struct msm_pm_time_stats *stats;
 	int i;
 	int64_t bt;
 
-	msm_pm_stats[id].total_time += t;
-	msm_pm_stats[id].count++;
+	spin_lock_irqsave(&msm_pm_stats_lock, flags);
+	stats = __get_cpu_var(msm_pm_stats).stats;
+
+	stats[id].total_time += t;
+	stats[id].count++;
 
 	bt = t;
-	do_div(bt, msm_pm_stats[id].first_bucket_time);
+	do_div(bt, stats[id].first_bucket_time);
 
 	if (bt < 1ULL << (CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT *
 				(CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1)))
@@ -758,12 +739,17 @@
 	else
 		i = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1;
 
-	msm_pm_stats[id].bucket[i]++;
+	if (i >= CONFIG_MSM_IDLE_STATS_BUCKET_COUNT)
+		i = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1;
 
-	if (t < msm_pm_stats[id].min_time[i] || !msm_pm_stats[id].max_time[i])
-		msm_pm_stats[id].min_time[i] = t;
-	if (t > msm_pm_stats[id].max_time[i])
-		msm_pm_stats[id].max_time[i] = t;
+	stats[id].bucket[i]++;
+
+	if (t < stats[id].min_time[i] || !stats[id].max_time[i])
+		stats[id].min_time[i] = t;
+	if (t > stats[id].max_time[i])
+		stats[id].max_time[i] = t;
+
+	spin_unlock_irqrestore(&msm_pm_stats_lock, flags);
 }
 
 /*
@@ -793,7 +779,8 @@
 static int msm_pm_read_proc
 	(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-	int i;
+	unsigned int cpu = off / MSM_PM_STAT_COUNT;
+	int id = off % MSM_PM_STAT_COUNT;
 	char *p = page;
 
 	if (count < 1024) {
@@ -809,44 +796,51 @@
 			SNPRINTF(p, count, "for TCXO shutdown\n\n");
 		else
 			SNPRINTF(p, count, "against TCXO shutdown\n\n");
+	}
 
-		*start = (char *) 1;
-		*eof = 0;
-	} else if (--off < ARRAY_SIZE(msm_pm_stats)) {
+	if (cpu < num_possible_cpus()) {
+		unsigned long flags;
+		struct msm_pm_time_stats *stats;
+		int i;
 		int64_t bucket_time;
 		int64_t s;
 		uint32_t ns;
 
-		s = msm_pm_stats[off].total_time;
+		spin_lock_irqsave(&msm_pm_stats_lock, flags);
+		stats = per_cpu(msm_pm_stats, cpu).stats;
+
+		s = stats[id].total_time;
 		ns = do_div(s, NSEC_PER_SEC);
 		SNPRINTF(p, count,
-			"%s:\n"
+			"[cpu %u] %s:\n"
 			"  count: %7d\n"
 			"  total_time: %lld.%09u\n",
-			msm_pm_stats[off].name,
-			msm_pm_stats[off].count,
+			cpu, stats[id].name,
+			stats[id].count,
 			s, ns);
 
-		bucket_time = msm_pm_stats[off].first_bucket_time;
+		bucket_time = stats[id].first_bucket_time;
 		for (i = 0; i < CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1; i++) {
 			s = bucket_time;
 			ns = do_div(s, NSEC_PER_SEC);
 			SNPRINTF(p, count,
 				"   <%6lld.%09u: %7d (%lld-%lld)\n",
-				s, ns, msm_pm_stats[off].bucket[i],
-				msm_pm_stats[off].min_time[i],
-				msm_pm_stats[off].max_time[i]);
+				s, ns, stats[id].bucket[i],
+				stats[id].min_time[i],
+				stats[id].max_time[i]);
 
 			bucket_time <<= CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT;
 		}
 
 		SNPRINTF(p, count, "  >=%6lld.%09u: %7d (%lld-%lld)\n",
-			s, ns, msm_pm_stats[off].bucket[i],
-			msm_pm_stats[off].min_time[i],
-			msm_pm_stats[off].max_time[i]);
+			s, ns, stats[id].bucket[i],
+			stats[id].min_time[i],
+			stats[id].max_time[i]);
 
 		*start = (char *) 1;
-		*eof = (off + 1 >= ARRAY_SIZE(msm_pm_stats));
+		*eof = (off + 1 >= MSM_PM_STAT_COUNT * num_possible_cpus());
+
+		spin_unlock_irqrestore(&msm_pm_stats_lock, flags);
 	}
 
 	return p - page;
@@ -864,7 +858,7 @@
 	char buf[sizeof(MSM_PM_STATS_RESET)];
 	int ret;
 	unsigned long flags;
-	int i;
+	unsigned int cpu;
 
 	if (count < strlen(MSM_PM_STATS_RESET)) {
 		ret = -EINVAL;
@@ -881,26 +875,32 @@
 		goto write_proc_failed;
 	}
 
-	local_irq_save(flags);
-	for (i = 0; i < ARRAY_SIZE(msm_pm_stats); i++) {
-		memset(msm_pm_stats[i].bucket,
-			0, sizeof(msm_pm_stats[i].bucket));
-		memset(msm_pm_stats[i].min_time,
-			0, sizeof(msm_pm_stats[i].min_time));
-		memset(msm_pm_stats[i].max_time,
-			0, sizeof(msm_pm_stats[i].max_time));
-		msm_pm_stats[i].count = 0;
-		msm_pm_stats[i].total_time = 0;
-	}
+	spin_lock_irqsave(&msm_pm_stats_lock, flags);
+	for_each_possible_cpu(cpu) {
+		struct msm_pm_time_stats *stats;
+		int i;
 
+		stats = per_cpu(msm_pm_stats, cpu).stats;
+		for (i = 0; i < MSM_PM_STAT_COUNT; i++) {
+			memset(stats[i].bucket,
+				0, sizeof(stats[i].bucket));
+			memset(stats[i].min_time,
+				0, sizeof(stats[i].min_time));
+			memset(stats[i].max_time,
+				0, sizeof(stats[i].max_time));
+			stats[i].count = 0;
+			stats[i].total_time = 0;
+		}
+	}
 	msm_pm_sleep_limit = SLEEP_LIMIT_NONE;
-	local_irq_restore(flags);
+	spin_unlock_irqrestore(&msm_pm_stats_lock, flags);
 
 	return count;
 
 write_proc_failed:
 	return ret;
 }
+
 #undef MSM_PM_STATS_RESET
 #endif /* CONFIG_MSM_IDLE_STATS */
 
@@ -1389,16 +1389,19 @@
 	int low_power;
 	int ret;
 	int i;
+	unsigned int cpu;
 
 #ifdef CONFIG_MSM_IDLE_STATS
 	int64_t t1;
 	static int64_t t2;
 	int exit_stat;
-#endif /* CONFIG_MSM_IDLE_STATS */
+ #endif /* CONFIG_MSM_IDLE_STATS */
 
 	if (!atomic_read(&msm_pm_init_done))
 		return;
 
+	cpu = smp_processor_id();
+
 	latency_qos = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
 	timer_expiration = msm_timer_enter_idle();
 
@@ -1406,39 +1409,14 @@
 	t1 = ktime_to_ns(ktime_get());
 	msm_pm_add_stat(MSM_PM_STAT_NOT_IDLE, t1 - t2);
 	msm_pm_add_stat(MSM_PM_STAT_REQUESTED_IDLE, timer_expiration);
+
+	exit_stat = MSM_PM_STAT_IDLE_SPIN;
+	low_power = 0;
 #endif /* CONFIG_MSM_IDLE_STATS */
 
 	for (i = 0; i < ARRAY_SIZE(allow); i++)
 		allow[i] = true;
 
-	switch (msm_pm_idle_sleep_mode) {
-	case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
-		allow[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT] =
-			false;
-		/* fall through */
-	case MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT:
-		allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE] = false;
-		/* fall through */
-	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
-		allow[MSM_PM_SLEEP_MODE_APPS_SLEEP] = false;
-		/* fall through */
-	case MSM_PM_SLEEP_MODE_APPS_SLEEP:
-		allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN] = false;
-		allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = false;
-		/* fall through */
-	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND:
-	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
-		break;
-	default:
-		printk(KERN_ERR "idle sleep mode is invalid: %d\n",
-			msm_pm_idle_sleep_mode);
-#ifdef CONFIG_MSM_IDLE_STATS
-		exit_stat = MSM_PM_STAT_IDLE_SPIN;
-#endif /* CONFIG_MSM_IDLE_STATS */
-		low_power = 0;
-		goto arch_idle_exit;
-	}
-
 	if ((timer_expiration < msm_pm_idle_sleep_min_time) ||
 #ifdef CONFIG_HAS_WAKELOCK
 		has_wake_lock(WAKE_LOCK_IDLE) ||
@@ -1450,7 +1428,8 @@
 	}
 
 	for (i = 0; i < ARRAY_SIZE(allow); i++) {
-		struct msm_pm_platform_data *mode = &msm_pm_modes[i];
+		struct msm_pm_platform_data *mode =
+					&msm_pm_modes[MSM_PM_MODE(cpu, i)];
 		if (!mode->idle_supported || !mode->idle_enabled ||
 			mode->latency >= latency_qos ||
 			mode->residency * 1000ULL >= timer_expiration)
@@ -1564,7 +1543,6 @@
 #endif /* CONFIG_MSM_IDLE_STATS */
 	}
 
-arch_idle_exit:
 	msm_timer_exit_idle(low_power);
 
 #ifdef CONFIG_MSM_IDLE_STATS
@@ -1604,32 +1582,9 @@
 	for (i = 0; i < ARRAY_SIZE(allow); i++)
 		allow[i] = true;
 
-	switch (msm_pm_sleep_mode) {
-	case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
-		allow[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT] =
-			false;
-		/* fall through */
-	case MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT:
-		allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE] = false;
-		/* fall through */
-	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
-		allow[MSM_PM_SLEEP_MODE_APPS_SLEEP] = false;
-		/* fall through */
-	case MSM_PM_SLEEP_MODE_APPS_SLEEP:
-		allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN] = false;
-		allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = false;
-		/* fall through */
-	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND:
-	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
-		break;
-	default:
-		printk(KERN_ERR "suspend sleep mode is invalid: %d\n",
-			msm_pm_sleep_mode);
-		return -EINVAL;
-	}
-
 	for (i = 0; i < ARRAY_SIZE(allow); i++) {
-		struct msm_pm_platform_data *mode = &msm_pm_modes[i];
+		struct msm_pm_platform_data *mode;
+		mode = &msm_pm_modes[MSM_PM_MODE(0, i)];
 		if (!mode->suspend_supported || !mode->suspend_enabled)
 			allow[i] = false;
 	}
@@ -1778,6 +1733,7 @@
 {
 #ifdef CONFIG_MSM_IDLE_STATS
 	struct proc_dir_entry *d_entry;
+	unsigned int cpu;
 #endif
 	int ret;
 #ifdef CONFIG_CPU_V7
@@ -1846,6 +1802,66 @@
 
 	msm_pm_mode_sysfs_add();
 #ifdef CONFIG_MSM_IDLE_STATS
+	for_each_possible_cpu(cpu) {
+		struct msm_pm_time_stats *stats =
+			per_cpu(msm_pm_stats, cpu).stats;
+
+		stats[MSM_PM_STAT_REQUESTED_IDLE].name = "idle-request";
+		stats[MSM_PM_STAT_REQUESTED_IDLE].first_bucket_time =
+			CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+		stats[MSM_PM_STAT_IDLE_SPIN].name = "idle-spin";
+		stats[MSM_PM_STAT_IDLE_SPIN].first_bucket_time =
+			CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+		stats[MSM_PM_STAT_IDLE_WFI].name = "idle-wfi";
+		stats[MSM_PM_STAT_IDLE_WFI].first_bucket_time =
+			CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+		stats[MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].name =
+			"idle-standalone-power-collapse";
+		stats[MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].
+			first_bucket_time =
+			CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+		stats[MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE].name =
+			"idle-failed-standalone-power-collapse";
+		stats[MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE].
+			first_bucket_time =
+			CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+		stats[MSM_PM_STAT_IDLE_SLEEP].name = "idle-sleep";
+		stats[MSM_PM_STAT_IDLE_SLEEP].first_bucket_time =
+			CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+		stats[MSM_PM_STAT_IDLE_FAILED_SLEEP].name =
+			"idle-failed-sleep";
+		stats[MSM_PM_STAT_IDLE_FAILED_SLEEP].first_bucket_time =
+			CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+		stats[MSM_PM_STAT_IDLE_POWER_COLLAPSE].name =
+			"idle-power-collapse";
+		stats[MSM_PM_STAT_IDLE_POWER_COLLAPSE].first_bucket_time =
+			CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+		stats[MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE].name =
+			"idle-failed-power-collapse";
+		stats[MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE].
+			first_bucket_time =
+			CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+		stats[MSM_PM_STAT_SUSPEND].name = "suspend";
+		stats[MSM_PM_STAT_SUSPEND].first_bucket_time =
+			CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET;
+
+		stats[MSM_PM_STAT_FAILED_SUSPEND].name = "failed-suspend";
+		stats[MSM_PM_STAT_FAILED_SUSPEND].first_bucket_time =
+			CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+		stats[MSM_PM_STAT_NOT_IDLE].name = "not-idle";
+		stats[MSM_PM_STAT_NOT_IDLE].first_bucket_time =
+			CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+	}
 	d_entry = create_proc_entry("msm_pm_stats",
 			S_IRUGO | S_IWUSR | S_IWGRP, NULL);
 	if (d_entry) {
diff --git a/arch/arm/mach-msm/rpm-regulator.c b/arch/arm/mach-msm/rpm-regulator.c
index 946d31b..ed366aed 100644
--- a/arch/arm/mach-msm/rpm-regulator.c
+++ b/arch/arm/mach-msm/rpm-regulator.c
@@ -268,8 +268,10 @@
 
 	if (vreg->part->uV.mask)
 		uV = GET_PART(vreg, uV);
-	else
+	else if (vreg->part->mV.mask)
 		uV = MILLI_TO_MICRO(GET_PART(vreg, mV));
+	else if (vreg->part->enable_state.mask)
+		uV = GET_PART(vreg, enable_state);
 
 	return uV;
 }
@@ -278,8 +280,10 @@
 {
 	if (vreg->part->uV.mask)
 		SET_PART(vreg, uV, uV);
-	else
+	else if (vreg->part->mV.mask)
 		SET_PART(vreg, mV, MICRO_TO_MILLI(uV));
+	else if (vreg->part->enable_state.mask)
+		SET_PART(vreg, enable_state, uV);
 }
 
 static int vreg_send_request(struct vreg *vreg, enum rpm_vreg_voter voter,
@@ -380,9 +384,14 @@
 		if (vreg->part->uV.mask) {
 			s_val[vreg->part->uV.word] = 0 << vreg->part->uV.shift;
 			s_mask[vreg->part->uV.word] = vreg->part->uV.mask;
-		} else {
+		} else if (vreg->part->mV.mask) {
 			s_val[vreg->part->mV.word] = 0 << vreg->part->mV.shift;
 			s_mask[vreg->part->mV.word] = vreg->part->mV.mask;
+		} else if (vreg->part->enable_state.mask) {
+			s_val[vreg->part->enable_state.word]
+				= 0 << vreg->part->enable_state.shift;
+			s_mask[vreg->part->enable_state.word]
+				= vreg->part->enable_state.mask;
 		}
 
 		rc = vreg_send_request(vreg, voter, MSM_RPM_CTX_SET_SLEEP,
@@ -421,6 +430,10 @@
  *
  * Consumers can vote to disable a regulator with this function by passing
  * min_uV = 0 and max_uV = 0.
+ *
+ * Voltage switch type regulators may be controlled via rpm_vreg_set_voltage
+ * as well.  For this type of regulator, max_uV > 0 is treated as an enable
+ * request and max_uV == 0 is treated as a disable request.
  */
 int rpm_vreg_set_voltage(int vreg_id, enum rpm_vreg_voter voter, int min_uV,
 			 int max_uV, int sleep_also)
@@ -431,14 +444,6 @@
 	int uV = min_uV;
 	int lim_min_uV, lim_max_uV, i, rc;
 
-	/*
-	 * HACK: make this function a no-op for 8064 so that it can be called by
-	 * consumers on 8064 before RPM capabilities are present. (needed for
-	 * acpuclock driver)
-	 */
-	if (cpu_is_apq8064())
-		return 0;
-
 	if (!config) {
 		pr_err("rpm-regulator driver has not probed yet.\n");
 		return -ENODEV;
@@ -450,7 +455,6 @@
 	}
 
 	vreg = &config->vregs[vreg_id];
-	range = &vreg->set_points->range[0];
 
 	if (!vreg->pdata.sleep_selectable) {
 		vreg_err(vreg, "regulator is not marked sleep selectable\n");
@@ -458,7 +462,8 @@
 	}
 
 	/* Allow min_uV == max_uV == 0 to represent a disable request. */
-	if (min_uV != 0 || max_uV != 0) {
+	if ((min_uV != 0 || max_uV != 0)
+	    && (vreg->part->uV.mask || vreg->part->mV.mask)) {
 		/*
 		 * Check if request voltage is outside of allowed range. The
 		 * regulator core has already checked that constraint range
@@ -477,6 +482,7 @@
 			return -EINVAL;
 		}
 
+		range = &vreg->set_points->range[0];
 		/* Find the range which uV is inside of. */
 		for (i = vreg->set_points->count - 1; i > 0; i--) {
 			if (uV > vreg->set_points->range[i - 1].max_uV) {
@@ -504,10 +510,20 @@
 	if (vreg->part->uV.mask) {
 		val[vreg->part->uV.word] = uV << vreg->part->uV.shift;
 		mask[vreg->part->uV.word] = vreg->part->uV.mask;
-	} else {
+	} else if (vreg->part->mV.mask) {
 		val[vreg->part->mV.word]
 			= MICRO_TO_MILLI(uV) << vreg->part->mV.shift;
 		mask[vreg->part->mV.word] = vreg->part->mV.mask;
+	} else if (vreg->part->enable_state.mask) {
+		/*
+		 * Translate max_uV > 0 into an enable request for regulator
+		 * types which to not support voltage setting, e.g. voltage
+		 * switches.
+		 */
+		val[vreg->part->enable_state.word]
+		    = (max_uV > 0 ? 1 : 0) << vreg->part->enable_state.shift;
+		mask[vreg->part->enable_state.word]
+		    = vreg->part->enable_state.mask;
 	}
 
 	rc = vreg_set_noirq(vreg, voter, sleep_also, mask[0], val[0], mask[1],
@@ -532,13 +548,6 @@
 	struct vreg *vreg;
 	int rc;
 
-	/*
-	 * HACK: make this function a no-op for 8064 so that it can be called by
-	 * consumers on 8064 before RPM capabilities are present.
-	 */
-	if (cpu_is_apq8064())
-		return 0;
-
 	if (!config) {
 		pr_err("rpm-regulator driver has not probed yet.\n");
 		return -ENODEV;
diff --git a/arch/arm/mach-msm/rpm.c b/arch/arm/mach-msm/rpm.c
index fb9d295..05b2953 100644
--- a/arch/arm/mach-msm/rpm.c
+++ b/arch/arm/mach-msm/rpm.c
@@ -31,7 +31,6 @@
 #include <asm/hardware/gic.h>
 #include <mach/msm_iomap.h>
 #include <mach/rpm.h>
-#include <mach/socinfo.h>
 
 /******************************************************************************
  * Data type and structure definitions
@@ -425,9 +424,6 @@
 	uint32_t sel_masks[SEL_MASK_SIZE] = {};
 	int rc;
 
-	if (cpu_is_apq8064())
-		return 0;
-
 	if (ctx >= MSM_RPM_CTX_SET_COUNT) {
 		rc = -EINVAL;
 		goto set_common_exit;
@@ -471,9 +467,6 @@
 	int rc;
 	int i;
 
-	if (cpu_is_apq8064())
-		return 0;
-
 	if (ctx >= MSM_RPM_CTX_SET_COUNT) {
 		rc = -EINVAL;
 		goto clear_common_exit;
@@ -612,9 +605,6 @@
 	int rc;
 	int i;
 
-	if (cpu_is_apq8064())
-		return 0;
-
 	seq_begin = msm_rpm_read(MSM_RPM_PAGE_STATUS,
 				target_status(MSM_RPM_STATUS_ID_SEQUENCE));
 
@@ -768,9 +758,6 @@
 	int rc;
 	int i;
 
-	if (cpu_is_apq8064())
-		return 0;
-
 	INIT_LIST_HEAD(&n->list);
 	rc = msm_rpm_fill_sel_masks(n->sel_masks, req, count);
 	if (rc)
@@ -823,9 +810,6 @@
 	int rc;
 	int i;
 
-	if (cpu_is_apq8064())
-		return 0;
-
 	rc = mutex_lock_interruptible(&msm_rpm_mutex);
 	if (rc)
 		goto unregister_notification_exit;
@@ -951,9 +935,6 @@
 	unsigned int irq;
 	int rc;
 
-	if (cpu_is_apq8064())
-		return 0;
-
 	memcpy(&msm_rpm_data, data, sizeof(struct msm_rpm_platform_data));
 	msm_rpm_sel_mask_size = msm_rpm_data.sel_last / 32 + 1;
 	BUG_ON(SEL_MASK_SIZE < msm_rpm_sel_mask_size);
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 609528c..546a917 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -1016,12 +1016,13 @@
 
 	/* Initialize listed bitmap for valid resource IDs */
 	for (i = 0; i < ARRAY_SIZE(msm_rpmrs_resources); i++) {
-		for (k = 0; k < msm_rpmrs_resources[i]->size; k++)
+		for (k = 0; k < msm_rpmrs_resources[i]->size; k++) {
 			if (msm_rpmrs_resources[i]->rs[k].id >=
 					MSM_RPM_ID_LAST)
 				continue;
 			set_bit(msm_rpmrs_resources[i]->rs[k].id,
 				msm_rpmrs_listed);
+		}
 	}
 
 	return 0;
@@ -1032,9 +1033,6 @@
 	struct msm_rpm_iv_pair req;
 	int rc;
 
-	if (cpu_is_apq8064())
-		return -ENODEV;
-
 	BUG_ON(!msm_rpmrs_levels);
 
 	if (cpu_is_msm8x60()) {
@@ -1068,7 +1066,7 @@
 
 static int __init msm_rpmrs_l2_init(void)
 {
-	if (cpu_is_msm8960() || cpu_is_msm8930()) {
+	if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_apq8064()) {
 
 		msm_pm_set_l2_flush_flag(0);
 
diff --git a/arch/arm/mach-msm/scm-pas.h b/arch/arm/mach-msm/scm-pas.h
index 67a0992..3651ee19 100644
--- a/arch/arm/mach-msm/scm-pas.h
+++ b/arch/arm/mach-msm/scm-pas.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -20,6 +20,8 @@
 	PAS_MODEM_SW,
 	PAS_MODEM_FW,
 	PAS_RIVA,
+	PAS_SECAPP,
+	PAS_GSS,
 };
 
 extern int pas_init_image(enum pas_id id, const u8 *metadata, size_t size);
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 10593c62..b95c3aa 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -102,6 +102,45 @@
 	uint32_t last_value;
 };
 
+struct interrupt_config_item {
+	/* must be initialized */
+	irqreturn_t (*irq_handler)(int req, void *data);
+	/* outgoing interrupt config (set from platform data) */
+	uint32_t out_bit_pos;
+	void __iomem *out_base;
+	uint32_t out_offset;
+};
+
+struct interrupt_config {
+	struct interrupt_config_item smd;
+	struct interrupt_config_item smsm;
+};
+
+static irqreturn_t smd_modem_irq_handler(int irq, void *data);
+static irqreturn_t smd_dsp_irq_handler(int irq, void *data);
+static irqreturn_t smd_dsps_irq_handler(int irq, void *data);
+static irqreturn_t smd_wcnss_irq_handler(int irq, void *data);
+static irqreturn_t smsm_irq_handler(int irq, void *data);
+
+static struct interrupt_config private_intr_config[NUM_SMD_SUBSYSTEMS] = {
+	[SMD_MODEM] = {
+		.smd.irq_handler = smd_modem_irq_handler,
+		.smsm.irq_handler = smsm_irq_handler,
+	},
+	[SMD_Q6] = {
+		.smd.irq_handler = smd_dsp_irq_handler,
+		.smsm.irq_handler = smsm_irq_handler,
+	},
+	[SMD_DSPS] = {
+		.smd.irq_handler = smd_dsps_irq_handler,
+		.smsm.irq_handler = smsm_irq_handler,
+	},
+	[SMD_WCNSS] = {
+		.smd.irq_handler = smd_wcnss_irq_handler,
+		.smsm.irq_handler = smsm_irq_handler,
+	},
+};
+
 #define SMSM_STATE_ADDR(entry)           (smsm_info.state + entry)
 #define SMSM_INTR_MASK_ADDR(entry, host) (smsm_info.intr_mask + \
 					  entry * SMSM_NUM_HOSTS + host)
@@ -240,7 +279,6 @@
 static remote_spinlock_t remote_spinlock;
 
 static LIST_HEAD(smd_ch_list_loopback);
-static irqreturn_t smsm_irq_handler(int irq, void *data);
 static void smd_fake_irq_handler(unsigned long arg);
 static void smsm_cb_snapshot(void);
 
@@ -275,6 +313,98 @@
 static inline void wakeup_v1_riva(void) {}
 #endif
 
+static inline void notify_modem_smd(void)
+{
+	static const struct interrupt_config_item *intr
+	   = &private_intr_config[SMD_MODEM].smd;
+	if (intr->out_base)
+		smd_write_intr(intr->out_bit_pos,
+		intr->out_base + intr->out_offset);
+	else
+		MSM_TRIG_A2M_SMD_INT;
+}
+
+static inline void notify_dsp_smd(void)
+{
+	static const struct interrupt_config_item *intr
+		= &private_intr_config[SMD_Q6].smd;
+	if (intr->out_base)
+		smd_write_intr(intr->out_bit_pos,
+		intr->out_base + intr->out_offset);
+	else
+		MSM_TRIG_A2Q6_SMD_INT;
+}
+
+static inline void notify_dsps_smd(void)
+{
+	static const struct interrupt_config_item *intr
+		= &private_intr_config[SMD_DSPS].smd;
+	if (intr->out_base)
+		smd_write_intr(intr->out_bit_pos,
+		intr->out_base + intr->out_offset);
+	else
+		MSM_TRIG_A2DSPS_SMD_INT;
+}
+
+static inline void notify_wcnss_smd(void)
+{
+	static const struct interrupt_config_item *intr
+		= &private_intr_config[SMD_WCNSS].smd;
+	wakeup_v1_riva();
+
+	if (intr->out_base)
+		smd_write_intr(intr->out_bit_pos,
+		intr->out_base + intr->out_offset);
+	else
+		MSM_TRIG_A2WCNSS_SMD_INT;
+}
+
+static inline void notify_modem_smsm(void)
+{
+	static const struct interrupt_config_item *intr
+		= &private_intr_config[SMD_MODEM].smsm;
+	if (intr->out_base)
+		smd_write_intr(intr->out_bit_pos,
+		intr->out_base + intr->out_offset);
+	else
+		MSM_TRIG_A2M_SMSM_INT;
+}
+
+static inline void notify_dsp_smsm(void)
+{
+	static const struct interrupt_config_item *intr
+		= &private_intr_config[SMD_Q6].smsm;
+	if (intr->out_base)
+		smd_write_intr(intr->out_bit_pos,
+		intr->out_base + intr->out_offset);
+	else
+		MSM_TRIG_A2Q6_SMSM_INT;
+}
+
+static inline void notify_dsps_smsm(void)
+{
+	static const struct interrupt_config_item *intr
+		= &private_intr_config[SMD_DSPS].smsm;
+	if (intr->out_base)
+		smd_write_intr(intr->out_bit_pos,
+		intr->out_base + intr->out_offset);
+	else
+		MSM_TRIG_A2DSPS_SMSM_INT;
+}
+
+static inline void notify_wcnss_smsm(void)
+{
+	static const struct interrupt_config_item *intr
+		= &private_intr_config[SMD_WCNSS].smsm;
+	wakeup_v1_riva();
+
+	if (intr->out_base)
+		smd_write_intr(intr->out_bit_pos,
+		intr->out_base + intr->out_offset);
+	else
+		MSM_TRIG_A2WCNSS_SMSM_INT;
+}
+
 static void notify_other_smsm(uint32_t smsm_entry, uint32_t notify_mask)
 {
 	/* older protocol don't use smsm_intr_mask,
@@ -282,7 +412,7 @@
 	if (!smsm_info.intr_mask ||
 	    (__raw_readl(SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_MODEM))
 				& notify_mask))
-		MSM_TRIG_A2M_SMSM_INT;
+		notify_modem_smsm();
 
 	if (smsm_info.intr_mask &&
 	    (__raw_readl(SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_Q6))
@@ -296,46 +426,24 @@
 			__raw_writel(mux_val,
 					SMSM_INTR_MUX_ADDR(SMEM_APPS_Q6_SMSM));
 		}
-		MSM_TRIG_A2Q6_SMSM_INT;
+		notify_dsp_smsm();
 	}
 
 	if (smsm_info.intr_mask &&
 	    (__raw_readl(SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_WCNSS))
 				& notify_mask)) {
-		wakeup_v1_riva();
-		MSM_TRIG_A2WCNSS_SMSM_INT;
+		notify_wcnss_smsm();
 	}
 
 	if (smsm_info.intr_mask &&
 	    (__raw_readl(SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_DSPS))
 				& notify_mask)) {
-		MSM_TRIG_A2DSPS_SMSM_INT;
+		notify_dsps_smsm();
 	}
 
 	smsm_cb_snapshot();
 }
 
-static inline void notify_modem_smd(void)
-{
-	MSM_TRIG_A2M_SMD_INT;
-}
-
-static inline void notify_dsp_smd(void)
-{
-	MSM_TRIG_A2Q6_SMD_INT;
-}
-
-static inline void notify_dsps_smd(void)
-{
-	MSM_TRIG_A2DSPS_SMD_INT;
-}
-
-static inline void notify_wcnss_smd(void)
-{
-	wakeup_v1_riva();
-	MSM_TRIG_A2WCNSS_SMD_INT;
-}
-
 void smd_diag(void)
 {
 	char *x;
@@ -451,23 +559,6 @@
 	uint32_t	remote_pid;
 };
 
-/*
- * SMD Processor ID's.
- *
- * For all processors that have both SMSM and SMD clients,
- * the SMSM Processor ID and the SMD Processor ID will
- * be the same.  In cases where a processor only supports
- * SMD, the entry will only exist in this enum.
- */
-enum {
-	SMD_APPS = SMSM_APPS,
-	SMD_MODEM = SMSM_MODEM,
-	SMD_Q6 = SMSM_Q6,
-	SMD_WCNSS = SMSM_WCNSS,
-	SMD_DSPS = SMSM_DSPS,
-	SMD_MODEM_Q6_FW,
-};
-
 /**
  * Maps edge type to local and remote processor ID's.
  */
@@ -1008,32 +1099,26 @@
 	return IRQ_HANDLED;
 }
 
-#if defined(CONFIG_QDSP6)
 static irqreturn_t smd_dsp_irq_handler(int irq, void *data)
 {
 	handle_smd_irq(&smd_ch_list_dsp, notify_dsp_smd);
 	handle_smd_irq_closing_list();
 	return IRQ_HANDLED;
 }
-#endif
 
-#if defined(CONFIG_DSPS)
 static irqreturn_t smd_dsps_irq_handler(int irq, void *data)
 {
 	handle_smd_irq(&smd_ch_list_dsps, notify_dsps_smd);
 	handle_smd_irq_closing_list();
 	return IRQ_HANDLED;
 }
-#endif
 
-#if defined(CONFIG_WCNSS)
 static irqreturn_t smd_wcnss_irq_handler(int irq, void *data)
 {
 	handle_smd_irq(&smd_ch_list_wcnss, notify_wcnss_smd);
 	handle_smd_irq_closing_list();
 	return IRQ_HANDLED;
 }
-#endif
 
 static void smd_fake_irq_handler(unsigned long arg)
 {
@@ -2567,22 +2652,121 @@
 		pr_err("smd_core_init: "
 		       "enable_irq_wake failed for INT_DSPS_A11_SMSM\n");
 #endif
-
-	/* we may have missed a signal while booting -- fake
-	 * an interrupt to make sure we process any existing
-	 * state
-	 */
-	smsm_irq_handler(0, 0);
-
 	SMD_INFO("smd_core_init() done\n");
 
 	return 0;
 }
 
+static int intr_init(struct interrupt_config_item *private_irq,
+			struct smd_irq_config *platform_irq,
+			struct platform_device *pdev
+			)
+{
+	int irq_id;
+	int ret;
+	int ret_wake;
+
+	private_irq->out_bit_pos = platform_irq->out_bit_pos;
+	private_irq->out_offset = platform_irq->out_offset;
+	private_irq->out_base = platform_irq->out_base;
+
+	irq_id = platform_get_irq_byname(
+					pdev,
+					platform_irq->irq_name
+				);
+	SMD_DBG("smd: %s: register irq: %s id: %d\n", __func__,
+				platform_irq->irq_name, irq_id);
+	ret = request_irq(irq_id,
+				private_irq->irq_handler,
+				platform_irq->flags,
+				platform_irq->device_name,
+				(void *)platform_irq->dev_id
+			);
+	if (ret < 0) {
+		platform_irq->irq_id = ret;
+	} else {
+		platform_irq->irq_id = irq_id;
+		ret_wake = enable_irq_wake(irq_id);
+		if (ret_wake < 0) {
+			pr_err("smd: enable_irq_wake failed on %s",
+					platform_irq->irq_name);
+		}
+	}
+
+	return ret;
+}
+
+int smd_core_platform_init(struct platform_device *pdev)
+{
+	int i;
+	int ret;
+	uint32_t num_ss;
+	struct smd_platform *smd_platform_data;
+	struct smd_subsystem_config *smd_ss_config_list;
+	struct smd_subsystem_config *cfg;
+	int err_ret = 0;
+
+	smd_platform_data = pdev->dev.platform_data;
+	num_ss = smd_platform_data->num_ss_configs;
+	smd_ss_config_list = smd_platform_data->smd_ss_configs;
+
+	for (i = 0; i < num_ss; i++) {
+		cfg = &smd_ss_config_list[i];
+
+		ret = intr_init(
+			&private_intr_config[cfg->irq_config_id].smd,
+			&cfg->smd_int,
+			pdev
+			);
+
+		if (ret < 0) {
+			err_ret = ret;
+			pr_err("smd: register irq failed on %s\n",
+				cfg->smd_int.irq_name);
+			break;
+		}
+
+		ret = intr_init(
+			&private_intr_config[cfg->irq_config_id].smsm,
+			&cfg->smsm_int,
+			pdev
+			);
+
+		if (ret < 0) {
+			err_ret = ret;
+			pr_err("smd: register irq failed on %s\n",
+				cfg->smsm_int.irq_name);
+			break;
+		}
+	}
+
+	if (err_ret < 0) {
+		pr_err("smd: deregistering IRQs\n");
+		for (i = 0; i < num_ss; ++i) {
+			cfg = &smd_ss_config_list[i];
+
+			if (cfg->smd_int.irq_id >= 0)
+				free_irq(cfg->smd_int.irq_id,
+					(void *)cfg->smd_int.dev_id
+					);
+			if (cfg->smsm_int.irq_id >= 0)
+				free_irq(cfg->smsm_int.irq_id,
+					(void *)cfg->smsm_int.dev_id
+					);
+		}
+		return err_ret;
+	}
+
+	SMD_INFO("smd_core_platform_init() done\n");
+	return 0;
+
+}
+
 static int __devinit msm_smd_probe(struct platform_device *pdev)
 {
-	SMD_INFO("smd probe\n");
+	int ret;
 
+	SMD_INFO("smd probe\n");
 	INIT_WORK(&probe_work, smd_channel_probe_worker);
 
 	channel_close_wq = create_singlethread_workqueue("smd_channel_close");
@@ -2596,9 +2780,27 @@
 		return -1;
 	}
 
-	if (smd_core_init()) {
-		pr_err("smd_core_init() failed\n");
-		return -1;
+	if (pdev) {
+		if (pdev->dev.of_node) {
+			pr_err("SMD: Device tree not currently supported\n");
+			return -ENODEV;
+		} else if (pdev->dev.platform_data) {
+			ret = smd_core_platform_init(pdev);
+			if (ret) {
+				pr_err(
+				"SMD: smd_core_platform_init() failed\n");
+				return -ENODEV;
+			}
+		} else {
+			ret = smd_core_init();
+			if (ret) {
+				pr_err("smd_core_init() failed\n");
+				return -ENODEV;
+			}
+		}
+	} else {
+		pr_err("SMD: PDEV not found\n");
+		return -ENODEV;
 	}
 
 	smd_initialized = 1;
@@ -2619,7 +2821,7 @@
 	{SMD_Q6, "lpass", .nb.notifier_call = restart_notifier_cb},
 	{SMD_WCNSS, "riva", .nb.notifier_call = restart_notifier_cb},
 	{SMD_DSPS, "dsps", .nb.notifier_call = restart_notifier_cb},
-	{SMD_MODEM, "gnss", .nb.notifier_call = restart_notifier_cb},
+	{SMD_MODEM, "gss", .nb.notifier_call = restart_notifier_cb},
 };
 
 static int restart_notifier_cb(struct notifier_block *this,
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 8023129..63c5fef 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -31,6 +31,7 @@
 #include <linux/msm_smd_pkt.h>
 #include <linux/poll.h>
 #include <asm/ioctls.h>
+#include <linux/wakelock.h>
 
 #include <mach/msm_smd.h>
 #include <mach/peripheral-loader.h>
@@ -45,6 +46,7 @@
 #define LOOPBACK_INX (NUM_SMD_PKT_PORTS - 1)
 
 #define DEVICE_NAME "smdpkt"
+#define WAKELOCK_TIMEOUT (2*HZ)
 
 struct smd_pkt_dev {
 	struct cdev cdev;
@@ -70,7 +72,8 @@
 	int has_reset;
 	int do_reset_notification;
 	struct completion ch_allocated;
-
+	struct wake_lock pa_wake_lock;		/* Packet Arrival Wake lock*/
+	struct work_struct packet_arrival_work;
 } *smd_pkt_devp[NUM_SMD_PKT_PORTS];
 
 struct class *smd_pkt_classp;
@@ -183,6 +186,19 @@
 
 }
 
+static void packet_arrival_worker(struct work_struct *work)
+{
+	struct smd_pkt_dev *smd_pkt_devp;
+
+	smd_pkt_devp = container_of(work, struct smd_pkt_dev,
+				    packet_arrival_work);
+	mutex_lock(&smd_pkt_devp->ch_lock);
+	if (smd_pkt_devp->ch)
+		wake_lock_timeout(&smd_pkt_devp->pa_wake_lock,
+				  WAKELOCK_TIMEOUT);
+	mutex_unlock(&smd_pkt_devp->ch_lock);
+}
+
 static long smd_pkt_ioctl(struct file *file, unsigned int cmd,
 					     unsigned long arg)
 {
@@ -421,6 +437,7 @@
 
 	/* here we have a packet of size sz ready */
 	wake_up(&smd_pkt_devp->ch_read_wait_queue);
+	schedule_work(&smd_pkt_devp->packet_arrival_work);
 	D(KERN_ERR "%s: after wake_up\n", __func__);
 }
 
@@ -579,6 +596,10 @@
 	if (!smd_pkt_devp)
 		return -EINVAL;
 
+	wake_lock_init(&smd_pkt_devp->pa_wake_lock, WAKE_LOCK_SUSPEND,
+			smd_pkt_dev_name[smd_pkt_devp->i]);
+	INIT_WORK(&smd_pkt_devp->packet_arrival_work, packet_arrival_worker);
+
 	file->private_data = smd_pkt_devp;
 
 	mutex_lock(&smd_pkt_devp->ch_lock);
@@ -665,6 +686,9 @@
 out:
 	mutex_unlock(&smd_pkt_devp->ch_lock);
 
+	if (r < 0)
+		wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
+
 	return r;
 }
 
@@ -690,6 +714,7 @@
 
 	smd_pkt_devp->has_reset = 0;
 	smd_pkt_devp->do_reset_notification = 0;
+	wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
 
 	return r;
 }
diff --git a/arch/arm/mach-msm/spm-v2.c b/arch/arm/mach-msm/spm-v2.c
index 021a216..4a7cf91 100644
--- a/arch/arm/mach-msm/spm-v2.c
+++ b/arch/arm/mach-msm/spm-v2.c
@@ -18,7 +18,6 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <mach/msm_iomap.h>
-#include <mach/socinfo.h>
 
 #include "spm_driver.h"
 
@@ -128,10 +127,6 @@
 {
 	uint32_t value = enable ? 0x01 : 0x00;
 
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return 0;
-
 	if (!dev)
 		return -EINVAL;
 
@@ -150,10 +145,6 @@
 	int i;
 	int num_spm_entry = msm_spm_drv_get_num_spm_entry(dev);
 
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return;
-
 	if (!dev) {
 		__WARN();
 		return;
@@ -174,10 +165,6 @@
 	uint32_t offset_w = offset / 4;
 	int ret = 0;
 
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return 0;
-
 	if (!cmd || !dev) {
 		__WARN();
 		goto failed_write_seq_data;
@@ -214,10 +201,6 @@
 		uint32_t addr)
 {
 
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return 0;
-
 	/* SPM is configured to reset start address to zero after end of Program
 	 */
 	if (!dev)
@@ -242,10 +225,6 @@
 {
 	uint32_t timeout_us;
 
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return 0;
-
 	if (!dev)
 		return -EINVAL;
 
@@ -299,10 +278,6 @@
 	int i;
 	int num_spm_entry;
 
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return 0;
-
 	BUG_ON(!dev || !data);
 
 	dev->reg_base_addr = data->reg_base_addr;
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index 0aa1358..883dec1 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -19,7 +19,6 @@
 #include <linux/slab.h>
 #include <mach/msm_iomap.h>
 #include <mach/socinfo.h>
-
 #include "spm.h"
 #include "spm_driver.h"
 
@@ -130,11 +129,6 @@
 int msm_spm_set_low_power_mode(unsigned int mode, bool notify_rpm)
 {
 	struct msm_spm_device *dev = &__get_cpu_var(msm_cpu_spm_device);
-
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return 0;
-
 	return msm_spm_dev_set_low_power_mode(dev, mode, notify_rpm);
 }
 
@@ -143,10 +137,6 @@
 	unsigned int cpu;
 	int ret = 0;
 
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return 0;
-
 	BUG_ON((nr_devs < num_possible_cpus()) || !data);
 
 	for_each_possible_cpu(cpu) {
@@ -210,10 +200,6 @@
 
 int __init msm_spm_l2_init(struct msm_spm_platform_data *data)
 {
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return 0;
-
 	return msm_spm_dev_init(&msm_spm_l2_device, data);
 }
 #endif
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 3d44075..4128e3a 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -215,13 +215,13 @@
 		return __raw_readl(addr);
 
 	t1 = __raw_readl(addr);
-	t2 = __raw_readl(addr);
+	t2 = __raw_readl_no_log(addr);
 	if ((t2-t1) <= 1)
 		return t2;
 	while (1) {
-		t1 = __raw_readl(addr);
-		t2 = __raw_readl(addr);
-		t3 = __raw_readl(addr);
+		t1 = __raw_readl_no_log(addr);
+		t2 = __raw_readl_no_log(addr);
+		t3 = __raw_readl_no_log(addr);
 		cpu_relax();
 		if ((t3-t2) <= 1)
 			return t3;
@@ -304,7 +304,7 @@
 		/* read the counter four extra times to make sure write posts
 		   before reading the time */
 		for (i = 0; i < 4; i++)
-			__raw_readl(clock->regbase + TIMER_COUNT_VAL);
+			__raw_readl_no_log(clock->regbase + TIMER_COUNT_VAL);
 	}
 	now = msm_read_timer_count(clock, LOCAL_TIMER);
 	clock_state->last_set = now;
@@ -415,11 +415,12 @@
 	tmp /= (loop_zero_count-1);
 
 	while (loop_zero_count--) {
-		t1 = __raw_readl(MSM_RPM_MPM_BASE + MPM_SCLK_COUNT_VAL);
+		t1 = __raw_readl_no_log(MSM_RPM_MPM_BASE + MPM_SCLK_COUNT_VAL);
 		do {
 			udelay(1);
 			t2 = t1;
-			t1 = __raw_readl(MSM_RPM_MPM_BASE + MPM_SCLK_COUNT_VAL);
+			t1 = __raw_readl_no_log(
+				MSM_RPM_MPM_BASE + MPM_SCLK_COUNT_VAL);
 		} while ((t2 != t1) && --loop_count);
 
 		if (!loop_count) {
@@ -1087,7 +1088,8 @@
 			res = request_percpu_irq(ce->irq, msm_timer_interrupt,
 						 ce->name, clock->percpu_evt);
 			if (!res)
-				enable_percpu_irq(ce->irq, 0);
+				enable_percpu_irq(ce->irq,
+						 IRQ_TYPE_EDGE_RISING);
 		} else {
 			clock->evt = ce;
 			res = request_irq(ce->irq, msm_timer_interrupt,
@@ -1150,7 +1152,7 @@
 	*__this_cpu_ptr(clock->percpu_evt) = evt;
 
 	clockevents_register_device(evt);
-	enable_percpu_irq(evt->irq, 0);
+	enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING);
 
 	return 0;
 }
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index 5cd1b05..3bce534 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -54,9 +54,15 @@
 	and	r1, r1, #7			@ mask of the bits for current cache only
 	cmp	r1, #2				@ see what cache we have at this level
 	blt	skip				@ skip if no cache, or just i-cache
+#ifdef CONFIG_PREEMPT
+	save_and_disable_irqs r9		@ make cssr&csidr read atomic
+#endif
 	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
 	isb					@ isb to sych the new cssr&csidr
 	mrc	p15, 1, r1, c0, c0, 0		@ read the new csidr
+#ifdef CONFIG_PREEMPT
+	restore_irqs_notrace r9
+#endif
 	and	r2, r1, #7			@ extract the length of the cache lines
 	add	r2, r2, #4			@ add 4 (line length offset)
 	ldr	r4, =0x3ff
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index b4ca325..7d2e44f 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1136,3 +1136,4 @@
 apq8064_cdp		MACH_APQ8064_CDP	APQ8064_CDP		3948
 apq8064_mtp		MACH_APQ8064_MTP	APQ8064_MTP		3949
 apq8064_liquid		MACH_APQ8064_LIQUID	APQ8064_LIQUID		3951
+msm7627a_qrd3		MACH_MSM7627A_QRD3	MSM7627A_QRD3		4005
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 7ceae89..07322cd 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -124,7 +124,8 @@
  */
 int chk_apps_master(void)
 {
-	if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615())
+	if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615() ||
+		 cpu_is_apq8064() || cpu_is_msm8627())
 		return 1;
 	else
 		return 0;
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index f2a2210..df2cd65 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -86,8 +86,8 @@
 				diagchar_ioctl(NULL, DIAG_IOCTL_COMMAND_REG,
 						 (unsigned long)pkt_params);
 				kfree(temp);
-				buf = buf + HDR_SIZ + data_len;
 			}
+			buf = buf + HDR_SIZ + data_len;
 		}
 	}
 	kfree(pkt_params);
diff --git a/drivers/char/hw_random/msm_rng.c b/drivers/char/hw_random/msm_rng.c
index b03a4ec..f5367ef 100644
--- a/drivers/char/hw_random/msm_rng.c
+++ b/drivers/char/hw_random/msm_rng.c
@@ -242,6 +242,9 @@
 
 static int __init msm_rng_init(void)
 {
+	if (cpu_is_apq8064())
+		return -ENODEV;
+
 	return platform_driver_register(&rng_driver);
 }
 
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index fc1cfb6..a6b0cf6 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -27,9 +27,11 @@
 #include <linux/memory_alloc.h>
 #include <linux/seq_file.h>
 #include <linux/fmem.h>
+#include <linux/iommu.h>
 #include <mach/msm_memtypes.h>
 #include <mach/scm.h>
-#include "ion_priv.h"
+#include <mach/iommu_domains.h>
+ #include "ion_priv.h"
 
 #include <asm/mach/map.h>
 
@@ -566,6 +568,103 @@
 	return ret_value;
 }
 
+static int ion_cp_heap_map_iommu(struct ion_buffer *buffer,
+				struct ion_iommu_map *data,
+				unsigned int domain_num,
+				unsigned int partition_num,
+				unsigned long align,
+				unsigned long iova_length,
+				unsigned long flags)
+{
+	unsigned long temp_phys, temp_iova;
+	struct iommu_domain *domain;
+	int i, ret = 0;
+	unsigned long extra;
+
+	data->mapped_size = iova_length;
+
+	if (!msm_use_iommu()) {
+		data->iova_addr = buffer->priv_phys;
+		return 0;
+	}
+
+	extra = iova_length - buffer->size;
+
+	data->iova_addr = msm_allocate_iova_address(domain_num, partition_num,
+						data->mapped_size, align);
+
+	if (!data->iova_addr) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	domain = msm_get_iommu_domain(domain_num);
+
+	if (!domain) {
+		ret = -ENOMEM;
+		goto out1;
+	}
+
+	temp_iova = data->iova_addr;
+	temp_phys = buffer->priv_phys;
+	for (i = buffer->size; i > 0; i -= SZ_4K, temp_iova += SZ_4K,
+						  temp_phys += SZ_4K) {
+		ret = iommu_map(domain, temp_iova, temp_phys,
+				get_order(SZ_4K),
+				ION_IS_CACHED(flags) ? 1 : 0);
+
+		if (ret) {
+			pr_err("%s: could not map %lx to %lx in domain %p\n",
+				__func__, temp_iova, temp_phys, domain);
+			goto out2;
+		}
+	}
+
+	if (extra && (msm_iommu_map_extra(domain, temp_iova, extra, flags) < 0))
+		goto out2;
+
+	return 0;
+
+out2:
+	for ( ; i < buffer->size; i += SZ_4K, temp_iova -= SZ_4K)
+		iommu_unmap(domain, temp_iova, get_order(SZ_4K));
+out1:
+	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+				data->mapped_size);
+out:
+	return ret;
+}
+
+static void ion_cp_heap_unmap_iommu(struct ion_iommu_map *data)
+{
+	int i;
+	unsigned long temp_iova;
+	unsigned int domain_num;
+	unsigned int partition_num;
+	struct iommu_domain *domain;
+
+	if (!msm_use_iommu())
+		return;
+
+	domain_num = iommu_map_domain(data);
+	partition_num = iommu_map_partition(data);
+
+	domain = msm_get_iommu_domain(domain_num);
+
+	if (!domain) {
+		WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
+		return;
+	}
+
+	temp_iova = data->iova_addr;
+	for (i = data->mapped_size; i > 0; i -= SZ_4K, temp_iova += SZ_4K)
+		iommu_unmap(domain, temp_iova, get_order(SZ_4K));
+
+	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+				data->mapped_size);
+
+	return;
+}
 
 static struct ion_heap_ops cp_heap_ops = {
 	.allocate = ion_cp_heap_allocate,
@@ -581,6 +680,8 @@
 	.print_debug = ion_cp_print_debug,
 	.secure_heap = ion_cp_secure_heap,
 	.unsecure_heap = ion_cp_unsecure_heap,
+	.map_iommu = ion_cp_heap_map_iommu,
+	.unmap_iommu = ion_cp_heap_unmap_iommu,
 };
 
 struct ion_heap *ion_cp_heap_create(struct ion_platform_heap *heap_data)
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 805e2b6..bde4045 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -131,31 +131,35 @@
 	struct adreno_gpudev *gpudev;
 	unsigned int istore_size;
 	unsigned int pix_shader_start;
+	unsigned int instruction_size; /* Size of an instruction in dwords */
 } adreno_gpulist[] = {
 	{ ADRENO_REV_A200, 0, 2, ANY_ID, ANY_ID,
 		"yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev,
-		512, 384},
+		512, 384, 3},
 	{ ADRENO_REV_A205, 0, 1, 0, ANY_ID,
 		"yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev,
-		512, 384},
+		512, 384, 3},
 	{ ADRENO_REV_A220, 2, 1, ANY_ID, ANY_ID,
 		"leia_pm4_470.fw", "leia_pfp_470.fw", &adreno_a2xx_gpudev,
-		512, 384},
+		512, 384, 3},
 	/*
 	 * patchlevel 5 (8960v2) needs special pm4 firmware to work around
 	 * a hardware problem.
 	 */
 	{ ADRENO_REV_A225, 2, 2, 0, 5,
 		"a225p5_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
-		1536, 768 },
+		1536, 768, 3 },
 	{ ADRENO_REV_A225, 2, 2, 0, 6,
 		"a225_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
-		1536, 768 },
+		1536, 768, 3 },
 	{ ADRENO_REV_A225, 2, 2, ANY_ID, ANY_ID,
 		"a225_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
-		1536, 768 },
+		1536, 768, 3 },
+	/* A3XX doesn't use the pix_shader_start */
 	{ ADRENO_REV_A320, 3, 1, ANY_ID, ANY_ID,
-		"a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev },
+		"a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev,
+		512, 0, 2 },
+
 };
 
 static irqreturn_t adreno_isr(int irq, void *data)
@@ -248,6 +252,16 @@
 	unsigned int mh_mmu_invalidate = 0x00000003; /*invalidate all and tc */
 
 	/*
+	 * A3XX doesn't support the fast path (the registers don't even exist)
+	 * so just bail out early
+	 */
+
+	if (adreno_is_a3xx(adreno_dev)) {
+		kgsl_mmu_device_setstate(device, flags);
+		return;
+	}
+
+	/*
 	 * If possible, then set the state via the command stream to avoid
 	 * a CPU idle.  Otherwise, use the default setstate which uses register
 	 * writes For CFF dump we must idle and use the registers so that it is
@@ -442,6 +456,7 @@
 	adreno_dev->pm4_fwfile = adreno_gpulist[i].pm4fw;
 	adreno_dev->istore_size = adreno_gpulist[i].istore_size;
 	adreno_dev->pix_shader_start = adreno_gpulist[i].pix_shader_start;
+	adreno_dev->instruction_size = adreno_gpulist[i].instruction_size;
 }
 
 static int __devinit
@@ -819,7 +834,11 @@
 	unsigned int rbbm_status;
 	unsigned long wait_timeout =
 		msecs_to_jiffies(adreno_dev->wait_timeout);
-	unsigned long wait_time = jiffies + wait_timeout;
+	unsigned long wait_time;
+	unsigned long wait_time_part;
+	unsigned int msecs;
+	unsigned int msecs_first;
+	unsigned int msecs_part;
 
 	kgsl_cffdump_regpoll(device->id,
 		adreno_dev->gpudev->reg_rbbm_status << 2,
@@ -829,8 +848,18 @@
 	 */
 retry:
 	if (rb->flags & KGSL_FLAGS_STARTED) {
+		msecs = adreno_dev->wait_timeout;
+		msecs_first = (msecs <= 100) ? ((msecs + 4) / 5) : 100;
+		msecs_part = (msecs - msecs_first + 3) / 4;
+		wait_time = jiffies + wait_timeout;
+		wait_time_part = jiffies + msecs_to_jiffies(msecs_first);
 		adreno_poke(device);
 		do {
+			if (time_after(jiffies, wait_time_part)) {
+				adreno_poke(device);
+				wait_time_part = jiffies +
+					msecs_to_jiffies(msecs_part);
+			}
 			GSL_RB_GET_READPTR(rb, &rb->rptr);
 			if (time_after(jiffies, wait_time)) {
 				KGSL_DRV_ERR(device, "rptr: %x, wptr: %x\n",
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 9c2d704..9498b80 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -39,12 +39,7 @@
 #define ADRENO_DEFAULT_PWRSCALE_POLICY  NULL
 #endif
 
-/*
- * constants for the size of shader instructions
- */
-#define ADRENO_ISTORE_BYTES 12
-#define ADRENO_ISTORE_WORDS 3
-#define ADRENO_ISTORE_START 0x5000
+#define ADRENO_ISTORE_START 0x5000 /* Istore offset */
 
 enum adreno_gpurev {
 	ADRENO_REV_UNKNOWN = 0,
@@ -75,6 +70,7 @@
 	unsigned int wait_timeout;
 	unsigned int istore_size;
 	unsigned int pix_shader_start;
+	unsigned int instruction_size;
 };
 
 struct adreno_gpudev {
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index e31b76b..f2b1278 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -164,7 +164,8 @@
 
 static inline int _shader_shadow_size(struct adreno_device *adreno_dev)
 {
-	return adreno_dev->istore_size*ADRENO_ISTORE_BYTES;
+	return adreno_dev->istore_size *
+		(adreno_dev->instruction_size * sizeof(unsigned int));
 }
 
 static inline int _context_size(struct adreno_device *adreno_dev)
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 1bad811..f68bc41 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -34,7 +34,7 @@
 	0x01ea, 0x01ea, 0x01ee, 0x01f1, 0x01f5, 0x01f5, 0x01fc, 0x01ff,
 	0x0440, 0x0440, 0x0443, 0x0443, 0x0445, 0x0445, 0x044d, 0x044f,
 	0x0452, 0x0452, 0x0454, 0x046f, 0x047c, 0x047c, 0x047f, 0x047f,
-	0x0579, 0x057f, 0x0600, 0x0602, 0x0605, 0x0607, 0x060a, 0x060e,
+	0x0578, 0x057f, 0x0600, 0x0602, 0x0605, 0x0607, 0x060a, 0x060e,
 	0x0612, 0x0614, 0x0c01, 0x0c02, 0x0c06, 0x0c1d, 0x0c3d, 0x0c3f,
 	0x0c48, 0x0c4b, 0x0c80, 0x0c80, 0x0c88, 0x0c8b, 0x0ca0, 0x0cb7,
 	0x0cc0, 0x0cc1, 0x0cc6, 0x0cc7, 0x0ce4, 0x0ce5, 0x0e00, 0x0e05,
@@ -127,13 +127,8 @@
 #define HLSQ_MEMOBJ_OFFSET  0x400
 #define HLSQ_MIPMAP_OFFSET  0x800
 
-#ifdef GSL_USE_A3XX_HLSQ_SHADOW_RAM
 /* Use shadow RAM */
 #define HLSQ_SHADOW_BASE		(0x10000+SSIZE*2)
-#else
-/* Use working RAM */
-#define HLSQ_SHADOW_BASE		0x10000
-#endif
 
 #define REG_TO_MEM_LOOP_COUNT_SHIFT	15
 
@@ -258,7 +253,7 @@
 				       struct adreno_context *drawctxt)
 {
 	unsigned int *cmd = tmp_ctx.cmd;
-	unsigned int *start = cmd;
+	unsigned int *start;
 	unsigned int i;
 
 	drawctxt->constant_save_commands[0].hostptr = cmd;
@@ -266,6 +261,8 @@
 	    virt2gpu(cmd, &drawctxt->gpustate);
 	cmd++;
 
+	start = cmd;
+
 	*cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
 	*cmd++ = 0;
 
@@ -1313,7 +1310,8 @@
 		_SET(SP_FSCTRLREG1_FSINITIALOUTSTANDING, 2) |
 		_SET(SP_FSCTRLREG1_HALFPRECVAROFFSET, 63);
 	/* SP_FS_OBJ_OFFSET_REG */
-	*cmds++ = _SET(SP_OBJOFFSETREG_CONSTOBJECTSTARTOFFSET, 128);
+	*cmds++ = _SET(SP_OBJOFFSETREG_CONSTOBJECTSTARTOFFSET, 128) |
+		_SET(SP_OBJOFFSETREG_SHADEROBJOFFSETINIC, 1);
 	/* SP_FS_OBJ_START_REG */
 	*cmds++ = 0x00000000;
 
@@ -1329,7 +1327,7 @@
 	/* SP_FS_OUT_REG */
 	*cmds++ = _SET(SP_FSOUTREG_PAD0, SP_PIXEL_BASED);
 
-	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
 	*cmds++ = CP_REG(A3XX_SP_FS_MRT_REG_0);
 	/* SP_FS_MRT_REG0 */
 	*cmds++ = _SET(SP_FSMRTREG_REGID, 4);
@@ -1426,7 +1424,7 @@
 		_SET(VPC_VPCVARPSREPLMODE_COMPONENT16, 1) |
 		_SET(VPC_VPCVARPSREPLMODE_COMPONENT17, 2);
 
-	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 11);
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
 	*cmds++ = CP_REG(A3XX_SP_SP_CTRL_REG);
 	/* SP_SP_CTRL_REG */
 	*cmds++ = _SET(SP_SPCTRLREG_SLEEPMODE, 1);
@@ -1652,7 +1650,9 @@
 	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
 	*cmds++ = CP_REG(A3XX_GRAS_SC_CONTROL);
 	/* GRAS_SC_CONTROL */
-	*cmds++ = _SET(GRAS_SC_CONTROL_RASTER_MODE, 1);
+	/*cmds++ = _SET(GRAS_SC_CONTROL_RASTER_MODE, 1);
+		*cmds++ = _SET(GRAS_SC_CONTROL_RASTER_MODE, 1) |*/
+	*cmds++ = 0x04001000;
 
 	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
 	*cmds++ = CP_REG(A3XX_GRAS_SU_MODE_CONTROL);
@@ -2130,24 +2130,17 @@
 static int a3xx_create_gmem_shadow(struct adreno_device *adreno_dev,
 				 struct adreno_context *drawctxt)
 {
+	int result;
+
 	calc_gmemsize(&drawctxt->context_gmem_shadow,
 		adreno_dev->gmemspace.sizebytes);
 	tmp_ctx.gmem_base = adreno_dev->gmemspace.gpu_base;
 
-	if (drawctxt->flags & CTXT_FLAGS_GMEM_SHADOW) {
-		int result =
-		    kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
-			drawctxt->pagetable,
-			drawctxt->context_gmem_shadow.size);
+	result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
+		drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
 
-		if (result)
-			return result;
-	} else {
-		memset(&drawctxt->context_gmem_shadow.gmemshadow, 0,
-		       sizeof(drawctxt->context_gmem_shadow.gmemshadow));
-
-		return 0;
-	}
+	if (result)
+		return result;
 
 	build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow,
 		&tmp_ctx.cmd);
@@ -2163,6 +2156,8 @@
 	kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
 		KGSL_CACHE_OP_FLUSH);
 
+	drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW;
+
 	return 0;
 }
 
@@ -2431,10 +2426,7 @@
 #define A3XX_INT_MASK \
 	((1 << A3XX_INT_RBBM_AHB_ERROR) |        \
 	 (1 << A3XX_INT_RBBM_REG_TIMEOUT) |      \
-	 (1 << A3XX_INT_RBBM_ME_MS_TIMEOUT) |    \
-	 (1 << A3XX_INT_RBBM_PFP_MS_TIMEOUT) |   \
 	 (1 << A3XX_INT_RBBM_ATB_BUS_OVERFLOW) | \
-	 (1 << A3XX_INT_VFD_ERROR) |             \
 	 (1 << A3XX_INT_CP_T0_PACKET_IN_IB) |    \
 	 (1 << A3XX_INT_CP_OPCODE_ERROR) |       \
 	 (1 << A3XX_INT_CP_RESERVED_BIT_ERROR) | \
@@ -2444,7 +2436,6 @@
 	 (1 << A3XX_INT_CP_RB_INT) |             \
 	 (1 << A3XX_INT_CP_REG_PROTECT_FAULT) |  \
 	 (1 << A3XX_INT_CP_AHB_ERROR_HALT) |     \
-	 (1 << A3XX_INT_MISC_HANG_DETECT) |      \
 	 (1 << A3XX_INT_UCHE_OOB_ACCESS))
 
 static struct {
@@ -2474,7 +2465,7 @@
 	A3XX_IRQ_CALLBACK(a3xx_err_callback),  /* 21 - CP_AHB_ERROR_FAULT */
 	A3XX_IRQ_CALLBACK(NULL),	       /* 22 - Unused */
 	A3XX_IRQ_CALLBACK(NULL),	       /* 23 - Unused */
-	A3XX_IRQ_CALLBACK(a3xx_err_callback),  /* 24 - MISC_HANG_DETECT */
+	A3XX_IRQ_CALLBACK(NULL),	       /* 24 - MISC_HANG_DETECT */
 	A3XX_IRQ_CALLBACK(a3xx_err_callback),  /* 25 - UCHE_OOB_ACCESS */
 	/* 26 to 31 - Unused */
 };
@@ -2547,6 +2538,9 @@
 {
 	struct kgsl_device *device = &adreno_dev->dev;
 
+	/* GMEM size on A320 is 512K */
+	adreno_dev->gmemspace.sizebytes = SZ_512K;
+
 	/* Reset the core */
 	adreno_regwrite(device, A3XX_RBBM_SW_RESET_CMD,
 		0x00000001);
@@ -2570,10 +2564,17 @@
 	adreno_regwrite(device, A3XX_RBBM_AHB_CTL0, 0x00000001);
 
 	/* Enable AHB error reporting */
-	adreno_regwrite(device, A3XX_RBBM_AHB_CTL1, 0xA6FFFFFF);
+	adreno_regwrite(device, A3XX_RBBM_AHB_CTL1, 0x86FFFFFF);
 
 	/* Turn on the power counters */
 	adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, 0x00003000);
+
+	/* Turn on hang detection - this spews a lot of useful information
+	 * into the RBBM registers on a hang */
+
+	adreno_regwrite(device, A3XX_RBBM_INTERFACE_HANG_INT_CTL,
+			(1 << 16) | 0xFFF);
+
 }
 
 /* Defined in adreno_a3xx_snapshot.c */
diff --git a/drivers/gpu/msm/adreno_a3xx_snapshot.c b/drivers/gpu/msm/adreno_a3xx_snapshot.c
index aade50c..c8c7c441 100644
--- a/drivers/gpu/msm/adreno_a3xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a3xx_snapshot.c
@@ -80,7 +80,7 @@
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct kgsl_snapshot_debug *header = snapshot;
 	unsigned int *data = snapshot + sizeof(*header);
-	int i, size = adreno_dev->pm4_fw_size >> 2;
+	int i, size = adreno_dev->pm4_fw_size - 1;
 
 	if (remain < DEBUG_SECTION_SZ(size)) {
 		SNAPSHOT_ERR_NOMEM(device, "CP PM4 RAM DEBUG");
@@ -98,7 +98,7 @@
 	 */
 
 	adreno_regwrite(device, REG_CP_ME_RAM_RADDR, 0x0);
-	for (i = 0; i < adreno_dev->pm4_fw_size >> 2; i++)
+	for (i = 0; i < size; i++)
 		adreno_regread(device, REG_CP_ME_RAM_DATA, &data[i]);
 
 	return DEBUG_SECTION_SZ(size);
@@ -110,7 +110,7 @@
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct kgsl_snapshot_debug *header = snapshot;
 	unsigned int *data = snapshot + sizeof(*header);
-	int i, size = adreno_dev->pfp_fw_size >> 2;
+	int i, size = adreno_dev->pfp_fw_size - 1;
 
 	if (remain < DEBUG_SECTION_SZ(size)) {
 		SNAPSHOT_ERR_NOMEM(device, "CP PFP RAM DEBUG");
@@ -127,7 +127,7 @@
 	 * maintain always changing hardcoded constants
 	 */
 	kgsl_regwrite(device, A3XX_CP_PFP_UCODE_ADDR, 0x0);
-	for (i = 0; i < adreno_dev->pfp_fw_size >> 2; i++)
+	for (i = 0; i < size; i++)
 		adreno_regread(device, A3XX_CP_PFP_UCODE_DATA, &data[i]);
 
 	return DEBUG_SECTION_SZ(size);
@@ -175,7 +175,7 @@
 		return 0;
 	}
 
-	val = (id << 0x06) | (1 << 0x10);
+	val = (id << 8) | (1 << 16);
 
 	header->id = id;
 	header->count = DEBUGFS_BLOCK_SIZE;
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index c1b9e4c..b53ca8f 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -143,7 +143,8 @@
 		return 0;
 
 	adreno_dev = ADRENO_DEVICE(device);
-	count = adreno_dev->istore_size * ADRENO_ISTORE_WORDS;
+	count = adreno_dev->istore_size * adreno_dev->instruction_size;
+
 	remaining = count;
 	for (i = 0; i < count; i += rowc) {
 		unsigned int vals[rowc];
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index 9bf85cf..aeb89b3 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -86,7 +86,7 @@
 	gmem_restore_quad[7] = uint2float(shadow->width);
 
 	memcpy(shadow->quad_vertices.hostptr, gmem_copy_quad, QUAD_LEN << 2);
-	memcpy(shadow->quad_vertices_restore.hostptr, gmem_copy_quad,
+	memcpy(shadow->quad_vertices_restore.hostptr, gmem_restore_quad,
 		QUAD_RESTORE_LEN << 2);
 
 	memcpy(shadow->quad_texcoords.hostptr, gmem_copy_texcoord,
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index fb88a72..cc3f3e7 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -86,7 +86,7 @@
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	int count, i;
 
-	count = adreno_dev->istore_size * ADRENO_ISTORE_WORDS;
+	count = adreno_dev->istore_size * adreno_dev->instruction_size;
 
 	if (remain < (count * 4) + sizeof(*header)) {
 		KGSL_DRV_ERR(device,
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 1b6696b..512a262 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2231,6 +2231,7 @@
 int kgsl_device_platform_probe(struct kgsl_device *device,
 			       irqreturn_t (*dev_isr) (int, void*))
 {
+	int result;
 	int status = -EINVAL;
 	struct kgsl_memregion *regspace = NULL;
 	struct resource *res;
@@ -2291,6 +2292,9 @@
 		device->id, regspace->mmio_phys_base,
 		regspace->sizebytes, regspace->mmio_virt_base);
 
+	result = kgsl_drm_init(pdev);
+	if (result)
+		goto error_iounmap;
 
 	status = kgsl_register_device(device);
 	if (!status)
@@ -2426,11 +2430,6 @@
 			goto err;
 	}
 
-	result = kgsl_drm_init(NULL);
-
-	if (result)
-		goto err;
-
 	return 0;
 
 err:
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index dba2dfc..e3f6f3b 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,7 +17,6 @@
 #include "drmP.h"
 #include "drm.h"
 #include <linux/android_pmem.h>
-#include <linux/notifier.h>
 
 #include "kgsl.h"
 #include "kgsl_device.h"
@@ -39,6 +38,9 @@
 #define ENTRY_EMPTY -1
 #define ENTRY_NEEDS_CLEANUP -2
 
+#define DRM_KGSL_NOT_INITED -1
+#define DRM_KGSL_INITED   1
+
 #define DRM_KGSL_NUM_FENCE_ENTRIES (DRM_KGSL_HANDLE_WAIT_ENTRIES << 2)
 #define DRM_KGSL_HANDLE_WAIT_ENTRIES 5
 
@@ -127,6 +129,8 @@
 	struct list_head wait_list;
 };
 
+static int kgsl_drm_inited = DRM_KGSL_NOT_INITED;
+
 /* This is a global list of all the memory currently mapped in the MMU */
 static struct list_head kgsl_mem_list;
 
@@ -186,41 +190,6 @@
 	struct kgsl_device_private *devpriv[KGSL_DEVICE_MAX];
 };
 
-static int kgsl_ts_notifier_cb(struct notifier_block *blk,
-			       unsigned long code, void *_param);
-
-static struct notifier_block kgsl_ts_nb[KGSL_DEVICE_MAX];
-
-static int kgsl_drm_firstopen(struct drm_device *dev)
-{
-	int i;
-
-	for (i = 0; i < KGSL_DEVICE_MAX; i++) {
-		struct kgsl_device *device = kgsl_get_device(i);
-
-		if (device == NULL)
-			continue;
-
-		kgsl_ts_nb[i].notifier_call = kgsl_ts_notifier_cb;
-		kgsl_register_ts_notifier(device, &kgsl_ts_nb[i]);
-	}
-
-	return 0;
-}
-
-void kgsl_drm_lastclose(struct drm_device *dev)
-{
-	int i;
-
-	for (i = 0; i < KGSL_DEVICE_MAX; i++) {
-		struct kgsl_device *device = kgsl_get_device(i);
-		if (device == NULL)
-			continue;
-
-		kgsl_unregister_ts_notifier(device, &kgsl_ts_nb[i]);
-	}
-}
-
 void kgsl_drm_preclose(struct drm_device *dev, struct drm_file *file_priv)
 {
 }
@@ -268,74 +237,72 @@
 {
 	struct drm_kgsl_gem_object *priv = obj->driver_private;
 	int index;
+	int result = 0;
 
 	/* Return if the memory is already allocated */
 
 	if (kgsl_gem_memory_allocated(obj) || TYPE_IS_FD(priv->type))
 		return 0;
 
+	if (priv->pagetable == NULL) {
+		priv->pagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
+
+		if (priv->pagetable == NULL) {
+			DRM_ERROR("Unable to get the GPU MMU pagetable\n");
+			return -EINVAL;
+		}
+	}
+
 	if (TYPE_IS_PMEM(priv->type)) {
 		int type;
 
 		if (priv->type == DRM_KGSL_GEM_TYPE_EBI ||
-		    priv->type & DRM_KGSL_GEM_PMEM_EBI)
-			type = PMEM_MEMTYPE_EBI1;
-		else
-			type = PMEM_MEMTYPE_SMI;
-
-		priv->memdesc.physaddr =
-			pmem_kalloc(obj->size * priv->bufcount,
-				    type | PMEM_ALIGNMENT_4K);
-
-		if (IS_ERR((void *) priv->memdesc.physaddr)) {
-			DRM_ERROR("Unable to allocate PMEM memory\n");
-			return -ENOMEM;
+		    priv->type & DRM_KGSL_GEM_PMEM_EBI) {
+				type = PMEM_MEMTYPE_EBI1;
+				result = kgsl_sharedmem_ebimem_user(
+						&priv->memdesc,
+						priv->pagetable,
+						obj->size * priv->bufcount,
+						0);
+				if (result) {
+					DRM_ERROR(
+					"Unable to allocate PMEM memory\n");
+					return result;
+				}
 		}
-
-		priv->memdesc.size = obj->size * priv->bufcount;
+		else
+			return -EINVAL;
 
 	} else if (TYPE_IS_MEM(priv->type)) {
-		priv->memdesc.hostptr =
-			vmalloc_user(obj->size * priv->bufcount);
 
-		if (priv->memdesc.hostptr == NULL) {
-			DRM_ERROR("Unable to allocate vmalloc memory\n");
-			return -ENOMEM;
+		if (priv->type == DRM_KGSL_GEM_TYPE_KMEM ||
+			priv->type & DRM_KGSL_GEM_CACHE_MASK)
+				list_add(&priv->list, &kgsl_mem_list);
+
+		result = kgsl_sharedmem_vmalloc_user(&priv->memdesc,
+					priv->pagetable,
+					obj->size * priv->bufcount, 0);
+
+		if (result != 0) {
+				DRM_ERROR(
+				"Unable to allocate Vmalloc user memory\n");
+				return result;
 		}
-
-		priv->memdesc.size = obj->size * priv->bufcount;
-		priv->memdesc.ops = &kgsl_vmalloc_ops;
 	} else
 		return -EINVAL;
 
-	for (index = 0; index < priv->bufcount; index++)
+	for (index = 0; index < priv->bufcount; index++) {
 		priv->bufs[index].offset = index * obj->size;
-
+		priv->bufs[index].gpuaddr =
+			priv->memdesc.gpuaddr +
+			priv->bufs[index].offset;
+	}
+	priv->flags |= DRM_KGSL_GEM_FLAG_MAPPED;
 
 	return 0;
 }
 
 static void
-kgsl_gem_unmap(struct drm_gem_object *obj)
-{
-	struct drm_kgsl_gem_object *priv = obj->driver_private;
-
-	if (!priv->flags & DRM_KGSL_GEM_FLAG_MAPPED)
-		return;
-
-	kgsl_mmu_unmap(priv->pagetable, &priv->memdesc);
-
-	kgsl_mmu_putpagetable(priv->pagetable);
-	priv->pagetable = NULL;
-
-	if ((priv->type == DRM_KGSL_GEM_TYPE_KMEM) ||
-	    (priv->type & DRM_KGSL_GEM_CACHE_MASK))
-		list_del(&priv->list);
-
-	priv->flags &= ~DRM_KGSL_GEM_FLAG_MAPPED;
-}
-
-static void
 kgsl_gem_free_memory(struct drm_gem_object *obj)
 {
 	struct drm_kgsl_gem_object *priv = obj->driver_private;
@@ -346,12 +313,17 @@
 	kgsl_gem_mem_flush(&priv->memdesc,  priv->type,
 			   DRM_KGSL_GEM_CACHE_OP_FROM_DEV);
 
-	kgsl_gem_unmap(obj);
-
-	if (TYPE_IS_PMEM(priv->type))
-		pmem_kfree(priv->memdesc.physaddr);
-
 	kgsl_sharedmem_free(&priv->memdesc);
+
+	kgsl_mmu_putpagetable(priv->pagetable);
+	priv->pagetable = NULL;
+
+	if ((priv->type == DRM_KGSL_GEM_TYPE_KMEM) ||
+	    (priv->type & DRM_KGSL_GEM_CACHE_MASK))
+		list_del(&priv->list);
+
+	priv->flags &= ~DRM_KGSL_GEM_FLAG_MAPPED;
+
 }
 
 int
@@ -447,7 +419,7 @@
 
 	filp = fget(drm_fd);
 	if (unlikely(filp == NULL)) {
-		DRM_ERROR("Unable to ghet the DRM file descriptor\n");
+		DRM_ERROR("Unable to get the DRM file descriptor\n");
 		return -EINVAL;
 	}
 	file_priv = filp->private_data;
@@ -520,7 +492,7 @@
 
 	ret = drm_gem_handle_create(file_priv, obj, handle);
 
-	drm_gem_object_handle_unreference(obj);
+	drm_gem_object_unreference(obj);
 	INIT_LIST_HEAD(&priv->wait_list);
 
 	for (i = 0; i < DRM_KGSL_HANDLE_WAIT_ENTRIES; i++) {
@@ -695,109 +667,14 @@
 kgsl_gem_unbind_gpu_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv)
 {
-	struct drm_kgsl_gem_bind_gpu *args = data;
-	struct drm_gem_object *obj;
-	struct drm_kgsl_gem_object *priv;
-
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-
-	if (obj == NULL) {
-		DRM_ERROR("Invalid GEM handle %x\n", args->handle);
-		return -EBADF;
-	}
-
-	mutex_lock(&dev->struct_mutex);
-	priv = obj->driver_private;
-
-	if (--priv->bound == 0)
-		kgsl_gem_unmap(obj);
-
-	drm_gem_object_unreference(obj);
-	mutex_unlock(&dev->struct_mutex);
 	return 0;
 }
 
-static int
-kgsl_gem_map(struct drm_gem_object *obj)
-{
-	struct drm_kgsl_gem_object *priv = obj->driver_private;
-	int index;
-	int ret = -EINVAL;
-
-	if (priv->flags & DRM_KGSL_GEM_FLAG_MAPPED)
-		return 0;
-
-	/* Get the global page table */
-
-	if (priv->pagetable == NULL) {
-		priv->pagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
-
-		if (priv->pagetable == NULL) {
-			DRM_ERROR("Unable to get the GPU MMU pagetable\n");
-			return -EINVAL;
-		}
-	}
-
-	priv->memdesc.pagetable = priv->pagetable;
-
-	ret = kgsl_mmu_map(priv->pagetable, &priv->memdesc,
-			   GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
-
-	if (!ret) {
-		for (index = 0; index < priv->bufcount; index++) {
-			priv->bufs[index].gpuaddr =
-				priv->memdesc.gpuaddr +
-				priv->bufs[index].offset;
-		}
-	}
-
-	/* Add cached memory to the list to be cached */
-
-	if (priv->type == DRM_KGSL_GEM_TYPE_KMEM ||
-	    priv->type & DRM_KGSL_GEM_CACHE_MASK)
-		list_add(&priv->list, &kgsl_mem_list);
-
-	priv->flags |= DRM_KGSL_GEM_FLAG_MAPPED;
-
-	return ret;
-}
-
 int
 kgsl_gem_bind_gpu_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv)
 {
-	struct drm_kgsl_gem_bind_gpu *args = data;
-	struct drm_gem_object *obj;
-	struct drm_kgsl_gem_object *priv;
-	int ret = 0;
-
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-
-	if (obj == NULL) {
-		DRM_ERROR("Invalid GEM handle %x\n", args->handle);
-		return -EBADF;
-	}
-
-	mutex_lock(&dev->struct_mutex);
-	priv = obj->driver_private;
-
-	if (priv->bound++ == 0) {
-
-		if (!kgsl_gem_memory_allocated(obj)) {
-			DRM_ERROR("Memory not allocated for this object\n");
-			ret = -ENOMEM;
-			goto out;
-		}
-
-		ret = kgsl_gem_map(obj);
-
-		/* This is legacy behavior - use GET_BUFFERINFO instead */
-		args->gpuptr = priv->bufs[0].gpuaddr;
-	}
-out:
-	drm_gem_object_unreference(obj);
-	mutex_unlock(&dev->struct_mutex);
-	return ret;
+	return 0;
 }
 
 /* Allocate the memory and prepare it for CPU mapping */
@@ -1344,27 +1221,6 @@
 	fence->fence_id = ENTRY_NEEDS_CLEANUP;  /* Mark it as needing cleanup */
 }
 
-static int kgsl_ts_notifier_cb(struct notifier_block *blk,
-			       unsigned long code, void *_param)
-{
-	struct drm_kgsl_gem_object_fence *fence;
-	struct kgsl_device *device = kgsl_get_device(code);
-	int i;
-
-	/* loop through the fences to see what things can be processed */
-
-	for (i = 0; i < DRM_KGSL_NUM_FENCE_ENTRIES; i++) {
-		fence = &gem_buf_fence[i];
-		if (!fence->ts_valid || fence->ts_device != code)
-			continue;
-
-		if (kgsl_check_timestamp(device, fence->timestamp))
-			wakeup_fence_entries(fence);
-	}
-
-	return 0;
-}
-
 int
 kgsl_gem_lock_handle_ioctl(struct drm_device *dev, void *data,
 						   struct drm_file *file_priv)
@@ -1608,11 +1464,9 @@
 };
 
 static struct drm_driver driver = {
-	.driver_features = DRIVER_USE_PLATFORM_DEVICE | DRIVER_GEM,
+	.driver_features = DRIVER_GEM,
 	.load = kgsl_drm_load,
 	.unload = kgsl_drm_unload,
-	.firstopen = kgsl_drm_firstopen,
-	.lastclose = kgsl_drm_lastclose,
 	.preclose = kgsl_drm_preclose,
 	.suspend = kgsl_drm_suspend,
 	.resume = kgsl_drm_resume,
@@ -1643,8 +1497,13 @@
 {
 	int i;
 
+	/* Only initialize once */
+	if (kgsl_drm_inited == DRM_KGSL_INITED)
+		return 0;
+
+	kgsl_drm_inited = DRM_KGSL_INITED;
+
 	driver.num_ioctls = DRM_ARRAY_SIZE(kgsl_drm_ioctls);
-	driver.platform_device = dev;
 
 	INIT_LIST_HEAD(&kgsl_mem_list);
 
@@ -1654,10 +1513,11 @@
 		gem_buf_fence[i].fence_id = ENTRY_EMPTY;
 	}
 
-	return drm_init(&driver);
+	return drm_platform_init(&driver, dev);
 }
 
 void kgsl_drm_exit(void)
 {
-	drm_exit(&driver);
+	kgsl_drm_inited = DRM_KGSL_NOT_INITED;
+	drm_platform_exit(&driver, driver.kdriver.platform_device);
 }
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 36248ef..671479e 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -17,6 +17,7 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/iommu.h>
+#include <mach/socinfo.h>
 
 #include "kgsl.h"
 #include "kgsl_mmu.h"
@@ -534,9 +535,16 @@
 	int ret;
 
 	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
-		memdesc->gpuaddr = memdesc->physaddr;
-		return 0;
+		if (memdesc->sglen == 1) {
+			memdesc->gpuaddr = sg_phys(memdesc->sg);
+			return 0;
+		} else {
+			KGSL_CORE_ERR("Memory is not contigious "
+					"(sglen = %d)\n", memdesc->sglen);
+			return -EINVAL;
+		}
 	}
+
 	memdesc->gpuaddr = gen_pool_alloc_aligned(pagetable->pool,
 		memdesc->size, KGSL_MMU_ALIGN_SHIFT);
 
@@ -712,7 +720,14 @@
 
 void kgsl_mmu_set_mmutype(char *mmutype)
 {
-	kgsl_mmu_type = iommu_found() ? KGSL_MMU_TYPE_IOMMU : KGSL_MMU_TYPE_GPU;
+	/* Set the default MMU - GPU on <=8960 and nothing on >= 8064 */
+	kgsl_mmu_type =
+		cpu_is_apq8064() ? KGSL_MMU_TYPE_NONE : KGSL_MMU_TYPE_GPU;
+
+	/* Use the IOMMU if it is found */
+	if (iommu_found())
+		kgsl_mmu_type = KGSL_MMU_TYPE_IOMMU;
+
 	if (mmutype && !strncmp(mmutype, "gpummu", 6))
 		kgsl_mmu_type = KGSL_MMU_TYPE_GPU;
 	if (iommu_found() && mmutype && !strncmp(mmutype, "iommu", 5))
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index f99a546..c8b4707 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -303,6 +303,22 @@
 	return 0;
 }
 
+/*
+ * Before calling qup_config_core_on_en(), please make
+ * sure that QuPE core is in RESET state.
+ */
+static void
+qup_config_core_on_en(struct qup_i2c_dev *dev)
+{
+	uint32_t status;
+
+	status = readl_relaxed(dev->base + QUP_CONFIG);
+	status |= BIT(13);
+	writel_relaxed(status, dev->base + QUP_CONFIG);
+	/* making sure that write has really gone through */
+	mb();
+}
+
 static void
 qup_i2c_pwr_mgmt(struct qup_i2c_dev *dev, unsigned int state)
 {
@@ -313,6 +329,7 @@
 	} else {
 		qup_update_state(dev, QUP_RESET_STATE);
 		clk_disable_unprepare(dev->clk);
+		qup_config_core_on_en(dev);
 		clk_disable_unprepare(dev->pclk);
 	}
 }
diff --git a/drivers/leds/leds-pm8xxx.c b/drivers/leds/leds-pm8xxx.c
index 025b756..46199d8 100644
--- a/drivers/leds/leds-pm8xxx.c
+++ b/drivers/leds/leds-pm8xxx.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,6 +39,46 @@
 #define PM8XXX_DRV_LED_CTRL_MASK	0xf8
 #define PM8XXX_DRV_LED_CTRL_SHIFT	0x03
 
+#define SSBI_REG_ADDR_WLED_CTRL_BASE	0x25A
+#define SSBI_REG_ADDR_WLED_CTRL(n)	(SSBI_REG_ADDR_WLED_CTRL_BASE + (n) - 1)
+
+/* wled control registers */
+#define WLED_MOD_CTRL_REG		SSBI_REG_ADDR_WLED_CTRL(1)
+#define WLED_MAX_CURR_CFG_REG(n)	SSBI_REG_ADDR_WLED_CTRL(n + 2)
+#define WLED_BRIGHTNESS_CNTL_REG1(n)	SSBI_REG_ADDR_WLED_CTRL(n + 5)
+#define WLED_BRIGHTNESS_CNTL_REG2(n)	SSBI_REG_ADDR_WLED_CTRL(n + 6)
+#define WLED_SYNC_REG			SSBI_REG_ADDR_WLED_CTRL(11)
+#define WLED_OVP_CFG_REG		SSBI_REG_ADDR_WLED_CTRL(13)
+#define WLED_BOOST_CFG_REG		SSBI_REG_ADDR_WLED_CTRL(14)
+#define WLED_HIGH_POLE_CAP_REG		SSBI_REG_ADDR_WLED_CTRL(16)
+
+#define WLED_STRINGS			0x03
+#define WLED_OVP_VAL_MASK		0x30
+#define WLED_OVP_VAL_BIT_SHFT		0x04
+#define WLED_BOOST_LIMIT_MASK		0xE0
+#define WLED_BOOST_LIMIT_BIT_SHFT	0x05
+#define WLED_EN_MASK			0x01
+#define WLED_CP_SELECT_MAX		0x03
+#define WLED_CP_SELECT_MASK		0x03
+#define WLED_DIG_MOD_GEN_MASK		0x70
+#define WLED_CS_OUT_MASK		0x0E
+#define WLED_CTL_DLY_STEP		200
+#define WLED_CTL_DLY_MAX		1400
+#define WLED_CTL_DLY_MASK		0xE0
+#define WLED_CTL_DLY_BIT_SHFT		0x05
+#define WLED_MAX_CURR			25
+#define WLED_MAX_CURR_MASK		0x1F
+#define WLED_OP_FDBCK_MASK		0x1C
+#define WLED_OP_FDBCK_BIT_SHFT		0x02
+
+#define WLED_MAX_LEVEL			100
+#define WLED_8_BIT_MASK			0xFF
+#define WLED_8_BIT_SHFT			0x08
+#define WLED_MAX_DUTY_CYCLE		0xFFF
+
+#define WLED_SYNC_VAL			0x07
+#define WLED_SYNC_RESET_VAL		0x00
+
 #define MAX_FLASH_LED_CURRENT		300
 #define MAX_LC_LED_CURRENT		40
 #define MAX_KP_BL_LED_CURRENT		300
@@ -81,6 +121,8 @@
 	int			pwm_channel;
 	u32			pwm_period_us;
 	struct pm8xxx_pwm_duty_cycles *pwm_duty_cycles;
+	struct wled_config_data *wled_cfg;
+	int			max_current;
 };
 
 static void led_kp_set(struct pm8xxx_led_data *led, enum led_brightness value)
@@ -145,6 +187,79 @@
 			 led->id, rc);
 }
 
+static int
+led_wled_set(struct pm8xxx_led_data *led, enum led_brightness value)
+{
+	int rc, duty;
+	u8 val, i, num_wled_strings;
+
+	if (value > WLED_MAX_LEVEL)
+		value = WLED_MAX_LEVEL;
+
+	duty = (WLED_MAX_DUTY_CYCLE * value) / WLED_MAX_LEVEL;
+
+	num_wled_strings = led->wled_cfg->num_strings;
+
+	/* program brightness control registers */
+	for (i = 0; i < num_wled_strings; i++) {
+		rc = pm8xxx_readb(led->dev->parent,
+				WLED_BRIGHTNESS_CNTL_REG1(i), &val);
+		if (rc) {
+			dev_err(led->dev->parent, "can't read wled brightnes ctrl"
+				" register1 rc=%d\n", rc);
+			return rc;
+		}
+
+		val = (val & ~WLED_MAX_CURR_MASK) | (duty >> WLED_8_BIT_SHFT);
+		rc = pm8xxx_writeb(led->dev->parent,
+				WLED_BRIGHTNESS_CNTL_REG1(i), val);
+		if (rc) {
+			dev_err(led->dev->parent, "can't write wled brightness ctrl"
+				" register1 rc=%d\n", rc);
+			return rc;
+		}
+
+		val = duty & WLED_8_BIT_MASK;
+		rc = pm8xxx_writeb(led->dev->parent,
+				WLED_BRIGHTNESS_CNTL_REG2(i), val);
+		if (rc) {
+			dev_err(led->dev->parent, "can't write wled brightness ctrl"
+				" register2 rc=%d\n", rc);
+			return rc;
+		}
+	}
+
+	/* sync */
+	val = WLED_SYNC_VAL;
+	rc = pm8xxx_writeb(led->dev->parent, WLED_SYNC_REG, val);
+	if (rc) {
+		dev_err(led->dev->parent,
+			"can't read wled sync register rc=%d\n", rc);
+		return rc;
+	}
+
+	val = WLED_SYNC_RESET_VAL;
+	rc = pm8xxx_writeb(led->dev->parent, WLED_SYNC_REG, val);
+	if (rc) {
+		dev_err(led->dev->parent,
+			"can't read wled sync register rc=%d\n", rc);
+		return rc;
+	}
+	return 0;
+}
+
+static void wled_dump_regs(struct pm8xxx_led_data *led)
+{
+	int i;
+	u8 val;
+
+	for (i = 1; i < 17; i++) {
+		pm8xxx_readb(led->dev->parent,
+				SSBI_REG_ADDR_WLED_CTRL(i), &val);
+		pr_debug("WLED_CTRL_%d = 0x%x\n", i, val);
+	}
+}
+
 static int pm8xxx_led_pwm_work(struct pm8xxx_led_data *led)
 {
 	int duty_us;
@@ -168,21 +283,31 @@
 static void __pm8xxx_led_work(struct pm8xxx_led_data *led,
 					enum led_brightness level)
 {
+	int rc;
+
 	mutex_lock(&led->lock);
 
 	switch (led->id) {
 	case PM8XXX_ID_LED_KB_LIGHT:
 		led_kp_set(led, level);
-	break;
+		break;
 	case PM8XXX_ID_LED_0:
 	case PM8XXX_ID_LED_1:
 	case PM8XXX_ID_LED_2:
 		led_lc_set(led, level);
-	break;
+		break;
 	case PM8XXX_ID_FLASH_LED_0:
 	case PM8XXX_ID_FLASH_LED_1:
 		led_flash_set(led, level);
-	break;
+		break;
+	case PM8XXX_ID_WLED:
+		rc = led_wled_set(led, level);
+		if (rc < 0)
+			pr_err("wled brightness set failed %d\n", rc);
+		break;
+	default:
+		dev_err(led->cdev.dev, "unknown led id %d", led->id);
+		break;
 	}
 
 	mutex_unlock(&led->lock);
@@ -261,6 +386,9 @@
 			break;
 		}
 		break;
+	case PM8XXX_ID_WLED:
+		led->cdev.max_brightness = WLED_MAX_LEVEL;
+		break;
 	default:
 		rc = -EINVAL;
 		pr_err("LED Id is invalid");
@@ -279,6 +407,149 @@
 	return led->cdev.brightness;
 }
 
+static int __devinit init_wled(struct pm8xxx_led_data *led)
+{
+	int rc, i;
+	u8 val, num_wled_strings;
+
+	num_wled_strings = led->wled_cfg->num_strings;
+
+	/* program over voltage protection threshold */
+	if (led->wled_cfg->ovp_val > WLED_OVP_37V) {
+		dev_err(led->dev->parent, "Invalid ovp value");
+		return -EINVAL;
+	}
+
+	rc = pm8xxx_readb(led->dev->parent, WLED_OVP_CFG_REG, &val);
+	if (rc) {
+		dev_err(led->dev->parent, "can't read wled ovp config"
+			" register rc=%d\n", rc);
+		return rc;
+	}
+
+	val = (val & ~WLED_OVP_VAL_MASK) |
+		(led->wled_cfg->ovp_val << WLED_OVP_VAL_BIT_SHFT);
+
+	rc = pm8xxx_writeb(led->dev->parent, WLED_OVP_CFG_REG, val);
+	if (rc) {
+		dev_err(led->dev->parent, "can't write wled ovp config"
+			" register rc=%d\n", rc);
+		return rc;
+	}
+
+	/* program current boost limit and output feedback*/
+	if (led->wled_cfg->boost_curr_lim > WLED_CURR_LIMIT_1680mA) {
+		dev_err(led->dev->parent, "Invalid boost current limit");
+		return -EINVAL;
+	}
+
+	rc = pm8xxx_readb(led->dev->parent, WLED_BOOST_CFG_REG, &val);
+	if (rc) {
+		dev_err(led->dev->parent, "can't read wled boost config"
+			" register rc=%d\n", rc);
+		return rc;
+	}
+
+	val = (val & ~WLED_BOOST_LIMIT_MASK) |
+		(led->wled_cfg->boost_curr_lim << WLED_BOOST_LIMIT_BIT_SHFT);
+
+	val = (val & ~WLED_OP_FDBCK_MASK) |
+		(led->wled_cfg->op_fdbck << WLED_OP_FDBCK_BIT_SHFT);
+
+	rc = pm8xxx_writeb(led->dev->parent, WLED_BOOST_CFG_REG, val);
+	if (rc) {
+		dev_err(led->dev->parent, "can't write wled boost config"
+			" register rc=%d\n", rc);
+		return rc;
+	}
+
+	/* program high pole capacitance */
+	if (led->wled_cfg->cp_select > WLED_CP_SELECT_MAX) {
+		dev_err(led->dev->parent, "Invalid pole capacitance");
+		return -EINVAL;
+	}
+
+	rc = pm8xxx_readb(led->dev->parent, WLED_HIGH_POLE_CAP_REG, &val);
+	if (rc) {
+		dev_err(led->dev->parent, "can't read wled high pole"
+			" capacitance register rc=%d\n", rc);
+		return rc;
+	}
+
+	val = (val & ~WLED_CP_SELECT_MASK) | led->wled_cfg->cp_select;
+
+	rc = pm8xxx_writeb(led->dev->parent, WLED_HIGH_POLE_CAP_REG, val);
+	if (rc) {
+		dev_err(led->dev->parent, "can't write wled high pole"
+			" capacitance register rc=%d\n", rc);
+		return rc;
+	}
+
+	/* program activation delay and maximum current */
+	for (i = 0; i < num_wled_strings; i++) {
+		rc = pm8xxx_readb(led->dev->parent,
+				WLED_MAX_CURR_CFG_REG(i + 2), &val);
+		if (rc) {
+			dev_err(led->dev->parent, "can't read wled max current"
+				" config register rc=%d\n", rc);
+			return rc;
+		}
+
+		if ((led->wled_cfg->ctrl_delay_us % WLED_CTL_DLY_STEP) ||
+			(led->wled_cfg->ctrl_delay_us > WLED_CTL_DLY_MAX)) {
+			dev_err(led->dev->parent, "Invalid control delay\n");
+			return rc;
+		}
+
+		val = val / WLED_CTL_DLY_STEP;
+		val = (val & ~WLED_CTL_DLY_MASK) |
+			(led->wled_cfg->ctrl_delay_us << WLED_CTL_DLY_BIT_SHFT);
+
+		if ((led->max_current > WLED_MAX_CURR)) {
+			dev_err(led->dev->parent, "Invalid max current\n");
+			return -EINVAL;
+		}
+
+		val = (val & ~WLED_MAX_CURR_MASK) | led->max_current;
+
+		rc = pm8xxx_writeb(led->dev->parent,
+				WLED_MAX_CURR_CFG_REG(i + 2), val);
+		if (rc) {
+			dev_err(led->dev->parent, "can't write wled max current"
+				" config register rc=%d\n", rc);
+			return rc;
+		}
+	}
+
+	/* program digital module generator, cs out and enable the module */
+	rc = pm8xxx_readb(led->dev->parent, WLED_MOD_CTRL_REG, &val);
+	if (rc) {
+		dev_err(led->dev->parent, "can't read wled module ctrl"
+			" register rc=%d\n", rc);
+		return rc;
+	}
+
+	if (led->wled_cfg->dig_mod_gen_en)
+		val |= WLED_DIG_MOD_GEN_MASK;
+
+	if (led->wled_cfg->cs_out_en)
+		val |= WLED_CS_OUT_MASK;
+
+	val |= WLED_EN_MASK;
+
+	rc = pm8xxx_writeb(led->dev->parent, WLED_MOD_CTRL_REG, val);
+	if (rc) {
+		dev_err(led->dev->parent, "can't write wled module ctrl"
+			" register rc=%d\n", rc);
+		return rc;
+	}
+
+	/* dump wled registers */
+	wled_dump_regs(led);
+
+	return 0;
+}
+
 static int __devinit get_init_value(struct pm8xxx_led_data *led, u8 *val)
 {
 	int rc, offset;
@@ -300,6 +571,15 @@
 	case PM8XXX_ID_FLASH_LED_1:
 		addr = SSBI_REG_ADDR_FLASH_DRV1;
 		break;
+	case PM8XXX_ID_WLED:
+		rc = init_wled(led);
+		if (rc)
+			dev_err(led->cdev.dev, "can't initialize wled rc=%d\n",
+								rc);
+		return rc;
+	default:
+		dev_err(led->cdev.dev, "unknown led id %d", led->id);
+		return -EINVAL;
 	}
 
 	rc = pm8xxx_readb(led->dev->parent, addr, val);
@@ -351,6 +631,7 @@
 	return rc;
 }
 
+
 static int __devinit pm8xxx_led_probe(struct platform_device *pdev)
 {
 	const struct pm8xxx_led_platform_data *pdata = pdev->dev.platform_data;
@@ -388,9 +669,11 @@
 		led_dat->pwm_channel = led_cfg->pwm_channel;
 		led_dat->pwm_period_us = led_cfg->pwm_period_us;
 		led_dat->pwm_duty_cycles = led_cfg->pwm_duty_cycles;
+		led_dat->wled_cfg = led_cfg->wled_cfg;
+		led_dat->max_current = led_cfg->max_current;
 
 		if (!((led_dat->id >= PM8XXX_ID_LED_KB_LIGHT) &&
-				(led_dat->id <= PM8XXX_ID_FLASH_LED_1))) {
+				(led_dat->id < PM8XXX_ID_MAX))) {
 			dev_err(&pdev->dev, "invalid LED ID (%d) specified\n",
 						 led_dat->id);
 			rc = -EINVAL;
@@ -424,6 +707,12 @@
 			goto fail_id_check;
 		}
 
+		/* configure default state */
+		if (led_cfg->default_state)
+			led->cdev.brightness = led_dat->cdev.max_brightness;
+		else
+			led->cdev.brightness = LED_OFF;
+
 		if (led_cfg->mode != PM8XXX_LED_MODE_MANUAL) {
 			__pm8xxx_led_work(led_dat,
 					led_dat->cdev.max_brightness);
@@ -436,9 +725,10 @@
 					"configure LED, error: %d\n", rc);
 					goto fail_id_check;
 				}
+			schedule_work(&led->work);
 			}
 		} else {
-			__pm8xxx_led_work(led_dat, LED_OFF);
+			__pm8xxx_led_work(led_dat, led->cdev.brightness);
 		}
 	}
 
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index b1dc87e..ca44c34 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -226,3 +226,11 @@
 	  by QUP in the board file as QUP is used by
 	  applications other than camera.
 
+config S5K3L1YX
+	bool "Sensor S5K3L1YX (BAYER 12M)"
+	depends on MSM_CAMERA
+	---help---
+		Samsung 12 MP Bayer Sensor with auto focus, uses
+		4 mipi lanes, preview config = 1984 * 1508 at 30 fps,
+		snapshot config = 4000 * 3000 at 20 fps,
+		hfr video at 60, 90 and 120 fps.
diff --git a/drivers/media/video/msm/csi/msm_ispif.c b/drivers/media/video/msm/csi/msm_ispif.c
index af61bd2..86d62c9 100644
--- a/drivers/media/video/msm/csi/msm_ispif.c
+++ b/drivers/media/video/msm/csi/msm_ispif.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -73,43 +73,54 @@
 
 
 static struct ispif_device *ispif;
+atomic_t ispif_irq_cnt;
+spinlock_t  ispif_tasklet_lock;
+struct list_head ispif_tasklet_q;
 
 static uint32_t global_intf_cmd_mask = 0xFFFFFFFF;
 
-static int msm_ispif_intf_reset(uint8_t intftype)
+
+static int msm_ispif_intf_reset(uint8_t intfmask)
 {
 	int rc = 0;
-	uint32_t data;
+	uint32_t data = 0x1;
+	uint8_t intfnum = 0, mask = intfmask;
+	while (mask != 0) {
+		if (!(intfmask & (0x1 << intfnum))) {
+			mask >>= 1;
+			intfnum++;
+			continue;
+		}
+		switch (intfnum) {
+		case PIX0:
+			data = (0x1 << STROBED_RST_EN) +
+				(0x1 << PIX_VFE_RST_STB) +
+				(0x1 << PIX_CSID_RST_STB);
+			break;
 
-	switch (intftype) {
-	case PIX0:
-		data = (0x1 << STROBED_RST_EN) +
-			(0x1 << PIX_VFE_RST_STB) +
-			(0x1 << PIX_CSID_RST_STB);
+		case RDI0:
+			data = (0x1 << STROBED_RST_EN) +
+				(0x1 << RDI_VFE_RST_STB)  +
+				(0x1 << RDI_CSID_RST_STB);
+			break;
+
+		case RDI1:
+			data = (0x1 << STROBED_RST_EN) +
+				(0x1 << RDI_1_VFE_RST_STB) +
+				(0x1 << RDI_1_CSID_RST_STB);
+			break;
+
+		default:
+			rc = -EINVAL;
+			break;
+		}
+		mask >>= 1;
+		intfnum++;
+	}	/*end while */
+	if (rc >= 0) {
 		msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
-		break;
-
-	case RDI0:
-		data = (0x1 << STROBED_RST_EN) +
-			(0x1 << RDI_VFE_RST_STB)  +
-			(0x1 << RDI_CSID_RST_STB);
-		msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
-		break;
-
-	case RDI1:
-		data = (0x1 << STROBED_RST_EN) +
-			(0x1 << RDI_1_VFE_RST_STB) +
-			(0x1 << RDI_1_CSID_RST_STB);
-		msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
-		break;
-
-	default:
-		rc = -EINVAL;
-		break;
+		rc = wait_for_completion_interruptible(&ispif->reset_complete);
 	}
-	if (rc >= 0)
-		rc = wait_for_completion_interruptible(
-				&ispif->reset_complete);
 
 	return rc;
 }
@@ -244,97 +255,109 @@
 }
 
 static void
-msm_ispif_intf_cmd(uint8_t intftype, uint8_t intf_cmd_mask)
+msm_ispif_intf_cmd(uint8_t intfmask, uint8_t intf_cmd_mask)
 {
 	uint8_t vc = 0, val = 0;
-	uint32_t cid_mask = msm_ispif_get_cid_mask(intftype);
-
-	while (cid_mask != 0) {
-		if ((cid_mask & 0xf) != 0x0) {
-			val = (intf_cmd_mask>>(vc*2)) & 0x3;
-			global_intf_cmd_mask &= ~((0x3 & ~val)
-				<<((vc*2)+(intftype*8)));
-			CDBG("intf cmd  0x%x\n", global_intf_cmd_mask);
-			msm_io_w(global_intf_cmd_mask,
-				ispif->base + ISPIF_INTF_CMD_ADDR);
+	uint8_t mask = intfmask, intfnum = 0;
+	uint32_t cid_mask = 0;
+	while (mask != 0) {
+		if (!(intfmask & (0x1 << intfnum))) {
+			mask >>= 1;
+			intfnum++;
+			continue;
 		}
-		vc++;
-		cid_mask >>= 4;
+
+		cid_mask = msm_ispif_get_cid_mask(intfnum);
+		vc = 0;
+
+		while (cid_mask != 0) {
+			if ((cid_mask & 0xf) != 0x0) {
+				val = (intf_cmd_mask>>(vc*2)) & 0x3;
+				global_intf_cmd_mask |=
+					(0x3 << ((vc * 2) + (intfnum * 8)));
+				global_intf_cmd_mask &= ~((0x3 & ~val)
+					<< ((vc * 2) +
+					(intfnum * 8)));
+			}
+			vc++;
+			cid_mask >>= 4;
+		}
+		mask >>= 1;
+		intfnum++;
 	}
+	msm_io_w(global_intf_cmd_mask, ispif->base + ISPIF_INTF_CMD_ADDR);
 }
 
-static int msm_ispif_abort_intf_transfer(uint8_t intf)
+static int msm_ispif_abort_intf_transfer(uint8_t intfmask)
 {
 	int rc = 0;
 	uint8_t intf_cmd_mask = 0xAA;
-
-	CDBG("abort stream request\n");
+	uint8_t intfnum = 0, mask = intfmask;
 	mutex_lock(&ispif->mutex);
-	msm_ispif_intf_cmd(intf, intf_cmd_mask);
-	rc = msm_ispif_intf_reset(intf);
-	global_intf_cmd_mask |= 0xFF<<(intf * 8);
+	msm_ispif_intf_cmd(intfmask, intf_cmd_mask);
+	while (mask != 0) {
+		if (intfmask & (0x1 << intfnum))
+			global_intf_cmd_mask |= (0xFF << (intfnum * 8));
+		mask >>= 1;
+		intfnum++;
+	}
 	mutex_unlock(&ispif->mutex);
 	return rc;
 }
 
-static int msm_ispif_start_intf_transfer(uint8_t intf)
+static int msm_ispif_start_intf_transfer(uint8_t intfmask)
 {
-	uint32_t data;
 	uint8_t intf_cmd_mask = 0x55;
 	int rc = 0;
-
-	CDBG("start stream request\n");
 	mutex_lock(&ispif->mutex);
-	switch (intf) {
-	case PIX0:
-		data = msm_io_r(ispif->base + ISPIF_PIX_STATUS_ADDR);
-		if ((data & 0xf) != 0xf) {
-			CDBG("interface is busy\n");
-			mutex_unlock(&ispif->mutex);
-			return -EBUSY;
-		}
-		break;
-
-	case RDI0:
-		data  = msm_io_r(ispif->base + ISPIF_RDI_STATUS_ADDR);
-		ispif->start_ack_pending = 1;
-		break;
-
-	case RDI1:
-		data  = msm_io_r(ispif->base + ISPIF_RDI_1_STATUS_ADDR);
-		ispif->start_ack_pending = 1;
-		break;
-	}
-	msm_ispif_intf_cmd(intf, intf_cmd_mask);
+	rc = msm_ispif_intf_reset(intfmask);
+	msm_ispif_intf_cmd(intfmask, intf_cmd_mask);
 	mutex_unlock(&ispif->mutex);
 	return rc;
 }
 
-static int msm_ispif_stop_intf_transfer(uint8_t intf)
+static int msm_ispif_stop_intf_transfer(uint8_t intfmask)
 {
 	int rc = 0;
 	uint8_t intf_cmd_mask = 0x00;
-	CDBG("stop stream request\n");
+	uint8_t intfnum = 0, mask = intfmask;
 	mutex_lock(&ispif->mutex);
-	msm_ispif_intf_cmd(intf, intf_cmd_mask);
-	switch (intf) {
-	case PIX0:
-		while ((msm_io_r(ispif->base + ISPIF_PIX_STATUS_ADDR)
-			& 0xf) != 0xf) {
-			CDBG("Wait for Idle\n");
-		}
-		break;
+	msm_ispif_intf_cmd(intfmask, intf_cmd_mask);
+	while (mask != 0) {
+		if (intfmask & (0x1 << intfnum)) {
+			switch (intfnum) {
+			case PIX0:
+				while ((msm_io_r(ispif->base +
+					ISPIF_PIX_STATUS_ADDR)
+					& 0xf) != 0xf) {
+					CDBG("Wait for pix0 Idle\n");
+				}
+				break;
 
-	case RDI0:
-		while ((msm_io_r(ispif->base + ISPIF_RDI_STATUS_ADDR)
-			& 0xf) != 0xf) {
-			CDBG("Wait for Idle\n");
+			case RDI0:
+				while ((msm_io_r(ispif->base +
+					ISPIF_RDI_STATUS_ADDR)
+					& 0xf) != 0xf) {
+					CDBG("Wait for rdi0 Idle\n");
+				}
+				break;
+
+			case RDI1:
+				while ((msm_io_r(ispif->base +
+					ISPIF_RDI_1_STATUS_ADDR)
+					& 0xf) != 0xf) {
+					CDBG("Wait for rdi1 Idle\n");
+				}
+				break;
+
+			default:
+				break;
+			}
+			global_intf_cmd_mask |= (0xFF << (intfnum * 8));
 		}
-		break;
-	default:
-		break;
+		mask >>= 1;
+		intfnum++;
 	}
-	global_intf_cmd_mask |= 0xFF<<(intf * 8);
 	mutex_unlock(&ispif->mutex);
 	return rc;
 }
@@ -364,10 +387,77 @@
 	return rc;
 }
 
+static void ispif_do_tasklet(unsigned long data)
+{
+	unsigned long flags;
+
+	struct ispif_isr_queue_cmd *qcmd = NULL;
+	CDBG("=== ispif_do_tasklet start ===\n");
+
+	while (atomic_read(&ispif_irq_cnt)) {
+		spin_lock_irqsave(&ispif_tasklet_lock, flags);
+		qcmd = list_first_entry(&ispif_tasklet_q,
+			struct ispif_isr_queue_cmd, list);
+		atomic_sub(1, &ispif_irq_cnt);
+
+		if (!qcmd) {
+			spin_unlock_irqrestore(&ispif_tasklet_lock,
+				flags);
+			return;
+		}
+		list_del(&qcmd->list);
+		spin_unlock_irqrestore(&ispif_tasklet_lock,
+			flags);
+		if (qcmd->ispifInterruptStatus0 &
+			ISPIF_IRQ_STATUS_RDI_SOF_MASK) {
+			CDBG("ispif rdi irq status\n");
+		}
+		if (qcmd->ispifInterruptStatus1 &
+			ISPIF_IRQ_STATUS_RDI_SOF_MASK) {
+			CDBG("ispif rdi1 irq status\n");
+		}
+		kfree(qcmd);
+	}
+	CDBG("=== ispif_do_tasklet end ===\n");
+}
+
+DECLARE_TASKLET(ispif_tasklet, ispif_do_tasklet, 0);
+
+static void ispif_process_irq(struct ispif_irq_status *out)
+{
+	unsigned long flags;
+	struct ispif_isr_queue_cmd *qcmd;
+
+	CDBG("ispif_process_irq\n");
+	qcmd = kzalloc(sizeof(struct ispif_isr_queue_cmd),
+		GFP_ATOMIC);
+	if (!qcmd) {
+		pr_err("ispif_process_irq: qcmd malloc failed!\n");
+		return;
+	}
+	qcmd->ispifInterruptStatus0 = out->ispifIrqStatus0;
+	qcmd->ispifInterruptStatus1 = out->ispifIrqStatus1;
+
+	spin_lock_irqsave(&ispif_tasklet_lock, flags);
+	list_add_tail(&qcmd->list, &ispif_tasklet_q);
+
+	atomic_add(1, &ispif_irq_cnt);
+	spin_unlock_irqrestore(&ispif_tasklet_lock, flags);
+	tasklet_schedule(&ispif_tasklet);
+	return;
+}
+
 static inline void msm_ispif_read_irq_status(struct ispif_irq_status *out)
 {
 	out->ispifIrqStatus0 = msm_io_r(ispif->base +
-					ISPIF_IRQ_STATUS_ADDR);
+		ISPIF_IRQ_STATUS_ADDR);
+	out->ispifIrqStatus1 = msm_io_r(ispif->base +
+		ISPIF_IRQ_STATUS_1_ADDR);
+	msm_io_w(out->ispifIrqStatus0,
+		ispif->base + ISPIF_IRQ_CLEAR_ADDR);
+	msm_io_w(out->ispifIrqStatus1,
+		ispif->base + ISPIF_IRQ_CLEAR_1_ADDR);
+
 	CDBG("ispif->irq: Irq_status0 = 0x%x\n",
 		out->ispifIrqStatus0);
 	if (out->ispifIrqStatus0 & ISPIF_IRQ_STATUS_MASK) {
@@ -377,23 +467,14 @@
 			pr_err("%s: pix intf 0 overflow.\n", __func__);
 		if (out->ispifIrqStatus0 & (0x1 << RAW_INTF_0_OVERFLOW_IRQ))
 			pr_err("%s: rdi intf 0 overflow.\n", __func__);
-		if (out->ispifIrqStatus0 & ISPIF_IRQ_STATUS_RDI_SOF_MASK) {
-			if (ispif->start_ack_pending) {
-				v4l2_subdev_notify(&ispif->subdev,
-						NOTIFY_ISP_MSG_EVT,
-						(void *)MSG_ID_START_ACK);
-				ispif->start_ack_pending = 0;
-				/* stop stream at frame boundary */
-				msm_ispif_stop_intf_transfer(RDI0);
-			}
-			v4l2_subdev_notify(&ispif->subdev, NOTIFY_ISP_MSG_EVT,
-					(void *)MSG_ID_SOF_ACK);
+		if ((out->ispifIrqStatus0 & ISPIF_IRQ_STATUS_RDI_SOF_MASK) ||
+			(out->ispifIrqStatus1 &
+				ISPIF_IRQ_STATUS_RDI_SOF_MASK)) {
+			ispif_process_irq(out);
 		}
 	}
-	msm_io_w(out->ispifIrqStatus0,
-			ispif->base + ISPIF_IRQ_CLEAR_ADDR);
 	msm_io_w(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
-		 ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
+		ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
 }
 
 static irqreturn_t msm_io_ispif_irq(int irq_num, void *data)
@@ -414,6 +495,8 @@
 static int msm_ispif_init(const uint32_t *csid_version)
 {
 	int rc = 0;
+	spin_lock_init(&ispif_tasklet_lock);
+	INIT_LIST_HEAD(&ispif_tasklet_q);
 	rc = request_irq(ispif->irq->start, msm_io_ispif_irq,
 		IRQF_TRIGGER_RISING, "ispif", 0);
 
@@ -451,6 +534,7 @@
 
 	CDBG("%s, free_irq\n", __func__);
 	free_irq(ispif->irq->start, 0);
+	tasklet_kill(&ispif_tasklet);
 }
 
 void msm_ispif_vfe_get_cid(uint8_t intftype, char *cids, int *num)
diff --git a/drivers/media/video/msm/csi/msm_ispif.h b/drivers/media/video/msm/csi/msm_ispif.h
index deadc28..8f1dd12 100644
--- a/drivers/media/video/msm/csi/msm_ispif.h
+++ b/drivers/media/video/msm/csi/msm_ispif.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -36,6 +36,12 @@
 	struct clk *ispif_clk[5];
 };
 
+struct ispif_isr_queue_cmd {
+	struct list_head list;
+	uint32_t    ispifInterruptStatus0;
+	uint32_t    ispifInterruptStatus1;
+};
+
 #define VIDIOC_MSM_ISPIF_CFG \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct msm_ispif_params)
 
@@ -51,6 +57,12 @@
 #define ISPIF_OFF_IMMEDIATELY       (0x01 << 2)
 #define ISPIF_S_STREAM_SHIFT	4
 
+
+#define PIX_0 (0x01 << 0)
+#define RDI_0 (0x01 << 1)
+#define PIX_1 (0x01 << 2)
+#define RDI_1 (0x01 << 3)
+
 void msm_ispif_vfe_get_cid(uint8_t intftype, char *cids, int *num);
 
 #endif
diff --git a/drivers/media/video/msm/io/msm_io_util.c b/drivers/media/video/msm/io/msm_io_util.c
index 0ae247e..207f8be 100644
--- a/drivers/media/video/msm/io/msm_io_util.c
+++ b/drivers/media/video/msm/io/msm_io_util.c
@@ -40,29 +40,42 @@
 					goto cam_clk_set_err;
 				}
 			}
+			rc = clk_prepare(clk_ptr[i]);
+			if (rc < 0) {
+				pr_err("%s prepare failed\n",
+					   clk_info[i].clk_name);
+				goto cam_clk_prepare_err;
+			}
+
 			rc = clk_enable(clk_ptr[i]);
 			if (rc < 0) {
 				pr_err("%s enable failed\n",
 					   clk_info[i].clk_name);
-				goto cam_clk_set_err;
+				goto cam_clk_enable_err;
 			}
 		}
 	} else {
 		for (i = num_clk - 1; i >= 0; i--) {
-			if (clk_ptr[i] != NULL)
+			if (clk_ptr[i] != NULL) {
 				clk_disable(clk_ptr[i]);
+				clk_unprepare(clk_ptr[i]);
 				clk_put(clk_ptr[i]);
+			}
 		}
 	}
 	return rc;
 
 
+cam_clk_enable_err:
+	clk_unprepare(clk_ptr[i]);
+cam_clk_prepare_err:
 cam_clk_set_err:
 	clk_put(clk_ptr[i]);
 cam_clk_get_err:
 	for (i--; i >= 0; i--) {
 		if (clk_ptr[i] != NULL) {
 			clk_disable(clk_ptr[i]);
+			clk_unprepare(clk_ptr[i]);
 			clk_put(clk_ptr[i]);
 		}
 	}
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 22322b8..7680559 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -116,6 +116,7 @@
 	NOTIFY_ISP_MSG_EVT, /* arg = enum ISP_MESSAGE_ID */
 	NOTIFY_VFE_MSG_OUT, /* arg = struct isp_msg_output */
 	NOTIFY_VFE_MSG_STATS,  /* arg = struct isp_msg_stats */
+	NOTIFY_VFE_MSG_COMP_STATS, /* arg = struct msm_stats_buf */
 	NOTIFY_VFE_BUF_EVT, /* arg = struct msm_vfe_resp */
 	NOTIFY_ISPIF_STREAM, /* arg = enable parameter for s_stream */
 	NOTIFY_VPE_MSG_EVT,
@@ -426,7 +427,7 @@
 			int msg_type, struct msm_free_buf *buf,
 			uint32_t frame_id);
 int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
-			int msg_type, struct msm_free_buf *frame, int dirty);
+	int msg_type, struct msm_free_buf *frame, int dirty, int node_type);
 int msm_mctl_reserve_free_buf(struct msm_cam_media_controller *pmctl,
 				struct msm_cam_v4l2_dev_inst *pcam_inst,
 				int path, struct msm_free_buf *free_buf);
@@ -473,7 +474,7 @@
 int msm_mctl_pp_notify(struct msm_cam_media_controller *pmctl,
 			struct msm_mctl_pp_frame_info *pp_frame_info);
 int msm_mctl_img_mode_to_inst_index(struct msm_cam_media_controller *pmctl,
-					int out_type);
+					int out_type, int node_type);
 struct msm_frame_buffer *msm_mctl_buf_find(
 	struct msm_cam_media_controller *pmctl,
 	struct msm_cam_v4l2_dev_inst *pcam_inst, int del_buf,
diff --git a/drivers/media/video/msm/msm_io_8960.c b/drivers/media/video/msm/msm_io_8960.c
index 79294a3..d111452 100644
--- a/drivers/media/video/msm/msm_io_8960.c
+++ b/drivers/media/video/msm/msm_io_8960.c
@@ -29,6 +29,7 @@
 
 static struct clk *camio_jpeg_clk;
 static struct clk *camio_jpeg_pclk;
+static struct clk *camio_imem_clk;
 static struct regulator *fs_ijpeg;
 
 static struct platform_device *camio_dev;
@@ -129,6 +130,11 @@
 		clk = clk_get(NULL, "ijpeg_pclk");
 		break;
 
+	case CAMIO_IMEM_CLK:
+		camio_imem_clk =
+		clk = clk_get(NULL, "imem_clk");
+		break;
+
 	default:
 		break;
 	}
@@ -158,6 +164,10 @@
 		clk = camio_jpeg_pclk;
 		break;
 
+	case CAMIO_IMEM_CLK:
+		clk = camio_imem_clk;
+		break;
+
 	default:
 		break;
 	}
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 6b3aef7..bb50d77 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -142,7 +142,7 @@
 {
 	int rc = -EINVAL, image_mode;
 	struct msm_vfe_resp *vdata = (struct msm_vfe_resp *)arg;
-	struct msm_free_buf free_buf;
+	struct msm_free_buf free_buf, temp_free_buf;
 	struct msm_camvfe_params vfe_params;
 	struct msm_vfe_cfg_cmd cfgcmd;
 	struct msm_sync *sync =
@@ -190,7 +190,12 @@
 		vfe_params.vfe_cfg = &cfgcmd;
 		vfe_params.data = (void *)&free_buf;
 		rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
-		/* Write the same buffer into PONG */
+		temp_free_buf = free_buf;
+		if (msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+					image_mode, &free_buf)) {
+			/* Write the same buffer into PONG */
+			free_buf = temp_free_buf;
+		}
 		cfgcmd.cmd_type = CMD_CONFIG_PONG_ADDR;
 		cfgcmd.value = &vfe_id;
 		vfe_params.vfe_cfg = &cfgcmd;
@@ -307,6 +312,36 @@
 		}
 		}
 		break;
+	case NOTIFY_VFE_MSG_COMP_STATS: {
+		struct msm_stats_buf *stats = (struct msm_stats_buf *)arg;
+		struct msm_stats_buf *stats_buf = NULL;
+
+		isp_event->isp_data.isp_msg.msg_id = MSG_ID_STATS_COMPOSITE;
+		stats->aec.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+					stats->aec.buff, &(stats->aec.fd));
+		stats->awb.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+					stats->awb.buff, &(stats->awb.fd));
+		stats->af.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+					stats->af.buff, &(stats->af.fd));
+		stats->ihist.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+					stats->ihist.buff, &(stats->ihist.fd));
+		stats->rs.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+					stats->rs.buff, &(stats->rs.fd));
+		stats->cs.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+					stats->cs.buff, &(stats->cs.fd));
+
+		stats_buf = kmalloc(sizeof(struct msm_stats_buf), GFP_ATOMIC);
+		if (!stats_buf) {
+			pr_err("%s: out of memory.\n", __func__);
+			rc = -ENOMEM;
+		} else {
+			*stats_buf = *stats;
+			isp_event->isp_data.isp_msg.len	=
+				sizeof(struct msm_stats_buf);
+			isp_event->isp_data.isp_msg.data = stats_buf;
+		}
+		}
+		break;
 	case NOTIFY_VFE_MSG_STATS: {
 		struct msm_stats_buf stats;
 		struct isp_msg_stats *isp_stats = (struct isp_msg_stats *)arg;
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 2c4fbe4..13d1daf 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -241,6 +241,7 @@
 	case NOTIFY_ISP_MSG_EVT:
 	case NOTIFY_VFE_MSG_OUT:
 	case NOTIFY_VFE_MSG_STATS:
+	case NOTIFY_VFE_MSG_COMP_STATS:
 	case NOTIFY_VFE_BUF_EVT:
 	case NOTIFY_VFE_BUF_FREE_EVT:
 		if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 1ab76fe..8148f1f 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -325,9 +325,13 @@
 }
 
 int msm_mctl_img_mode_to_inst_index(struct msm_cam_media_controller *pmctl,
-					int image_mode)
+					int image_mode, int node_type)
 {
-	if ((image_mode >= 0) &&
+	if ((image_mode >= 0) && node_type &&
+		pmctl->sync.pcam_sync->mctl_node.dev_inst_map[image_mode])
+		return pmctl->sync.pcam_sync->
+				mctl_node.dev_inst_map[image_mode]->my_index;
+	else if ((image_mode >= 0) &&
 		pmctl->sync.pcam_sync->dev_inst_map[image_mode])
 		return	pmctl->sync.pcam_sync->
 				dev_inst_map[image_mode]->my_index;
@@ -424,13 +428,13 @@
 
 	msm_mctl_check_pp(p_mctl, image_mode, &pp_divert_type, &pp_type);
 	D("%s: pp_type=%d, pp_divert_type = %d, frame_id = 0x%x",
-		 __func__, pp_type, pp_divert_type, frame_id);
+		__func__, pp_type, pp_divert_type, frame_id);
 	if (pp_type || pp_divert_type)
 		rc = msm_mctl_do_pp_divert(p_mctl,
 		image_mode, fbuf, frame_id, pp_type);
 	else {
 		idx = msm_mctl_img_mode_to_inst_index(
-				p_mctl, image_mode);
+				p_mctl, image_mode, 0);
 		if (idx < 0) {
 			pr_err("%s Invalid instance, dropping buffer\n",
 				__func__);
@@ -450,6 +454,22 @@
 	return 0;
 }
 
+static int is_buffer_queued(struct msm_cam_v4l2_device *pcam, int image_mode)
+{
+	int idx;
+	int ret = 0;
+	struct msm_frame_buffer *buf = NULL;
+	struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
+	idx = pcam->mctl_node.dev_inst_map[image_mode]->my_index;
+	pcam_inst = pcam->mctl_node.dev_inst[idx];
+	list_for_each_entry(buf, &pcam_inst->free_vq, list) {
+		if (buf->state != MSM_BUFFER_STATE_QUEUED)
+			continue;
+		ret = 1;
+	}
+	return ret;
+}
+
 struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst(
 				struct msm_cam_media_controller *pmctl,
 				int image_mode)
@@ -462,22 +482,39 @@
 		/* Valid image mode. Search the mctl node first.
 		 * If mctl node doesnt have the instance, then
 		 * search in the user's video node */
-		if (pcam->mctl_node.dev_inst_map[image_mode]) {
-			idx =
-			pcam->mctl_node.dev_inst_map[image_mode]->my_index;
-			pcam_inst = pcam->mctl_node.dev_inst[idx];
-			D("%s Found instance %p in mctl node device\n",
+		if (pmctl->vfe_output_mode == VFE_OUTPUTS_MAIN_AND_THUMB
+		|| pmctl->vfe_output_mode == VFE_OUTPUTS_THUMB_AND_MAIN) {
+			if (pcam->mctl_node.dev_inst_map[image_mode]
+			&& is_buffer_queued(pcam, image_mode)) {
+				idx =
+				pcam->mctl_node.dev_inst_map[image_mode]
+				->my_index;
+				pcam_inst = pcam->mctl_node.dev_inst[idx];
+				D("%s Found instance %p in mctl node device\n",
+				  __func__, pcam_inst);
+			} else if (pcam->dev_inst_map[image_mode]) {
+				idx = pcam->dev_inst_map[image_mode]->my_index;
+				pcam_inst = pcam->dev_inst[idx];
+				D("%s Found instance %p in video device",
 				__func__, pcam_inst);
-		} else if (pcam->dev_inst_map[image_mode]) {
-			idx = pcam->dev_inst_map[image_mode]->my_index;
-			pcam_inst = pcam->dev_inst[idx];
-			D("%s Found instance %p in video device",
+			}
+		} else {
+			if (pcam->mctl_node.dev_inst_map[image_mode]) {
+				idx = pcam->mctl_node.dev_inst_map[image_mode]
+				->my_index;
+				pcam_inst = pcam->mctl_node.dev_inst[idx];
+				D("%s Found instance %p in mctl node device\n",
 				__func__, pcam_inst);
+			} else if (pcam->dev_inst_map[image_mode]) {
+				idx = pcam->dev_inst_map[image_mode]->my_index;
+				pcam_inst = pcam->dev_inst[idx];
+				D("%s Found instance %p in video device",
+				__func__, pcam_inst);
+			}
 		}
 	} else
 		pr_err("%s Invalid image mode %d. Return NULL\n",
 			__func__, image_mode);
-
 	return pcam_inst;
 }
 
@@ -597,19 +634,21 @@
 	return rc;
 }
 
-int msm_mctl_buf_done_pp(
-		struct msm_cam_media_controller *pmctl,
-		int image_mode, struct msm_free_buf *frame, int dirty)
+int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
+	int image_mode, struct msm_free_buf *frame, int dirty, int node_type)
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	int rc = 0, idx;
 
-	idx = msm_mctl_img_mode_to_inst_index(pmctl, image_mode);
+	idx = msm_mctl_img_mode_to_inst_index(pmctl, image_mode, node_type);
 	if (idx < 0) {
 		pr_err("%s Invalid instance, buffer not released\n", __func__);
 		return idx;
 	}
-	pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+	if (node_type)
+		pcam_inst = pmctl->sync.pcam_sync->mctl_node.dev_inst[idx];
+	else
+		pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
 	if (!pcam_inst) {
 		pr_err("%s Invalid instance, cannot send buf to user",
 			__func__);
@@ -638,7 +677,7 @@
 	int rc = -EINVAL, idx;
 
 	idx = msm_mctl_img_mode_to_inst_index(pmctl,
-		image_mode);
+		image_mode, 0);
 	if (idx < 0) {
 		pr_err("%s Invalid instance, cant get buffer\n", __func__);
 		return NULL;
@@ -677,7 +716,7 @@
 	struct msm_frame_buffer *buf = NULL;
 
 	idx = msm_mctl_img_mode_to_inst_index(pmctl,
-		image_mode);
+		image_mode, 0);
 	if (idx < 0) {
 		pr_err("%s Invalid instance, cant put buffer\n", __func__);
 		return idx;
@@ -712,7 +751,7 @@
 	int idx;
 
 	idx = msm_mctl_img_mode_to_inst_index(pmctl,
-		image_mode);
+		image_mode, 0);
 	if (idx < 0) {
 		pr_err("%s Invalid instance, cant delete buffer\n", __func__);
 		return idx;
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index 1593e7e..82c5bf7 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -95,20 +95,95 @@
 			*pp_type = OUTPUT_TYPE_V;
 		break;
 	case MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL:
+		pp_key = PP_THUMB;
+		if (p_mctl->pp_info.pp_key & pp_key)
+			*pp_divert_type = OUTPUT_TYPE_T;
 		if (p_mctl->pp_info.pp_ctrl.pp_msg_type == OUTPUT_TYPE_T)
 			*pp_type = OUTPUT_TYPE_T;
 		break;
 	default:
 		break;
 	}
-	if (p_mctl->pp_info.div_frame[image_mode].ch_paddr[0])
-		*pp_divert_type = 0;
+	if (p_mctl->vfe_output_mode != VFE_OUTPUTS_MAIN_AND_THUMB &&
+		p_mctl->vfe_output_mode != VFE_OUTPUTS_THUMB_AND_MAIN) {
+		if (p_mctl->pp_info.div_frame[image_mode].ch_paddr[0])
+			*pp_divert_type = 0;
+	}
 	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
 	D("%s: pp_type=%d, pp_divert_type = %d",
 	__func__, *pp_type, *pp_divert_type);
 	return rc;
 }
 
+static int is_buf_in_queue(struct msm_cam_v4l2_device *pcam,
+	struct msm_free_buf *fbuf, int image_mode)
+{
+	struct msm_frame_buffer *buf = NULL, *tmp;
+	struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
+	unsigned long flags = 0;
+	struct videobuf2_contig_pmem *mem;
+	uint32_t buf_idx, offset = 0;
+	uint32_t buf_phyaddr = 0;
+	int idx;
+	idx = pcam->mctl_node.dev_inst_map[image_mode]->my_index;
+	pcam_inst = pcam->mctl_node.dev_inst[idx];
+	spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
+	list_for_each_entry_safe(buf, tmp,
+	&pcam_inst->free_vq, list) {
+		buf_idx = buf->vidbuf.v4l2_buf.index;
+		mem = vb2_plane_cookie(&buf->vidbuf, 0);
+		if (mem->buffer_type ==	VIDEOBUF2_MULTIPLE_PLANES)
+			offset = mem->offset.data_offset +
+				pcam_inst->buf_offset[buf_idx][0].data_offset;
+		else
+			offset = mem->offset.sp_off.y_off;
+		buf_phyaddr = (unsigned long)
+			videobuf2_to_pmem_contig(&buf->vidbuf, 0) +
+			offset;
+		D("%s vb_idx=%d,vb_paddr=0x%x ch0=0x%x\n",
+		  __func__, buf->vidbuf.v4l2_buf.index,
+		  buf_phyaddr, fbuf->ch_paddr[0]);
+		if (fbuf->ch_paddr[0] == buf_phyaddr) {
+			spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+			return 1;
+		}
+	}
+	spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+	return 0;
+}
+static struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst_for_divert(
+		struct msm_cam_media_controller *pmctl,
+		int image_mode, struct msm_free_buf *fbuf, int *node_type)
+{
+	struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
+	struct msm_cam_v4l2_device *pcam = pmctl->sync.pcam_sync;
+	int idx;
+
+	if (image_mode >= 0) {
+		/* Valid image mode. Search the mctl node first.
+		 * If mctl node doesnt have the instance, then
+		 * search in the user's video node */
+		if (pcam->mctl_node.dev_inst_map[image_mode]
+		&& is_buf_in_queue(pcam, fbuf, image_mode)) {
+			idx =
+			pcam->mctl_node.dev_inst_map[image_mode]->my_index;
+			pcam_inst = pcam->mctl_node.dev_inst[idx];
+			*node_type = MCTL_NODE;
+			D("%s Found instance %p in mctl node device\n",
+				__func__, pcam_inst);
+		} else if (pcam->dev_inst_map[image_mode]) {
+			idx = pcam->dev_inst_map[image_mode]->my_index;
+			pcam_inst = pcam->dev_inst[idx];
+			*node_type = VIDEO_NODE;
+			D("%s Found instance %p in video device",
+				__func__, pcam_inst);
+		} else
+			pr_err("%s Invalid image mode %d. Return NULL\n",
+				   __func__, image_mode);
+	}
+		return pcam_inst;
+}
+
 int msm_mctl_do_pp_divert(
 	struct msm_cam_media_controller *p_mctl,
 	int image_mode, struct msm_free_buf *fbuf,
@@ -120,8 +195,10 @@
 	struct msm_cam_evt_divert_frame div;
 	struct msm_frame_buffer *vb = NULL;
 	struct videobuf2_contig_pmem *mem;
+	int node;
 
-	pcam_inst = msm_mctl_get_pcam_inst(p_mctl, image_mode);
+	pcam_inst = msm_mctl_get_pcam_inst_for_divert
+		(p_mctl, image_mode, fbuf, &node);
 	if (!pcam_inst) {
 		pr_err("%s Invalid instance. Cannot divert frame.\n",
 			__func__);
@@ -155,6 +232,7 @@
 	 * this buffer.*/
 	mem = vb2_plane_cookie(&vb->vidbuf, 0);
 	div.frame.path = mem->path;
+	div.frame.node_type = node;
 	if (mem->buffer_type == VIDEOBUF2_SINGLE_PLANE) {
 		/* This buffer contains only 1 plane. Use the
 		 * single planar structure to store the info.*/
@@ -670,7 +748,7 @@
 			done_frame.vb =
 				pp_frame_info->dest_frame.handle;
 			msm_mctl_buf_done_pp(
-				p_mctl, img_mode, &done_frame, 0);
+				p_mctl, img_mode, &done_frame, 0, 0);
 			D("%s: vpe done to app, vb=0x%x, path=%d, phy=0x%x",
 				__func__, done_frame.vb,
 				pp_frame_cmd->path, done_frame.ch_paddr[0]);
@@ -848,7 +926,7 @@
 	}
 	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
 	/* here buf.addr is phy_addr */
-	rc = msm_mctl_buf_done_pp(p_mctl, image_mode, &buf, dirty);
+	rc = msm_mctl_buf_done_pp(p_mctl, image_mode, &buf, dirty, 0);
 	return rc;
 }
 
@@ -882,6 +960,9 @@
 		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
 		break;
 	case OUTPUT_TYPE_T:
+		msg_type = VFE_MSG_OUTPUT_T;
+		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
+		break;
 	default:
 		rc = -EFAULT;
 		goto err;
@@ -895,7 +976,8 @@
 
 	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
 	D("%s Frame done id: %d\n", __func__, frame.frame_id);
-	rc = msm_mctl_buf_done_pp(p_mctl, image_mode, &buf, dirty);
+	rc = msm_mctl_buf_done_pp(p_mctl, image_mode,
+		&buf, dirty, frame.node_type);
 	return rc;
 err:
 	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 4b86bd8..99d9911 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -547,6 +547,10 @@
 
 	memset(&(vfe32_ctrl->csStatsControl), 0,
 		sizeof(struct vfe_stats_control));
+
+	vfe32_ctrl->frame_skip_cnt = 31;
+	vfe32_ctrl->frame_skip_pattern = 0xffffffff;
+	vfe32_ctrl->snapshot_frame_cnt = 0;
 }
 
 static void vfe32_reset(void)
@@ -589,6 +593,7 @@
 
 	vfe32_ctrl->operation_mode = *p;
 	vfe32_ctrl->stats_comp = *(++p);
+	vfe32_ctrl->hfr_mode = *(++p);
 
 	msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_CFG);
 	msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_MODULE_CFG);
@@ -684,10 +689,16 @@
 
 static void vfe32_start_common(void)
 {
+	uint32_t irq_mask = 0x00E00021;
 	vfe32_ctrl->start_ack_pending = TRUE;
 	CDBG("VFE opertaion mode = 0x%x, output mode = 0x%x\n",
 		vfe32_ctrl->operation_mode, vfe32_ctrl->outpath.output_mode);
-	msm_io_w(0x00EFE021, vfe32_ctrl->vfebase + VFE_IRQ_MASK_0);
+	if (vfe32_ctrl->stats_comp)
+		irq_mask |= VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK;
+	else
+		irq_mask |= 0x000FE000;
+
+	msm_io_w(irq_mask, vfe32_ctrl->vfebase + VFE_IRQ_MASK_0);
 	msm_io_w(VFE_IMASK_WHILE_STOPPING_1,
 		vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
 
@@ -2363,6 +2374,23 @@
 			goto proc_general_done;
 		}
 		break;
+	case VFE_CMD_FRAME_SKIP_CFG:
+		if (cmd->length != vfe32_cmd[cmd->id].length)
+			return -EINVAL;
+
+		cmdp = kmalloc(vfe32_cmd[cmd->id].length, GFP_ATOMIC);
+		if (!cmdp) {
+			rc = -ENOMEM;
+			goto proc_general_done;
+		}
+
+		CHECKED_COPY_FROM_USER(cmdp);
+		msm_io_memcpy(vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+			cmdp, (vfe32_cmd[cmd->id].length));
+		vfe32_ctrl->frame_skip_cnt = ((uint32_t)
+			*cmdp & VFE_FRAME_SKIP_PERIOD_MASK) + 1;
+		vfe32_ctrl->frame_skip_pattern = (uint32_t)(*(cmdp + 2));
+		break;
 	default:
 		if (cmd->length != vfe32_cmd[cmd->id].length)
 			return -EINVAL;
@@ -2389,47 +2417,73 @@
 static void vfe32_stats_af_ack(struct vfe_cmd_stats_ack *pAck)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&vfe32_ctrl->af_ack_lock, flags);
+	spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+		&vfe32_ctrl->comp_stats_ack_lock :
+		&vfe32_ctrl->af_ack_lock);
+	spin_lock_irqsave(lock, flags);
 	vfe32_ctrl->afStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
 	vfe32_ctrl->afStatsControl.ackPending = FALSE;
-	spin_unlock_irqrestore(&vfe32_ctrl->af_ack_lock, flags);
+	spin_unlock_irqrestore(lock, flags);
 }
 
 static void vfe32_stats_awb_ack(struct vfe_cmd_stats_ack *pAck)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&vfe32_ctrl->awb_ack_lock, flags);
+	spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+		&vfe32_ctrl->comp_stats_ack_lock :
+		&vfe32_ctrl->awb_ack_lock);
+	spin_lock_irqsave(lock, flags);
 	vfe32_ctrl->awbStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
 	vfe32_ctrl->awbStatsControl.ackPending = FALSE;
-	spin_unlock_irqrestore(&vfe32_ctrl->awb_ack_lock, flags);
+	spin_unlock_irqrestore(lock, flags);
 }
 
 static void vfe32_stats_aec_ack(struct vfe_cmd_stats_ack *pAck)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&vfe32_ctrl->aec_ack_lock, flags);
+	spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+		&vfe32_ctrl->comp_stats_ack_lock :
+		&vfe32_ctrl->aec_ack_lock);
+	spin_lock_irqsave(lock, flags);
 	vfe32_ctrl->aecStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
 	vfe32_ctrl->aecStatsControl.ackPending = FALSE;
-	spin_unlock_irqrestore(&vfe32_ctrl->aec_ack_lock, flags);
+	spin_unlock_irqrestore(lock, flags);
 }
 
 static void vfe32_stats_ihist_ack(struct vfe_cmd_stats_ack *pAck)
 {
+	unsigned long flags;
+	spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+		&vfe32_ctrl->comp_stats_ack_lock :
+		&vfe32_ctrl->ihist_ack_lock);
+	spin_lock_irqsave(lock, flags);
 	vfe32_ctrl->ihistStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
 	vfe32_ctrl->ihistStatsControl.ackPending = FALSE;
+	spin_unlock_irqrestore(lock, flags);
 }
 static void vfe32_stats_rs_ack(struct vfe_cmd_stats_ack *pAck)
 {
+	unsigned long flags;
+	spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+		&vfe32_ctrl->comp_stats_ack_lock :
+		&vfe32_ctrl->rs_ack_lock);
+	spin_lock_irqsave(lock, flags);
 	vfe32_ctrl->rsStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
 	vfe32_ctrl->rsStatsControl.ackPending = FALSE;
+	spin_unlock_irqrestore(lock, flags);
 }
 static void vfe32_stats_cs_ack(struct vfe_cmd_stats_ack *pAck)
 {
+	unsigned long flags;
+	spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+		&vfe32_ctrl->comp_stats_ack_lock :
+		&vfe32_ctrl->cs_ack_lock);
+	spin_lock_irqsave(lock, flags);
 	vfe32_ctrl->csStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
 	vfe32_ctrl->csStatsControl.ackPending = FALSE;
+	spin_unlock_irqrestore(lock, flags);
 }
 
-
 static inline void vfe32_read_irq_status(struct vfe32_irq_status *out)
 {
 	uint32_t *temp;
@@ -2559,30 +2613,43 @@
 		(vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB)) {
 		/* in snapshot mode */
 		/* later we need to add check for live snapshot mode. */
-		vfe32_ctrl->vfe_capture_count--;
-		/* if last frame to be captured: */
-		if (vfe32_ctrl->vfe_capture_count == 0) {
-			if (vfe32_ctrl->outpath.output_mode &
-					VFE32_OUTPUT_MODE_PRIMARY) {
-				msm_io_w(0, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
-				msm_io_w(0, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
-			}
-			if (vfe32_ctrl->outpath.output_mode &
-					VFE32_OUTPUT_MODE_SECONDARY) {
-				msm_io_w(0, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
-				msm_io_w(0, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
-			}
-			msm_io_w_mb(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+		if (vfe32_ctrl->frame_skip_pattern & (0x1 <<
+			(vfe32_ctrl->snapshot_frame_cnt %
+				vfe32_ctrl->frame_skip_cnt))) {
+			vfe32_ctrl->vfe_capture_count--;
+			/* if last frame to be captured: */
+			if (vfe32_ctrl->vfe_capture_count == 0) {
+				/* stop the bus output:write master enable = 0*/
+				if (vfe32_ctrl->outpath.output_mode &
+						VFE32_OUTPUT_MODE_PRIMARY) {
+					msm_io_w(0, vfe32_ctrl->vfebase +
+						vfe32_AXI_WM_CFG[vfe32_ctrl->
+							outpath.out0.ch0]);
+					msm_io_w(0, vfe32_ctrl->vfebase +
+						vfe32_AXI_WM_CFG[vfe32_ctrl->
+							outpath.out0.ch1]);
+				}
+				if (vfe32_ctrl->outpath.output_mode &
+						VFE32_OUTPUT_MODE_SECONDARY) {
+					msm_io_w(0, vfe32_ctrl->vfebase +
+						vfe32_AXI_WM_CFG[vfe32_ctrl->
+							outpath.out1.ch0]);
+					msm_io_w(0, vfe32_ctrl->vfebase +
+						vfe32_AXI_WM_CFG[vfe32_ctrl->
+							outpath.out1.ch1]);
+				}
+				msm_io_w_mb
+				(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
 				vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
-
-			/* then do reg_update. */
-			msm_io_w(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
-		}
-	} /* in snapshot mode. */
+				vfe32_ctrl->snapshot_frame_cnt = -1;
+				vfe32_ctrl->frame_skip_cnt = 31;
+				vfe32_ctrl->frame_skip_pattern = 0xffffffff;
+			} /*if snapshot count is 0*/
+		} /*if frame is not being dropped*/
+		vfe32_ctrl->snapshot_frame_cnt++;
+		/* then do reg_update. */
+		msm_io_w(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+	} /* if snapshot mode. */
 }
 
 static void vfe32_set_default_reg_values(void)
@@ -2654,6 +2721,13 @@
 			msm_io_w_mb(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
 				vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
 		}
+	} /* if raw snapshot mode. */
+	if ((vfe32_ctrl->hfr_mode != HFR_MODE_OFF) &&
+		(vfe32_ctrl->operation_mode == VFE_MODE_OF_OPERATION_VIDEO) &&
+		(vfe32_ctrl->vfeFrameId % vfe32_ctrl->hfr_mode != 0)) {
+		vfe32_ctrl->vfeFrameId++;
+		CDBG("Skip the SOF notification when HFR enabled\n");
+		return;
 	}
 	vfe32_ctrl->vfeFrameId++;
 	vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_SOF_ACK);
@@ -2907,11 +2981,6 @@
 	}
 }
 
-static void vfe32_process_stats_comb_irq(uint32_t *irqstatus)
-{
-	return;
-}
-
 static uint32_t  vfe32_process_stats_irq_common(uint32_t statsNum,
 						uint32_t newAddr) {
 
@@ -2971,17 +3040,23 @@
 
 	case statsIhistNum: {
 		msgStats.id = MSG_ID_STATS_IHIST;
+		spin_lock_irqsave(&vfe32_ctrl->ihist_ack_lock, flags);
 		vfe32_ctrl->ihistStatsControl.ackPending = TRUE;
+		spin_unlock_irqrestore(&vfe32_ctrl->ihist_ack_lock, flags);
 		}
 		break;
 	case statsRsNum: {
 		msgStats.id = MSG_ID_STATS_RS;
+		spin_lock_irqsave(&vfe32_ctrl->rs_ack_lock, flags);
 		vfe32_ctrl->rsStatsControl.ackPending = TRUE;
+		spin_unlock_irqrestore(&vfe32_ctrl->rs_ack_lock, flags);
 		}
 		break;
 	case statsCsNum: {
 		msgStats.id = MSG_ID_STATS_CS;
+		spin_lock_irqsave(&vfe32_ctrl->cs_ack_lock, flags);
 		vfe32_ctrl->csStatsControl.ackPending = TRUE;
+		spin_unlock_irqrestore(&vfe32_ctrl->cs_ack_lock, flags);
 		}
 		break;
 
@@ -2997,6 +3072,30 @@
 	return;
 }
 
+static void vfe_send_comp_stats_msg(uint32_t status_bits)
+{
+	struct msm_stats_buf msgStats;
+	uint32_t temp;
+
+	msgStats.frame_id = vfe32_ctrl->vfeFrameId;
+	msgStats.status_bits = status_bits;
+
+	msgStats.aec.buff = vfe32_ctrl->aecStatsControl.bufToRender;
+	msgStats.awb.buff = vfe32_ctrl->awbStatsControl.bufToRender;
+	msgStats.af.buff = vfe32_ctrl->afStatsControl.bufToRender;
+
+	msgStats.ihist.buff = vfe32_ctrl->ihistStatsControl.bufToRender;
+	msgStats.rs.buff = vfe32_ctrl->rsStatsControl.bufToRender;
+	msgStats.cs.buff = vfe32_ctrl->csStatsControl.bufToRender;
+
+	temp = msm_io_r(vfe32_ctrl->vfebase + VFE_STATS_AWB_SGW_CFG);
+	msgStats.awb_ymin = (0xFF00 & temp) >> 8;
+
+	v4l2_subdev_notify(&vfe32_ctrl->subdev,
+				NOTIFY_VFE_MSG_COMP_STATS,
+				&msgStats);
+}
+
 static void vfe32_process_stats_ae_irq(void)
 {
 	unsigned long flags;
@@ -3105,6 +3204,126 @@
 	}
 }
 
+static void vfe32_process_stats(uint32_t status_bits)
+{
+	unsigned long flags;
+	int32_t process_stats = false;
+	CDBG("%s, stats = 0x%x\n", __func__, status_bits);
+
+	spin_lock_irqsave(&vfe32_ctrl->comp_stats_ack_lock, flags);
+	if (status_bits & VFE_IRQ_STATUS0_STATS_AEC) {
+		if (!vfe32_ctrl->aecStatsControl.ackPending) {
+			vfe32_ctrl->aecStatsControl.ackPending = TRUE;
+			vfe32_ctrl->aecStatsControl.bufToRender =
+				vfe32_process_stats_irq_common(statsAeNum,
+				vfe32_ctrl->aecStatsControl.nextFrameAddrBuf);
+			process_stats = true;
+		} else{
+			vfe32_ctrl->aecStatsControl.bufToRender = 0;
+			vfe32_ctrl->aecStatsControl.droppedStatsFrameCount++;
+		}
+	} else {
+		vfe32_ctrl->aecStatsControl.bufToRender = 0;
+	}
+
+	if (status_bits & VFE_IRQ_STATUS0_STATS_AWB) {
+		if (!vfe32_ctrl->awbStatsControl.ackPending) {
+			vfe32_ctrl->awbStatsControl.ackPending = TRUE;
+			vfe32_ctrl->awbStatsControl.bufToRender =
+				vfe32_process_stats_irq_common(statsAwbNum,
+				vfe32_ctrl->awbStatsControl.nextFrameAddrBuf);
+			process_stats = true;
+		} else{
+			vfe32_ctrl->awbStatsControl.droppedStatsFrameCount++;
+			vfe32_ctrl->awbStatsControl.bufToRender = 0;
+		}
+	} else {
+		vfe32_ctrl->awbStatsControl.bufToRender = 0;
+	}
+
+
+	if (status_bits & VFE_IRQ_STATUS0_STATS_AF) {
+		if (!vfe32_ctrl->afStatsControl.ackPending) {
+			vfe32_ctrl->afStatsControl.ackPending = TRUE;
+			vfe32_ctrl->afStatsControl.bufToRender =
+				vfe32_process_stats_irq_common(statsAfNum,
+				vfe32_ctrl->afStatsControl.nextFrameAddrBuf);
+			process_stats = true;
+		} else {
+			vfe32_ctrl->afStatsControl.bufToRender = 0;
+			vfe32_ctrl->afStatsControl.droppedStatsFrameCount++;
+		}
+	} else {
+		vfe32_ctrl->afStatsControl.bufToRender = 0;
+	}
+
+	if (status_bits & VFE_IRQ_STATUS0_STATS_IHIST) {
+		if (!vfe32_ctrl->ihistStatsControl.ackPending) {
+			vfe32_ctrl->ihistStatsControl.ackPending = TRUE;
+			vfe32_ctrl->ihistStatsControl.bufToRender =
+				vfe32_process_stats_irq_common(statsIhistNum,
+				vfe32_ctrl->ihistStatsControl.nextFrameAddrBuf);
+			process_stats = true;
+		} else {
+			vfe32_ctrl->ihistStatsControl.droppedStatsFrameCount++;
+			vfe32_ctrl->ihistStatsControl.bufToRender = 0;
+		}
+	} else {
+		vfe32_ctrl->ihistStatsControl.bufToRender = 0;
+	}
+
+	if (status_bits & VFE_IRQ_STATUS0_STATS_RS) {
+		if (!vfe32_ctrl->rsStatsControl.ackPending) {
+			vfe32_ctrl->rsStatsControl.ackPending = TRUE;
+			vfe32_ctrl->rsStatsControl.bufToRender =
+				vfe32_process_stats_irq_common(statsRsNum,
+				vfe32_ctrl->rsStatsControl.nextFrameAddrBuf);
+			process_stats = true;
+		} else {
+			vfe32_ctrl->rsStatsControl.droppedStatsFrameCount++;
+			vfe32_ctrl->rsStatsControl.bufToRender = 0;
+		}
+	} else {
+		vfe32_ctrl->rsStatsControl.bufToRender = 0;
+	}
+
+
+	if (status_bits & VFE_IRQ_STATUS0_STATS_CS) {
+		if (!vfe32_ctrl->csStatsControl.ackPending) {
+			vfe32_ctrl->csStatsControl.ackPending = TRUE;
+			vfe32_ctrl->csStatsControl.bufToRender =
+				vfe32_process_stats_irq_common(statsCsNum,
+				vfe32_ctrl->csStatsControl.nextFrameAddrBuf);
+			process_stats = true;
+		} else {
+			vfe32_ctrl->csStatsControl.droppedStatsFrameCount++;
+			vfe32_ctrl->csStatsControl.bufToRender = 0;
+		}
+	} else {
+		vfe32_ctrl->csStatsControl.bufToRender = 0;
+	}
+
+	spin_unlock_irqrestore(&vfe32_ctrl->comp_stats_ack_lock, flags);
+	if (process_stats)
+		vfe_send_comp_stats_msg(status_bits);
+
+	return;
+}
+
+static void vfe32_process_stats_irq(uint32_t *irqstatus)
+{
+	uint32_t status_bits = VFE_COM_STATUS & *irqstatus;
+
+	if ((vfe32_ctrl->hfr_mode != HFR_MODE_OFF) &&
+		(vfe32_ctrl->vfeFrameId % vfe32_ctrl->hfr_mode != 0)) {
+		CDBG("Skip the stats when HFR enabled\n");
+		return;
+	}
+
+	vfe32_process_stats(status_bits);
+	return;
+}
+
 static void vfe32_do_tasklet(unsigned long data)
 {
 	unsigned long flags;
@@ -3191,7 +3410,7 @@
 				if (qcmd->vfeInterruptStatus0 &
 					VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK) {
 					CDBG("Stats composite irq occured.\n");
-					vfe32_process_stats_comb_irq(
+					vfe32_process_stats_irq(
 						&qcmd->vfeInterruptStatus0);
 				}
 			} else {
@@ -3618,6 +3837,10 @@
 	spin_lock_init(&vfe32_ctrl->aec_ack_lock);
 	spin_lock_init(&vfe32_ctrl->awb_ack_lock);
 	spin_lock_init(&vfe32_ctrl->af_ack_lock);
+	spin_lock_init(&vfe32_ctrl->ihist_ack_lock);
+	spin_lock_init(&vfe32_ctrl->rs_ack_lock);
+	spin_lock_init(&vfe32_ctrl->cs_ack_lock);
+	spin_lock_init(&vfe32_ctrl->comp_stats_ack_lock);
 	spin_lock_init(&vfe32_ctrl->sd_notify_lock);
 	INIT_LIST_HEAD(&vfe32_ctrl->tasklet_q);
 
@@ -3625,6 +3848,7 @@
 	vfe32_ctrl->update_rolloff = false;
 	vfe32_ctrl->update_la = false;
 	vfe32_ctrl->update_gamma = false;
+	vfe32_ctrl->hfr_mode = HFR_MODE_OFF;
 
 	enable_irq(vfe32_ctrl->vfeirq->start);
 
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index 1adfffd..62c3639 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -168,6 +168,9 @@
 #define VFE_AF_PINGPONG_STATUS_BIT       0x100
 #define VFE_AWB_PINGPONG_STATUS_BIT      0x200
 
+#define HFR_MODE_OFF 1
+#define VFE_FRAME_SKIP_PERIOD_MASK 0x0000001F /*bits 0 -4*/
+
 enum VFE32_DMI_RAM_SEL {
 	NO_MEM_SELECTED          = 0,
 	BLACK_LUT_RAM_BANK0      = 0x1,
@@ -220,7 +223,7 @@
 #define V32_OUT_CLAMP_OFF         0x00000524
 #define V32_OUT_CLAMP_LEN         8
 
-#define V32_OPERATION_CFG_LEN     32
+#define V32_OPERATION_CFG_LEN     36
 
 #define V32_AXI_OUT_OFF           0x00000038
 #define V32_AXI_OUT_LEN           216
@@ -778,6 +781,8 @@
 #define VFE32_IMASK_STATS_SKIN_BHIST_BUS_OVFL (0x00000001<<21)
 #define VFE32_IMASK_AXI_ERROR                 (0x00000001<<22)
 
+#define VFE_COM_STATUS 0x000FE000
+
 struct vfe32_output_path {
 	uint16_t output_mode;     /* bitmask  */
 
@@ -864,6 +869,7 @@
 #define VFE_CLAMP_MIN                   0x00000528
 #define VFE_REALIGN_BUF                 0x0000052C
 #define VFE_STATS_CFG                   0x00000530
+#define VFE_STATS_AWB_SGW_CFG           0x00000554
 #define VFE_DMI_CFG                     0x00000598
 #define VFE_DMI_ADDR                    0x0000059C
 #define VFE_DMI_DATA_LO                 0x000005A4
@@ -906,6 +912,10 @@
 	spinlock_t  aec_ack_lock;
 	spinlock_t  awb_ack_lock;
 	spinlock_t  af_ack_lock;
+	spinlock_t  ihist_ack_lock;
+	spinlock_t  rs_ack_lock;
+	spinlock_t  cs_ack_lock;
+	spinlock_t  comp_stats_ack_lock;
 
 	uint32_t extlen;
 	void *extdata;
@@ -958,6 +968,10 @@
 	struct platform_device *pdev;
 	struct clk *vfe_clk[3];
 	spinlock_t  sd_notify_lock;
+	uint32_t hfr_mode;
+	uint32_t frame_skip_cnt;
+	uint32_t frame_skip_pattern;
+	uint32_t snapshot_frame_cnt;
 };
 
 #define statsAeNum      0
diff --git a/drivers/media/video/msm/sensors/Makefile b/drivers/media/video/msm/sensors/Makefile
index a9b7bc6..047226e 100644
--- a/drivers/media/video/msm/sensors/Makefile
+++ b/drivers/media/video/msm/sensors/Makefile
@@ -5,6 +5,7 @@
 obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
 obj-$(CONFIG_IMX074) += imx074_v4l2.o
 obj-$(CONFIG_MT9M114) += mt9m114_v4l2.o
+obj-$(CONFIG_S5K3L1YX) += s5k3l1yx.o
 obj-$(CONFIG_OV2720) += ov2720.o
 obj-$(CONFIG_S5K4E1) += s5k4e1_v4l2.o
 obj-$(CONFIG_MT9E013) += mt9e013_v4l2.o
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 2c296618..d0b4f1f 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -215,7 +215,7 @@
 
 	v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
 		NOTIFY_ISPIF_STREAM, (void *)ISPIF_STREAM(
-		PIX0, ISPIF_OFF_IMMEDIATELY));
+		PIX_0, ISPIF_OFF_IMMEDIATELY));
 	s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
 	msleep(30);
 	if (update_type == MSM_SENSOR_REG_INIT) {
@@ -244,7 +244,7 @@
 			output_settings[res].op_pixel_clk);
 		v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
 			NOTIFY_ISPIF_STREAM, (void *)ISPIF_STREAM(
-			PIX0, ISPIF_ON_FRAME_BOUNDARY));
+			PIX_0, ISPIF_ON_FRAME_BOUNDARY));
 		s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
 		msleep(30);
 	}
@@ -502,6 +502,7 @@
 		goto enable_clk_failed;
 	}
 
+	usleep_range(1000, 2000);
 	if (data->sensor_platform_info->ext_power_ctrl != NULL)
 		data->sensor_platform_info->ext_power_ctrl(1);
 
diff --git a/drivers/media/video/msm/sensors/s5k3l1yx.c b/drivers/media/video/msm/sensors/s5k3l1yx.c
new file mode 100644
index 0000000..2177991
--- /dev/null
+++ b/drivers/media/video/msm/sensors/s5k3l1yx.c
@@ -0,0 +1,695 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_sensor.h"
+#define SENSOR_NAME "s5k3l1yx"
+#define PLATFORM_DRIVER_NAME "msm_camera_s5k3l1yx"
+
+DEFINE_MUTEX(s5k3l1yx_mut);
+static struct msm_sensor_ctrl_t s5k3l1yx_s_ctrl;
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_start_settings[] = {
+	{0x0100, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_stop_settings[] = {
+	{0x0100, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_groupon_settings[] = {
+	{0x104, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_groupoff_settings[] = {
+	{0x104, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_snap_settings[] = {
+	{0x0501, 0x00}, /* compression_algorithim_L(1d) */
+	{0x0112, 0x0A}, /* CCP_data_format_H */
+	{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+	{0x0306, 0x00}, /* pll_multiplier */
+	{0x0307, 0xA5}, /* pll_multiplier */
+	{0x0202, 0x09}, /* coarse_integration_time */
+	{0x0203, 0x32}, /* coarse_integration_time */
+	{0x0340, 0x0B}, /* frame_length_lines */
+	{0x0341, 0xEC}, /* frame_length_lines */
+	{0x0342, 0x14}, /* line_length_pck */
+	{0x0343, 0xD8}, /* line_length_pck */
+	{0x0344, 0x00}, /* x_addr_start */
+	{0x0345, 0x08}, /* x_addr_start */
+	{0x0346, 0x00}, /* y_addr_start */
+	{0x0347, 0x00}, /* y_addr_start */
+	{0x0348, 0x0F}, /* x_addr_end */
+	{0x0349, 0xA7}, /* x_addr_end */
+	{0x034A, 0x0B}, /* y_addr_end */
+	{0x034B, 0xC7}, /* y_addr_end */
+	{0x034C, 0x0F}, /* x_output_size */
+	{0x034D, 0xA0}, /* x_output_size */
+	{0x034E, 0x0B}, /* y_output_size */
+	{0x034F, 0xC8}, /* y_output_size */
+	{0x0380, 0x00}, /* x_even_inc */
+	{0x0381, 0x01}, /* x_even_inc */
+	{0x0382, 0x00}, /* x_odd_inc */
+	{0x0383, 0x01}, /* x_odd_inc */
+	{0x0384, 0x00}, /* y_even_inc */
+	{0x0385, 0x01}, /* y_even_inc */
+	{0x0386, 0x00}, /* y_odd_inc */
+	{0x0387, 0x01}, /* y_odd_inc */
+	{0x0900, 0x00}, /* binning_mode */
+	{0x0901, 0x22}, /* binning_type */
+	{0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_prev_settings[] = {
+	{0x0501, 0x00}, /* compression_algorithim_L(1d) */
+	{0x0112, 0x0A}, /* CCP_data_format_H */
+	{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+	{0x0306, 0x00}, /* pll_multiplier */
+	{0x0307, 0xA5}, /* pll_multiplier */
+	{0x0202, 0x06}, /* coarse_integration_time */
+	{0x0203, 0x00}, /* coarse_integration_time */
+	{0x0340, 0x09}, /* frame_length_lines */
+	{0x0341, 0x98}, /* frame_length_lines */
+	{0x0342, 0x11}, /* line_length_pck */
+	{0x0343, 0x80}, /* line_length_pck */
+	{0x0344, 0x00}, /* x_addr_start */
+	{0x0345, 0x18}, /* x_addr_start */
+	{0x0346, 0x00}, /* y_addr_start */
+	{0x0347, 0x00}, /* y_addr_start */
+	{0x0348, 0x0F}, /* x_addr_end */
+	{0x0349, 0x97}, /* x_addr_end */
+	{0x034A, 0x0B}, /* y_addr_end */
+	{0x034B, 0xC7}, /* y_addr_end */
+	{0x034C, 0x07}, /* x_output_size */
+	{0x034D, 0xC0}, /* x_output_size */
+	{0x034E, 0x05}, /* y_output_size */
+	{0x034F, 0xE4}, /* y_output_size */
+	{0x0380, 0x00}, /* x_even_inc */
+	{0x0381, 0x01}, /* x_even_inc */
+	{0x0382, 0x00}, /* x_odd_inc */
+	{0x0383, 0x03}, /* x_odd_inc */
+	{0x0384, 0x00}, /* y_even_inc */
+	{0x0385, 0x01}, /* y_even_inc */
+	{0x0386, 0x00}, /* y_odd_inc */
+	{0x0387, 0x03}, /* y_odd_inc */
+	{0x0900, 0x01}, /* binning_mode */
+	{0x0901, 0x22}, /* binning_type */
+	{0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_video_60fps_settings[] = {
+	{0x0501, 0x00}, /* compression_algorithim_L(1d) */
+	{0x0112, 0x0A}, /* CCP_data_format_H */
+	{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+	{0x0306, 0x00}, /* pll_multiplier */
+	{0x0307, 0xA5}, /* pll_multiplier */
+	{0x0202, 0x02}, /* coarse_integration_time */
+	{0x0203, 0x1C}, /* coarse_integration_time */
+	{0x0340, 0x03}, /* frame_length_lines */
+	{0x0341, 0xE0}, /* frame_length_lines */
+	{0x0342, 0x14}, /* line_length_pck */
+	{0x0343, 0xD8}, /* line_length_pck */
+	{0x0344, 0x01}, /* x_addr_start */
+	{0x0345, 0x20}, /* x_addr_start */
+	{0x0346, 0x02}, /* y_addr_start */
+	{0x0347, 0x23}, /* y_addr_start */
+	{0x0348, 0x0E}, /* x_addr_end */
+	{0x0349, 0xA0}, /* x_addr_end */
+	{0x034A, 0x09}, /* y_addr_end */
+	{0x034B, 0xA4}, /* y_addr_end */
+	{0x034C, 0x03}, /* x_output_size */
+	{0x034D, 0x60}, /* x_output_size */
+	{0x034E, 0x01}, /* y_output_size */
+	{0x034F, 0xE0}, /* y_output_size */
+	{0x0380, 0x00}, /* x_even_inc */
+	{0x0381, 0x01}, /* x_even_inc */
+	{0x0382, 0x00}, /* x_odd_inc */
+	{0x0383, 0x07}, /* x_odd_inc */
+	{0x0384, 0x00}, /* y_even_inc */
+	{0x0385, 0x01}, /* y_even_inc */
+	{0x0386, 0x00}, /* y_odd_inc */
+	{0x0387, 0x07}, /* y_odd_inc */
+	{0x0900, 0x01}, /* binning_mode */
+	{0x0901, 0x44}, /* binning_type */
+	{0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_video_90fps_settings[] = {
+	{0x0501, 0x00}, /* compression_algorithim_L(1d) */
+	{0x0112, 0x0A}, /* CCP_data_format_H */
+	{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+	{0x0306, 0x00}, /* pll_multiplier */
+	{0x0307, 0xA5}, /* pll_multiplier */
+	{0x0202, 0x02}, /* coarse_integration_time */
+	{0x0203, 0x1C}, /* coarse_integration_time */
+	{0x0340, 0x02}, /* frame_length_lines */
+	{0x0341, 0x98}, /* frame_length_lines */
+	{0x0342, 0x14}, /* line_length_pck */
+	{0x0343, 0xD8}, /* line_length_pck */
+	{0x0344, 0x01}, /* x_addr_start */
+	{0x0345, 0x20}, /* x_addr_start */
+	{0x0346, 0x02}, /* y_addr_start */
+	{0x0347, 0x23}, /* y_addr_start */
+	{0x0348, 0x0E}, /* x_addr_end */
+	{0x0349, 0xA0}, /* x_addr_end */
+	{0x034A, 0x09}, /* y_addr_end */
+	{0x034B, 0xA4}, /* y_addr_end */
+	{0x034C, 0x03}, /* x_output_size */
+	{0x034D, 0x60}, /* x_output_size */
+	{0x034E, 0x01}, /* y_output_size */
+	{0x034F, 0xE0}, /* y_output_size */
+	{0x0380, 0x00}, /* x_even_inc */
+	{0x0381, 0x01}, /* x_even_inc */
+	{0x0382, 0x00}, /* x_odd_inc */
+	{0x0383, 0x07}, /* x_odd_inc */
+	{0x0384, 0x00}, /* y_even_inc */
+	{0x0385, 0x01}, /* y_even_inc */
+	{0x0386, 0x00}, /* y_odd_inc */
+	{0x0387, 0x07}, /* y_odd_inc */
+	{0x0900, 0x01}, /* binning_mode */
+	{0x0901, 0x44}, /* binning_type */
+	{0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_video_120fps_settings[] = {
+	{0x0501, 0x00}, /* compression_algorithim_L(1d) */
+	{0x0112, 0x0A}, /* CCP_data_format_H */
+	{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+	{0x0306, 0x00}, /* pll_multiplier */
+	{0x0307, 0xA5}, /* pll_multiplier */
+	{0x0202, 0x02}, /* coarse_integration_time */
+	{0x0203, 0x1C}, /* coarse_integration_time */
+	{0x0340, 0x02}, /* frame_length_lines */
+	{0x0341, 0x0D}, /* frame_length_lines */
+	{0x0342, 0x14}, /* line_length_pck */
+	{0x0343, 0xD8}, /* line_length_pck */
+	{0x0344, 0x01}, /* x_addr_start */
+	{0x0345, 0x20}, /* x_addr_start */
+	{0x0346, 0x02}, /* y_addr_start */
+	{0x0347, 0x23}, /* y_addr_start */
+	{0x0348, 0x0E}, /* x_addr_end */
+	{0x0349, 0xA0}, /* x_addr_end */
+	{0x034A, 0x09}, /* y_addr_end */
+	{0x034B, 0xA4}, /* y_addr_end */
+	{0x034C, 0x03}, /* x_output_size */
+	{0x034D, 0x60}, /* x_output_size */
+	{0x034E, 0x01}, /* y_output_size */
+	{0x034F, 0xE0}, /* y_output_size */
+	{0x0380, 0x00}, /* x_even_inc */
+	{0x0381, 0x01}, /* x_even_inc */
+	{0x0382, 0x00}, /* x_odd_inc */
+	{0x0383, 0x07}, /* x_odd_inc */
+	{0x0384, 0x00}, /* y_even_inc */
+	{0x0385, 0x01}, /* y_even_inc */
+	{0x0386, 0x00}, /* y_odd_inc */
+	{0x0387, 0x07}, /* y_odd_inc */
+	{0x0900, 0x01}, /* binning_mode */
+	{0x0901, 0x44}, /* binning_type */
+	{0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_dpcm_settings[] = {
+	{0x0501, 0x01}, /* compression_algorithim_L(1d) */
+	{0x0112, 0x0A}, /* CCP_data_format_H */
+	{0x0113, 0x08}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+	{0x0306, 0x00}, /* pll_multiplier */
+	{0x0307, 0xA0}, /* pll_multiplier */
+	{0x0202, 0x09}, /* coarse_integration_time */
+	{0x0203, 0x32}, /* coarse_integration_time */
+	{0x0340, 0x0B}, /* frame_length_lines */
+	{0x0341, 0xEC}, /* frame_length_lines */
+	{0x0342, 0x11}, /* line_length_pck */
+	{0x0343, 0x80}, /* line_length_pck */
+	{0x0344, 0x00}, /* x_addr_start */
+	{0x0345, 0x08}, /* x_addr_start */
+	{0x0346, 0x00}, /* y_addr_start */
+	{0x0347, 0x00}, /* y_addr_start */
+	{0x0348, 0x0F}, /* x_addr_end */
+	{0x0349, 0xA7}, /* x_addr_end */
+	{0x034A, 0x0B}, /* y_addr_end */
+	{0x034B, 0xC7}, /* y_addr_end */
+	{0x034C, 0x0F}, /* x_output_size */
+	{0x034D, 0xA0}, /* x_output_size */
+	{0x034E, 0x0B}, /* y_output_size */
+	{0x034F, 0xC8}, /* y_output_size */
+	{0x0380, 0x00}, /* x_even_inc */
+	{0x0381, 0x01}, /* x_even_inc */
+	{0x0382, 0x00}, /* x_odd_inc */
+	{0x0383, 0x01}, /* x_odd_inc */
+	{0x0384, 0x00}, /* y_even_inc */
+	{0x0385, 0x01}, /* y_even_inc */
+	{0x0386, 0x00}, /* y_odd_inc */
+	{0x0387, 0x01}, /* y_odd_inc */
+	{0x0900, 0x00}, /* binning_mode */
+	{0x0901, 0x22}, /* binning_type */
+	{0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_recommend_settings[] = {
+	{0x0100, 0x00},
+	{0x0103, 0x01}, /* software_reset */
+	{0x0104, 0x00}, /* grouped_parameter_hold */
+	{0x0114, 0x03}, /* CSI_lane_mode, 4 lane setting */
+	{0x0120, 0x00}, /* gain_mode, global analogue gain*/
+	{0x0121, 0x00}, /* exposure_mode, global exposure */
+	{0x0136, 0x18}, /* Extclk_frequency_mhz */
+	{0x0137, 0x00}, /* Extclk_frequency_mhz */
+	{0x0200, 0x08}, /* fine_integration_time */
+	{0x0201, 0x88}, /* fine_integration_time */
+	{0x0204, 0x00}, /* analogue_gain_code_global */
+	{0x0205, 0x20}, /* analogue_gain_code_global */
+	{0x020E, 0x01}, /* digital_gain_greenR */
+	{0x020F, 0x00}, /* digital_gain_greenR */
+	{0x0210, 0x01}, /* digital_gain_red */
+	{0x0211, 0x00}, /* digital_gain_red */
+	{0x0212, 0x01}, /* digital_gain_blue */
+	{0x0213, 0x00}, /* digital_gain_blue */
+	{0x0214, 0x01}, /* digital_gain_greenB */
+	{0x0215, 0x00}, /* digital_gain_greenB */
+	{0x0300, 0x00}, /* vt_pix_clk_div */
+	{0x0301, 0x02}, /* vt_pix_clk_div */
+	{0x0302, 0x00}, /* vt_sys_clk_div */
+	{0x0303, 0x01}, /* vt_sys_clk_div */
+	{0x0304, 0x00}, /* pre_pll_clk_div */
+	{0x0305, 0x06}, /* pre_pll_clk_div */
+	{0x0308, 0x00}, /* op_pix_clk_div */
+	{0x0309, 0x02}, /* op_pix_clk_div */
+	{0x030A, 0x00}, /* op_sys_clk_div */
+	{0x030B, 0x01}, /* op_sys_clk_div */
+	{0x0800, 0x00}, /* tclk_post for D-PHY control */
+	{0x0801, 0x00}, /* ths_prepare for D-PHY control */
+	{0x0802, 0x00}, /* ths_zero_min for D-PHY control */
+	{0x0803, 0x00}, /* ths_trail for D-PHY control */
+	{0x0804, 0x00}, /* tclk_trail_min for D-PHY control */
+	{0x0805, 0x00}, /* tclk_prepare for D-PHY control */
+	{0x0806, 0x00}, /* tclk_zero_zero for D-PHY control */
+	{0x0807, 0x00}, /* tlpx for D-PHY control */
+	{0x0820, 0x02}, /* requested_link_bit_rate_mbps */
+	{0x0821, 0x94}, /* requested_link_bit_rate_mbps */
+	{0x0822, 0x00}, /* requested_link_bit_rate_mbps */
+	{0x0823, 0x00}, /* requested_link_bit_rate_mbps */
+	{0x3000, 0x0A},
+	{0x3001, 0xF7},
+	{0x3002, 0x0A},
+	{0x3003, 0xF7},
+	{0x3004, 0x08},
+	{0x3005, 0xF8},
+	{0x3006, 0x5B},
+	{0x3007, 0x73},
+	{0x3008, 0x49},
+	{0x3009, 0x0C},
+	{0x300A, 0xF8},
+	{0x300B, 0x4E},
+	{0x300C, 0x64},
+	{0x300D, 0x5C},
+	{0x300E, 0x71},
+	{0x300F, 0x0C},
+	{0x3010, 0x6A},
+	{0x3011, 0x14},
+	{0x3012, 0x14},
+	{0x3013, 0x0C},
+	{0x3014, 0x24},
+	{0x3015, 0x4F},
+	{0x3016, 0x86},
+	{0x3017, 0x0E},
+	{0x3018, 0x2C},
+	{0x3019, 0x30},
+	{0x301A, 0x31},
+	{0x301B, 0x32},
+	{0x301C, 0xFF},
+	{0x301D, 0x33},
+	{0x301E, 0x5C},
+	{0x301F, 0xFA},
+	{0x3020, 0x36},
+	{0x3021, 0x46},
+	{0x3022, 0x92},
+	{0x3023, 0xF5},
+	{0x3024, 0x6E},
+	{0x3025, 0x19},
+	{0x3026, 0x32},
+	{0x3027, 0x4B},
+	{0x3028, 0x04},
+	{0x3029, 0x50},
+	{0x302A, 0x0C},
+	{0x302B, 0x04},
+	{0x302C, 0xEF},
+	{0x302D, 0xC1},
+	{0x302E, 0x74},
+	{0x302F, 0x40},
+	{0x3030, 0x00},
+	{0x3031, 0x00},
+	{0x3032, 0x00},
+	{0x3033, 0x00},
+	{0x3034, 0x0F},
+	{0x3035, 0x01},
+	{0x3036, 0x00},
+	{0x3037, 0x00},
+	{0x3038, 0x88},
+	{0x3039, 0x98},
+	{0x303A, 0x1F},
+	{0x303B, 0x01},
+	{0x303C, 0x00},
+	{0x303D, 0x03},
+	{0x303E, 0x2F},
+	{0x303F, 0x09},
+	{0x3040, 0xFF},
+	{0x3041, 0x22},
+	{0x3042, 0x03},
+	{0x3043, 0x03},
+	{0x3044, 0x20},
+	{0x3045, 0x10},
+	{0x3046, 0x10},
+	{0x3047, 0x08},
+	{0x3048, 0x10},
+	{0x3049, 0x01},
+	{0x304A, 0x00},
+	{0x304B, 0x80},
+	{0x304C, 0x80},
+	{0x304D, 0x00},
+	{0x304E, 0x00},
+	{0x304F, 0x00},
+	{0x3051, 0x09},
+	{0x3052, 0xC4},
+	{0x305A, 0xE0},
+	{0x323D, 0x04},
+	{0x323E, 0x38},
+	{0x3305, 0xDD},
+	{0x3050, 0x01},
+	{0x3202, 0x01},
+	{0x3203, 0x01},
+	{0x3204, 0x01},
+	{0x3205, 0x01},
+	{0x3206, 0x01},
+	{0x3207, 0x01},
+	{0x320A, 0x05},
+	{0x320B, 0x20},
+	{0x3235, 0xB7},
+	{0x324C, 0x04},
+	{0x324A, 0x07},
+	{0x3902, 0x01},
+	{0x3915, 0x70},
+	{0x3916, 0x80},
+	{0x3A00, 0x01},
+	{0x3A06, 0x03},
+	{0x3B29, 0x01},
+	{0x3C11, 0x08},
+	{0x3C12, 0x7B},
+	{0x3C13, 0xC0},
+	{0x3C14, 0x70},
+	{0x3C15, 0x80},
+	{0x3C20, 0x00},
+	{0x3C23, 0x03},
+	{0x3C24, 0x00},
+	{0x3C50, 0x72},
+	{0x3C51, 0x85},
+	{0x3C53, 0x40},
+	{0x3C55, 0xA0},
+	{0x3D00, 0x00},
+	{0x3D01, 0x00},
+	{0x3D11, 0x01},
+	{0x3486, 0x05},
+	{0x3B35, 0x06},
+	{0x3A05, 0x01},
+	{0x3A07, 0x2B},
+	{0x3A09, 0x01},
+	{0x3940, 0xFF},
+	{0x3300, 0x00},
+	{0x3900, 0xFF},
+	{0x3914, 0x08},
+	{0x3A01, 0x0F},
+	{0x3A02, 0xA0},
+	{0x3A03, 0x0B},
+	{0x3A04, 0xC8},
+	{0x3701, 0x00},
+	{0x3702, 0x00},
+	{0x3703, 0x00},
+	{0x3704, 0x00},
+	{0x0101, 0x00}, /* image_orientation, mirror & flip off*/
+	{0x0105, 0x01}, /* mask_corrupted_frames */
+	{0x0110, 0x00}, /* CSI-2_channel_identifier */
+	{0x3942, 0x01}, /* [0] 1:mipi, 0:pvi */
+	{0x0B00, 0x00},
+};
+
+static struct v4l2_subdev_info s5k3l1yx_subdev_info[] = {
+	{
+	.code   = V4L2_MBUS_FMT_SBGGR10_1X10,
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	.fmt    = 1,
+	.order    = 0,
+	},
+	/* more can be supported, to be added later */
+};
+
+static struct msm_camera_i2c_conf_array s5k3l1yx_init_conf[] = {
+	{&s5k3l1yx_recommend_settings[0],
+	ARRAY_SIZE(s5k3l1yx_recommend_settings), 0, MSM_CAMERA_I2C_BYTE_DATA}
+};
+
+static struct msm_camera_i2c_conf_array s5k3l1yx_confs[] = {
+	{&s5k3l1yx_snap_settings[0],
+	ARRAY_SIZE(s5k3l1yx_snap_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&s5k3l1yx_prev_settings[0],
+	ARRAY_SIZE(s5k3l1yx_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&s5k3l1yx_video_60fps_settings[0],
+	ARRAY_SIZE(s5k3l1yx_video_60fps_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&s5k3l1yx_video_90fps_settings[0],
+	ARRAY_SIZE(s5k3l1yx_video_90fps_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&s5k3l1yx_video_120fps_settings[0],
+	ARRAY_SIZE(s5k3l1yx_video_120fps_settings), 0,
+					MSM_CAMERA_I2C_BYTE_DATA},
+	{&s5k3l1yx_dpcm_settings[0],
+	ARRAY_SIZE(s5k3l1yx_dpcm_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+};
+
+static struct msm_sensor_output_info_t s5k3l1yx_dimensions[] = {
+	/* 20 fps snapshot */
+	{
+		.x_output = 4000,
+		.y_output = 3016,
+		.line_length_pclk = 5336,
+		.frame_length_lines = 3052,
+		.vt_pixel_clk = 330000000,
+		.op_pixel_clk = 320000000,
+		.binning_factor = 1,
+	},
+	/* 30 fps preview */
+	{
+		.x_output = 1984,
+		.y_output = 1508,
+		.line_length_pclk = 4480,
+		.frame_length_lines = 2456,
+		.vt_pixel_clk = 330000000,
+		.op_pixel_clk = 320000000,
+		.binning_factor = 1,
+	},
+	/* 60 fps video */
+	{
+		.x_output = 864,
+		.y_output = 480,
+		.line_length_pclk = 5336,
+		.frame_length_lines = 992,
+		.vt_pixel_clk = 330000000,
+		.op_pixel_clk = 320000000,
+		.binning_factor = 1,
+	},
+	/* 90 fps video */
+	{
+		.x_output = 864,
+		.y_output = 480,
+		.line_length_pclk = 5336,
+		.frame_length_lines = 664,
+		.vt_pixel_clk = 330000000,
+		.op_pixel_clk = 320000000,
+		.binning_factor = 1,
+	},
+	/* 120 fps video */
+	{
+		.x_output = 864,
+		.y_output = 480,
+		.line_length_pclk = 5336,
+		.frame_length_lines = 525,
+		.vt_pixel_clk = 330000000,
+		.op_pixel_clk = 320000000,
+		.binning_factor = 1,
+	},
+	/* 24 fps snapshot */
+	{
+		.x_output = 4000,
+		.y_output = 3016,
+		.line_length_pclk = 4480,
+		.frame_length_lines = 3052,
+		.vt_pixel_clk = 330000000,
+		.op_pixel_clk = 320000000,
+		.binning_factor = 1,
+	},
+};
+
+static struct msm_camera_csid_vc_cfg s5k3l1yx_cid_cfg[] = {
+	{0, CSI_RAW10, CSI_DECODE_10BIT},
+};
+
+static struct msm_camera_csi2_params s5k3l1yx_csi_params = {
+	.csid_params = {
+		.lane_assign = 0xe4,
+		.lane_cnt = 4,
+		.lut_params = {
+			.num_cid = ARRAY_SIZE(s5k3l1yx_cid_cfg),
+			.vc_cfg = s5k3l1yx_cid_cfg,
+		},
+	},
+	.csiphy_params = {
+		.lane_cnt = 4,
+		.settle_cnt = 0x1B,
+	},
+};
+
+static struct msm_camera_csid_vc_cfg s5k3l1yx_cid_dpcm_cfg[] = {
+	{0, CSI_RAW8, CSI_DECODE_DPCM_10_8_10},
+};
+
+static struct msm_camera_csi2_params s5k3l1yx_csi_dpcm_params = {
+	.csid_params = {
+		.lane_assign = 0xe4,
+		.lane_cnt = 4,
+		.lut_params = {
+			.num_cid = ARRAY_SIZE(s5k3l1yx_cid_dpcm_cfg),
+			.vc_cfg = s5k3l1yx_cid_dpcm_cfg,
+		},
+	},
+	.csiphy_params = {
+		.lane_cnt = 4,
+		.settle_cnt = 0x1B,
+	},
+};
+
+static struct msm_camera_csi2_params *s5k3l1yx_csi_params_array[] = {
+	&s5k3l1yx_csi_params,
+	&s5k3l1yx_csi_params,
+	&s5k3l1yx_csi_params,
+	&s5k3l1yx_csi_params,
+	&s5k3l1yx_csi_params,
+	&s5k3l1yx_csi_dpcm_params,
+};
+
+static struct msm_sensor_output_reg_addr_t s5k3l1yx_reg_addr = {
+	.x_output = 0x34C,
+	.y_output = 0x34E,
+	.line_length_pclk = 0x342,
+	.frame_length_lines = 0x340,
+};
+
+static struct msm_sensor_id_info_t s5k3l1yx_id_info = {
+	.sensor_id_reg_addr = 0x0,
+	.sensor_id = 0x3121,
+};
+
+static struct msm_sensor_exp_gain_info_t s5k3l1yx_exp_gain_info = {
+	.coarse_int_time_addr = 0x202,
+	.global_gain_addr = 0x204,
+	.vert_offset = 8,
+};
+
+static const struct i2c_device_id s5k3l1yx_i2c_id[] = {
+	{SENSOR_NAME, (kernel_ulong_t)&s5k3l1yx_s_ctrl},
+	{ }
+};
+
+static struct i2c_driver s5k3l1yx_i2c_driver = {
+	.id_table = s5k3l1yx_i2c_id,
+	.probe  = msm_sensor_i2c_probe,
+	.driver = {
+		.name = SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client s5k3l1yx_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static int __init msm_sensor_init_module(void)
+{
+	return i2c_add_driver(&s5k3l1yx_i2c_driver);
+}
+
+static struct v4l2_subdev_core_ops s5k3l1yx_subdev_core_ops = {
+	.ioctl = msm_sensor_subdev_ioctl,
+	.s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops s5k3l1yx_subdev_video_ops = {
+	.enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops s5k3l1yx_subdev_ops = {
+	.core = &s5k3l1yx_subdev_core_ops,
+	.video  = &s5k3l1yx_subdev_video_ops,
+};
+
+static struct msm_sensor_fn_t s5k3l1yx_func_tbl = {
+	.sensor_start_stream = msm_sensor_start_stream,
+	.sensor_stop_stream = msm_sensor_stop_stream,
+	.sensor_group_hold_on = msm_sensor_group_hold_on,
+	.sensor_group_hold_off = msm_sensor_group_hold_off,
+	.sensor_set_fps = msm_sensor_set_fps,
+	.sensor_write_exp_gain = msm_sensor_write_exp_gain1,
+	.sensor_write_snapshot_exp_gain = msm_sensor_write_exp_gain1,
+	.sensor_setting = msm_sensor_setting,
+	.sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+	.sensor_mode_init = msm_sensor_mode_init,
+	.sensor_get_output_info = msm_sensor_get_output_info,
+	.sensor_config = msm_sensor_config,
+	.sensor_power_up = msm_sensor_power_up,
+	.sensor_power_down = msm_sensor_power_down,
+};
+
+static struct msm_sensor_reg_t s5k3l1yx_regs = {
+	.default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+	.start_stream_conf = s5k3l1yx_start_settings,
+	.start_stream_conf_size = ARRAY_SIZE(s5k3l1yx_start_settings),
+	.stop_stream_conf = s5k3l1yx_stop_settings,
+	.stop_stream_conf_size = ARRAY_SIZE(s5k3l1yx_stop_settings),
+	.group_hold_on_conf = s5k3l1yx_groupon_settings,
+	.group_hold_on_conf_size = ARRAY_SIZE(s5k3l1yx_groupon_settings),
+	.group_hold_off_conf = s5k3l1yx_groupoff_settings,
+	.group_hold_off_conf_size =
+		ARRAY_SIZE(s5k3l1yx_groupoff_settings),
+	.init_settings = &s5k3l1yx_init_conf[0],
+	.init_size = ARRAY_SIZE(s5k3l1yx_init_conf),
+	.mode_settings = &s5k3l1yx_confs[0],
+	.output_settings = &s5k3l1yx_dimensions[0],
+	.num_conf = ARRAY_SIZE(s5k3l1yx_confs),
+};
+
+static struct msm_sensor_ctrl_t s5k3l1yx_s_ctrl = {
+	.msm_sensor_reg = &s5k3l1yx_regs,
+	.sensor_i2c_client = &s5k3l1yx_sensor_i2c_client,
+	.sensor_i2c_addr = 0x6E,
+	.sensor_output_reg_addr = &s5k3l1yx_reg_addr,
+	.sensor_id_info = &s5k3l1yx_id_info,
+	.sensor_exp_gain_info = &s5k3l1yx_exp_gain_info,
+	.cam_mode = MSM_SENSOR_MODE_INVALID,
+	.csi_params = &s5k3l1yx_csi_params_array[0],
+	.msm_sensor_mutex = &s5k3l1yx_mut,
+	.sensor_i2c_driver = &s5k3l1yx_i2c_driver,
+	.sensor_v4l2_subdev_info = s5k3l1yx_subdev_info,
+	.sensor_v4l2_subdev_info_size = ARRAY_SIZE(s5k3l1yx_subdev_info),
+	.sensor_v4l2_subdev_ops = &s5k3l1yx_subdev_ops,
+	.func_tbl = &s5k3l1yx_func_tbl,
+	.clk_rate = MSM_SENSOR_MCLK_24HZ,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Samsung 12MP Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 30192d9..c8fcf5f 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -69,7 +69,7 @@
 obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-core.o
 obj-$(CONFIG_MCP_UCB1200_TS)	+= ucb1x00-ts.o
 
-obj-$(CONFIG_WCD9310_CODEC)       += wcd9310-core.o wcd9310-irq.o
+obj-$(CONFIG_WCD9310_CODEC)       += wcd9310-core.o wcd9310-irq.o wcd9310-slimslave.o
 
 ifeq ($(CONFIG_SA1100_ASSABET),y)
 obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-assabet.o
diff --git a/drivers/mfd/pm8038-core.c b/drivers/mfd/pm8038-core.c
index ceb4210..ac57418 100644
--- a/drivers/mfd/pm8038-core.c
+++ b/drivers/mfd/pm8038-core.c
@@ -268,6 +268,11 @@
 	.id             = -1,
 };
 
+static struct mfd_cell leds_cell __devinitdata = {
+	.name		= PM8XXX_LEDS_DEV_NAME,
+	.id		= -1,
+};
+
 static struct mfd_cell debugfs_cell __devinitdata = {
 	.name		= "pm8xxx-debug",
 	.id		= 0,
@@ -501,6 +506,16 @@
 		}
 	}
 
+	if (pdata->leds_pdata) {
+		leds_cell.platform_data = pdata->leds_pdata;
+		leds_cell.pdata_size = sizeof(struct pm8xxx_led_platform_data);
+		ret = mfd_add_devices(pmic->dev, 0, &leds_cell, 1, NULL, 0);
+		if (ret) {
+			pr_err("Failed to add leds subdevice ret=%d\n", ret);
+			goto bail;
+		}
+	}
+
 	if (pdata->num_regulators > 0 && pdata->regulator_pdatas) {
 		ret = pm8038_add_regulators(pdata, pmic, irq_base);
 		if (ret) {
diff --git a/drivers/mfd/wcd9310-core.c b/drivers/mfd/wcd9310-core.c
index 84eadef..87abcda 100644
--- a/drivers/mfd/wcd9310-core.c
+++ b/drivers/mfd/wcd9310-core.c
@@ -14,8 +14,8 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/mfd/core.h>
+#include <linux/mfd/wcd9310/wcd9310-slimslave.h>
 #include <linux/mfd/pm8xxx/pm8921.h>
-#include <linux/mfd/wcd9310/core.h>
 #include <linux/mfd/wcd9310/pdata.h>
 #include <linux/mfd/wcd9310/registers.h>
 #include <linux/delay.h>
@@ -370,6 +370,13 @@
 
 	mutex_init(&tabla->io_lock);
 	mutex_init(&tabla->xfer_lock);
+
+	mutex_init(&tabla->pm_lock);
+	tabla->wlock_holders = 0;
+	tabla->pm_state = TABLA_PM_SLEEPABLE;
+	init_waitqueue_head(&tabla->pm_wq);
+	wake_lock_init(&tabla->wlock, WAKE_LOCK_IDLE, "wcd9310-irq");
+
 	dev_set_drvdata(tabla->dev, tabla);
 
 	tabla_bring_up(tabla);
@@ -397,19 +404,22 @@
 	tabla_irq_exit(tabla);
 err:
 	tabla_bring_down(tabla);
+	wake_lock_destroy(&tabla->wlock);
+	mutex_destroy(&tabla->pm_lock);
 	mutex_destroy(&tabla->io_lock);
 	mutex_destroy(&tabla->xfer_lock);
 	return ret;
 }
+
 static void tabla_device_exit(struct tabla *tabla)
 {
 	tabla_irq_exit(tabla);
 	tabla_bring_down(tabla);
 	tabla_free_reset(tabla);
+	mutex_destroy(&tabla->pm_lock);
+	wake_lock_destroy(&tabla->wlock);
 	mutex_destroy(&tabla->io_lock);
 	mutex_destroy(&tabla->xfer_lock);
-	slim_remove_device(tabla->slim_slave);
-	kfree(tabla);
 }
 
 
@@ -707,13 +717,13 @@
 }
 
 int tabla_i2c_read(struct tabla *tabla, unsigned short reg,
-			int bytes, void *dest, bool interface_reg)
+		   int bytes, void *dest, bool interface_reg)
 {
 	return tabla_i2c_read_device(reg, bytes, dest);
 }
 
 int tabla_i2c_write(struct tabla *tabla, unsigned short reg,
-			 int bytes, void *src, bool interface_reg)
+		    int bytes, void *src, bool interface_reg)
 {
 	return tabla_i2c_write_device(reg, src, bytes);
 }
@@ -799,7 +809,13 @@
 
 static int __devexit tabla_i2c_remove(struct i2c_client *client)
 {
+	struct tabla *tabla;
+
 	pr_debug("exit\n");
+	tabla = dev_get_drvdata(&client->dev);
+	tabla_device_exit(tabla);
+	tabla_disable_supplies(tabla);
+	kfree(tabla);
 	return 0;
 }
 
@@ -905,7 +921,7 @@
 		pr_err("%s: error, initializing device failed\n", __func__);
 		goto err_slim_add;
 	}
-
+	tabla_init_slimslave(tabla, tabla_pgd_la);
 #ifdef CONFIG_DEBUG_FS
 	debugTabla = tabla;
 
@@ -935,6 +951,7 @@
 err:
 	return ret;
 }
+
 static int tabla_slim_remove(struct slim_device *pdev)
 {
 	struct tabla *tabla;
@@ -946,16 +963,106 @@
 #endif
 
 	tabla = slim_get_devicedata(pdev);
+	tabla_deinit_slimslave(tabla);
 	tabla_device_exit(tabla);
 	tabla_disable_supplies(tabla);
+	slim_remove_device(tabla->slim_slave);
 	kfree(tabla);
 
 	return 0;
 }
+
+static int tabla_resume(struct tabla *tabla)
+{
+	int ret = 0;
+
+	pr_debug("%s: enter\n", __func__);
+	mutex_lock(&tabla->pm_lock);
+	if (tabla->pm_state == TABLA_PM_ASLEEP) {
+		pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
+			 tabla->pm_state, tabla->wlock_holders);
+		tabla->pm_state = TABLA_PM_SLEEPABLE;
+	} else {
+		pr_warn("%s: system is already awake, state %d wlock %d\n",
+			__func__, tabla->pm_state, tabla->wlock_holders);
+	}
+	mutex_unlock(&tabla->pm_lock);
+	wake_up_all(&tabla->pm_wq);
+
+	return ret;
+}
+
+static int tabla_slim_resume(struct slim_device *sldev)
+{
+	struct tabla *tabla = slim_get_devicedata(sldev);
+	return tabla_resume(tabla);
+}
+
+static int tabla_i2c_resume(struct i2c_client *i2cdev)
+{
+	struct tabla *tabla = dev_get_drvdata(&i2cdev->dev);
+	return tabla_resume(tabla);
+}
+
+static int tabla_suspend(struct tabla *tabla, pm_message_t pmesg)
+{
+	int ret = 0;
+
+	pr_debug("%s: enter\n", __func__);
+	/* wake_lock() can be called after this suspend chain call started.
+	 * thus suspend can be called while wlock is being held */
+	mutex_lock(&tabla->pm_lock);
+	if (tabla->pm_state == TABLA_PM_SLEEPABLE) {
+		pr_debug("%s: suspending system, state %d, wlock %d\n",
+			 __func__, tabla->pm_state, tabla->wlock_holders);
+		tabla->pm_state = TABLA_PM_ASLEEP;
+	} else if (tabla->pm_state == TABLA_PM_AWAKE) {
+		/* unlock to wait for pm_state == TABLA_PM_SLEEPABLE
+		 * then set to TABLA_PM_ASLEEP */
+		pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
+			 __func__, tabla->pm_state, tabla->wlock_holders);
+		mutex_unlock(&tabla->pm_lock);
+		if (!(wait_event_timeout(tabla->pm_wq,
+					 tabla_pm_cmpxchg(tabla,
+							  TABLA_PM_SLEEPABLE,
+							  TABLA_PM_ASLEEP) ==
+							     TABLA_PM_SLEEPABLE,
+					 HZ))) {
+			pr_debug("%s: suspend failed state %d, wlock %d\n",
+				 __func__, tabla->pm_state,
+				 tabla->wlock_holders);
+			ret = -EBUSY;
+		} else {
+			pr_debug("%s: done, state %d, wlock %d\n", __func__,
+				 tabla->pm_state, tabla->wlock_holders);
+		}
+		mutex_lock(&tabla->pm_lock);
+	} else if (tabla->pm_state == TABLA_PM_ASLEEP) {
+		pr_warn("%s: system is already suspended, state %d, wlock %dn",
+			__func__, tabla->pm_state, tabla->wlock_holders);
+	}
+	mutex_unlock(&tabla->pm_lock);
+
+	return ret;
+}
+
+static int tabla_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
+{
+	struct tabla *tabla = slim_get_devicedata(sldev);
+	return tabla_suspend(tabla, pmesg);
+}
+
+static int tabla_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
+{
+	struct tabla *tabla = dev_get_drvdata(&i2cdev->dev);
+	return tabla_suspend(tabla, pmesg);
+}
+
 static const struct slim_device_id slimtest_id[] = {
 	{"tabla-slim", 0},
 	{}
 };
+
 static struct slim_driver tabla_slim_driver = {
 	.driver = {
 		.name = "tabla-slim",
@@ -964,6 +1071,8 @@
 	.probe = tabla_slim_probe,
 	.remove = tabla_slim_remove,
 	.id_table = slimtest_id,
+	.resume = tabla_slim_resume,
+	.suspend = tabla_slim_suspend,
 };
 
 static const struct slim_device_id slimtest2x_id[] = {
@@ -979,6 +1088,8 @@
 	.probe = tabla_slim_probe,
 	.remove = tabla_slim_remove,
 	.id_table = slimtest2x_id,
+	.resume = tabla_slim_resume,
+	.suspend = tabla_slim_suspend,
 };
 
 #define TABLA_I2C_TOP_LEVEL 0
@@ -996,13 +1107,15 @@
 MODULE_DEVICE_TABLE(i2c, tabla_id_table);
 
 static struct i2c_driver tabla_i2c_driver = {
-	.driver                 = {
-		.owner          =       THIS_MODULE,
-		.name           =       "tabla-i2c-core",
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "tabla-i2c-core",
 	},
-	.id_table               =       tabla_id_table,
-	.probe                  =       tabla_i2c_probe,
-	.remove                 =       __devexit_p(tabla_i2c_remove),
+	.id_table = tabla_id_table,
+	.probe = tabla_i2c_probe,
+	.remove = __devexit_p(tabla_i2c_remove),
+	.resume	= tabla_i2c_resume,
+	.suspend = tabla_i2c_suspend,
 };
 
 static int __init tabla_init(void)
diff --git a/drivers/mfd/wcd9310-irq.c b/drivers/mfd/wcd9310-irq.c
index fef1323..c6a9c23 100644
--- a/drivers/mfd/wcd9310-irq.c
+++ b/drivers/mfd/wcd9310-irq.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,6 +12,7 @@
 #include <linux/bitops.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <linux/irq.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/wcd9310/core.h>
@@ -83,6 +84,60 @@
 	.irq_enable = tabla_irq_enable,
 };
 
+enum tabla_pm_state tabla_pm_cmpxchg(struct tabla *tabla, enum tabla_pm_state o,
+				     enum tabla_pm_state n)
+{
+	enum tabla_pm_state old;
+	mutex_lock(&tabla->pm_lock);
+	old = tabla->pm_state;
+	if (old == o)
+		tabla->pm_state = n;
+	mutex_unlock(&tabla->pm_lock);
+	return old;
+}
+EXPORT_SYMBOL_GPL(tabla_pm_cmpxchg);
+
+void tabla_lock_sleep(struct tabla *tabla)
+{
+	enum tabla_pm_state os;
+
+	/* tabla_{lock/unlock}_sleep will be called by tabla_irq_thread
+	 * and its subroutines only motly.
+	 * but btn0_lpress_fn is not tabla_irq_thread's subroutine and
+	 * it can race with tabla_irq_thread.
+	 * so need to embrace wlock_holders with mutex.
+	 */
+	mutex_lock(&tabla->pm_lock);
+	if (tabla->wlock_holders++ == 0)
+		wake_lock(&tabla->wlock);
+	mutex_unlock(&tabla->pm_lock);
+	while (!wait_event_timeout(tabla->pm_wq,
+			((os = tabla_pm_cmpxchg(tabla, TABLA_PM_SLEEPABLE,
+						TABLA_PM_AWAKE)) ==
+						    TABLA_PM_SLEEPABLE ||
+			 (os == TABLA_PM_AWAKE)),
+			5 * HZ)) {
+		pr_err("%s: system didn't resume within 5000ms, state %d, "
+		       "wlock %d\n", __func__, tabla->pm_state,
+		       tabla->wlock_holders);
+		WARN_ON_ONCE(1);
+	}
+	wake_up_all(&tabla->pm_wq);
+}
+EXPORT_SYMBOL_GPL(tabla_lock_sleep);
+
+void tabla_unlock_sleep(struct tabla *tabla)
+{
+	mutex_lock(&tabla->pm_lock);
+	if (--tabla->wlock_holders == 0) {
+		tabla->pm_state = TABLA_PM_SLEEPABLE;
+		wake_unlock(&tabla->wlock);
+	}
+	mutex_unlock(&tabla->pm_lock);
+	wake_up_all(&tabla->pm_wq);
+}
+EXPORT_SYMBOL_GPL(tabla_unlock_sleep);
+
 static irqreturn_t tabla_irq_thread(int irq, void *data)
 {
 	int ret;
@@ -90,11 +145,13 @@
 	u8 status[TABLA_NUM_IRQ_REGS];
 	unsigned int i;
 
+	tabla_lock_sleep(tabla);
 	ret = tabla_bulk_read(tabla, TABLA_A_INTR_STATUS0,
 			       TABLA_NUM_IRQ_REGS, status);
 	if (ret < 0) {
 		dev_err(tabla->dev, "Failed to read interrupt status: %d\n",
 			ret);
+		tabla_unlock_sleep(tabla);
 		return IRQ_NONE;
 	}
 	/* Apply masking */
@@ -127,6 +184,7 @@
 			break;
 		}
 	}
+	tabla_unlock_sleep(tabla);
 
 	return IRQ_HANDLED;
 }
diff --git a/drivers/mfd/wcd9310-slimslave.c b/drivers/mfd/wcd9310-slimslave.c
new file mode 100644
index 0000000..dd586fa
--- /dev/null
+++ b/drivers/mfd/wcd9310-slimslave.c
@@ -0,0 +1,522 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/mfd/wcd9310/wcd9310-slimslave.h>
+
+struct tabla_slim_sch_rx {
+	u32 sph;
+	u32 ch_num;
+	u16 ch_h;
+	u16 grph;
+};
+
+struct tabla_slim_sch_tx {
+	u32 sph;
+	u32 ch_num;
+	u16 ch_h;
+	u16 grph;
+};
+
+struct tabla_slim_sch {
+	struct tabla_slim_sch_rx rx[SLIM_MAX_RX_PORTS];
+	struct tabla_slim_sch_tx tx[SLIM_MAX_TX_PORTS];
+};
+
+static struct tabla_slim_sch sh_ch;
+
+static int tabla_alloc_slim_sh_ch_rx(struct tabla *tabla, u8 tabla_pgd_la);
+static int tabla_alloc_slim_sh_ch_tx(struct tabla *tabla, u8 tabla_pgd_la);
+static int tabla_dealloc_slim_sh_ch_rx(struct tabla *tab);
+static int tabla_dealloc_slim_sh_ch_tx(struct tabla *tab);
+
+int tabla_init_slimslave(struct tabla *tabla, u8 tabla_pgd_la)
+{
+	int ret = 0;
+
+	ret = tabla_alloc_slim_sh_ch_rx(tabla, tabla_pgd_la);
+	if (ret) {
+		pr_err("%s: Failed to alloc rx slimbus shared channels\n",
+								__func__);
+		goto rx_err;
+	}
+	ret = tabla_alloc_slim_sh_ch_tx(tabla, tabla_pgd_la);
+	if (ret) {
+		pr_err("%s: Failed to alloc tx slimbus shared channels\n",
+								__func__);
+		goto tx_err;
+	}
+	return 0;
+tx_err:
+	tabla_dealloc_slim_sh_ch_rx(tabla);
+rx_err:
+	return ret;
+}
+
+
+int tabla_deinit_slimslave(struct tabla *tabla)
+{
+	int ret = 0;
+	ret = tabla_dealloc_slim_sh_ch_rx(tabla);
+	if (ret < 0) {
+		pr_err("%s: fail to dealloc rx slim ports\n", __func__);
+		goto err;
+	}
+	ret = tabla_dealloc_slim_sh_ch_tx(tabla);
+	if (ret < 0) {
+		pr_err("%s: fail to dealloc tx slim ports\n", __func__);
+		goto err;
+	}
+err:
+	return ret;
+}
+
+int tabla_get_channel(struct tabla *tabla,
+		unsigned int *rx_ch,
+		unsigned int *tx_ch)
+{
+	int ch_idx = 0;
+	struct tabla_slim_sch_rx *rx = sh_ch.rx;
+	struct tabla_slim_sch_tx *tx = sh_ch.tx;
+
+	for (ch_idx = 0; ch_idx < SLIM_MAX_RX_PORTS; ch_idx++)
+		rx_ch[ch_idx] = rx[ch_idx].ch_num;
+	for (ch_idx = 0; ch_idx < SLIM_MAX_TX_PORTS; ch_idx++)
+		tx_ch[ch_idx] = tx[ch_idx].ch_num;
+	return 0;
+}
+
+static int tabla_alloc_slim_sh_ch_rx(struct tabla *tabla, u8 tabla_pgd_la)
+{
+	int ret = 0;
+	u8 ch_idx ;
+	u16 slave_port_id = 0;
+	struct tabla_slim_sch_rx *rx = sh_ch.rx;
+
+	/* DSP requires channel number to be between 128 and 255. For RX port
+	 * use channel numbers from 138 to 144, for TX port
+	 * use channel numbers from 128 to 137
+	 */
+	pr_debug("%s: pgd_la[%d]\n", __func__, tabla_pgd_la);
+	for (ch_idx = 0; ch_idx < SLIM_MAX_RX_PORTS; ch_idx++) {
+		slave_port_id = (ch_idx + 1 +
+				SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS);
+		rx[ch_idx].ch_num = slave_port_id + BASE_CH_NUM;
+		ret = slim_get_slaveport(tabla_pgd_la, slave_port_id,
+					&rx[ch_idx].sph, SLIM_SINK);
+		if (ret < 0) {
+			pr_err("%s: slave port failure id[%d] ret[%d]\n",
+					__func__, slave_port_id, ret);
+			goto err;
+		}
+
+		ret = slim_query_ch(tabla->slim, rx[ch_idx].ch_num,
+							&rx[ch_idx].ch_h);
+		if (ret < 0) {
+			pr_err("%s: slim_query_ch failed ch-num[%d] ret[%d]\n",
+					__func__, rx[ch_idx].ch_num, ret);
+			goto err;
+		}
+	}
+err:
+	return ret;
+}
+
+static int tabla_alloc_slim_sh_ch_tx(struct tabla *tabla, u8 tabla_pgd_la)
+{
+	int ret = 0;
+	u8 ch_idx ;
+	struct tabla_slim_sch_tx *tx = sh_ch.tx;
+	u16 slave_port_id = 0;
+
+	pr_debug("%s: pgd_la[%d]\n", __func__, tabla_pgd_la);
+	/* DSP requires channel number to be between 128 and 255. For RX port
+	 * use channel numbers from 138 to 144, for TX port
+	 * use channel numbers from 128 to 137
+	 */
+	for (ch_idx = 0; ch_idx < SLIM_MAX_TX_PORTS; ch_idx++) {
+		slave_port_id = ch_idx;
+		tx[ch_idx].ch_num = slave_port_id + BASE_CH_NUM;
+		ret = slim_get_slaveport(tabla_pgd_la, slave_port_id,
+					&tx[ch_idx].sph, SLIM_SRC);
+		if (ret < 0) {
+			pr_err("%s: slave port failure id[%d] ret[%d]\n",
+					__func__, slave_port_id, ret);
+			goto err;
+		}
+		ret = slim_query_ch(tabla->slim, tx[ch_idx].ch_num,
+							&tx[ch_idx].ch_h);
+		if (ret < 0) {
+			pr_err("%s: slim_query_ch failed ch-num[%d] ret[%d]\n",
+					__func__, tx[ch_idx].ch_num, ret);
+			goto err;
+		}
+	}
+err:
+	return ret;
+}
+
+static int tabla_dealloc_slim_sh_ch_rx(struct tabla *tab)
+{
+	int idx = 0;
+	int ret = 0;
+	struct tabla_slim_sch_rx *rx = sh_ch.rx;
+	/* slim_dealloc_ch */
+	for (idx = 0; idx < SLIM_MAX_RX_PORTS; idx++) {
+		ret = slim_dealloc_ch(tab->slim, rx[idx].ch_h);
+		if (ret < 0) {
+			pr_err("%s: slim_dealloc_ch fail ret[%d] ch_h[%d]\n",
+				__func__, ret, rx[idx].ch_h);
+		}
+	}
+	memset(sh_ch.rx, 0, sizeof(sh_ch.rx));
+	return ret;
+}
+
+static int tabla_dealloc_slim_sh_ch_tx(struct tabla *tab)
+{
+	int idx = 0;
+	int ret = 0;
+	struct tabla_slim_sch_tx *tx = sh_ch.tx;
+	/* slim_dealloc_ch */
+	for (idx = 0; idx < SLIM_MAX_TX_PORTS; idx++) {
+		ret = slim_dealloc_ch(tab->slim, tx[idx].ch_h);
+		if (ret < 0) {
+			pr_err("%s: slim_dealloc_ch fail ret[%d] ch_h[%d]\n",
+				__func__, ret, tx[idx].ch_h);
+		}
+	}
+	memset(sh_ch.tx, 0, sizeof(sh_ch.tx));
+	return ret;
+}
+
+/* Enable slimbus slave device for RX path */
+int tabla_cfg_slim_sch_rx(struct tabla *tab, unsigned int *ch_num,
+				unsigned int ch_cnt, unsigned int rate)
+{
+	u8 i = 0;
+	u16 grph;
+	u32 sph[SLIM_MAX_RX_PORTS] = {0};
+	u16 ch_h[SLIM_MAX_RX_PORTS] = {0};
+	u16 slave_port_id;
+	u8  payload_rx = 0, wm_payload = 0;
+	int ret, idx = 0;
+	unsigned short  multi_chan_cfg_reg_addr;
+	struct tabla_slim_sch_rx *rx = sh_ch.rx;
+	struct slim_ch prop;
+
+	/* Configure slave interface device */
+	pr_debug("%s: ch_cnt[%d] rate=%d\n", __func__, ch_cnt, rate);
+
+	for (i = 0; i < ch_cnt; i++) {
+		idx = (ch_num[i] - BASE_CH_NUM -
+				SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
+		ch_h[i] = rx[idx].ch_h;
+		sph[i] = rx[idx].sph;
+		slave_port_id = idx + 1;
+		if ((slave_port_id > SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS) ||
+			(slave_port_id == 0)) {
+			pr_err("Slimbus: invalid slave port id: %d",
+							slave_port_id);
+			ret = -EINVAL;
+			goto err;
+		}
+		slave_port_id += SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS;
+		/* look for the valid port range and chose the
+		 * payload accordingly
+		 */
+		if ((slave_port_id >
+				SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID) &&
+			(slave_port_id <
+			 SB_PGD_RX_PORT_MULTI_CHANNEL_0_END_PORT_ID)) {
+				payload_rx = payload_rx  |
+				(1 <<
+				(slave_port_id -
+				SB_PGD_RX_PORT_MULTI_CHANNEL_0_START_PORT_ID));
+		} else {
+			ret = -EINVAL;
+			goto err;
+		}
+		multi_chan_cfg_reg_addr =
+				SB_PGD_RX_PORT_MULTI_CHANNEL_0(slave_port_id);
+		/* write to interface device */
+		ret = tabla_interface_reg_write(tab, multi_chan_cfg_reg_addr,
+				payload_rx);
+		if (ret < 0) {
+			pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
+							__func__,
+							multi_chan_cfg_reg_addr,
+							payload_rx, ret);
+			goto err;
+		}
+		/* configure the slave port for water mark and enable*/
+		wm_payload = (SLAVE_PORT_WATER_MARK_VALUE <<
+				SLAVE_PORT_WATER_MARK_SHIFT) +
+				SLAVE_PORT_ENABLE;
+		ret = tabla_interface_reg_write(tab,
+				SB_PGD_PORT_CFG_BYTE_ADDR(slave_port_id),
+				wm_payload);
+		if (ret < 0) {
+			pr_err("%s:watermark set failure for port[%d] ret[%d]",
+						__func__, slave_port_id, ret);
+		}
+	}
+
+	/* slim_define_ch api */
+	prop.prot = SLIM_AUTO_ISO;
+	prop.baser = SLIM_RATE_4000HZ;
+	prop.dataf = SLIM_CH_DATAF_NOT_DEFINED;
+	prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
+	prop.ratem = (rate/4000);
+	prop.sampleszbits = 16;
+
+	ret = slim_define_ch(tab->slim, &prop, ch_h, ch_cnt,
+					true, &grph);
+	if (ret < 0) {
+		pr_err("%s: slim_define_ch failed ret[%d]\n",
+					__func__, ret);
+		goto err;
+	}
+	for (i = 0; i < ch_cnt; i++) {
+		ret = slim_connect_sink(tab->slim, &sph[i],
+							1, ch_h[i]);
+		if (ret < 0) {
+			pr_err("%s: slim_connect_sink failed ret[%d]\n",
+						__func__, ret);
+			goto err_close_slim_sch;
+		}
+	}
+	/* slim_control_ch */
+	ret = slim_control_ch(tab->slim, grph, SLIM_CH_ACTIVATE,
+					true);
+	if (ret < 0) {
+		pr_err("%s: slim_control_ch failed ret[%d]\n",
+				__func__, ret);
+		goto err_close_slim_sch;
+	}
+	for (i = 0; i < ch_cnt; i++) {
+		idx = (ch_num[i] - BASE_CH_NUM -
+				SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
+		rx[idx].grph = grph;
+	}
+	return 0;
+
+err_close_slim_sch:
+	/*  release all acquired handles */
+	tabla_close_slim_sch_rx(tab, ch_num, ch_cnt);
+err:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tabla_cfg_slim_sch_rx);
+
+/* Enable slimbus slave device for RX path */
+int tabla_cfg_slim_sch_tx(struct tabla *tab, unsigned int *ch_num,
+				unsigned int ch_cnt, unsigned int rate)
+{
+	u8 i = 0;
+	u8  payload_tx_0 = 0, payload_tx_1 = 0, wm_payload = 0;
+	u16 grph;
+	u32 sph[SLIM_MAX_TX_PORTS] = {0};
+	u16 ch_h[SLIM_MAX_TX_PORTS] = {0};
+	u16 idx = 0, slave_port_id;
+	int ret = 0;
+	unsigned short  multi_chan_cfg_reg_addr;
+
+	struct tabla_slim_sch_tx *tx = sh_ch.tx;
+	struct slim_ch prop;
+
+	pr_debug("%s: ch_cnt[%d] rate[%d]\n", __func__, ch_cnt, rate);
+	for (i = 0; i < ch_cnt; i++) {
+		idx = (ch_num[i] - BASE_CH_NUM);
+		ch_h[i] = tx[idx].ch_h;
+		sph[i] = tx[idx].sph;
+		slave_port_id = idx ;
+		if ((slave_port_id > SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS) ||
+		(slave_port_id == 0)) {
+			pr_err("SLIMbus: invalid slave port id: %d",
+							slave_port_id);
+			ret = -EINVAL;
+			goto err;
+		}
+		/* look for the valid port range and chose the
+		 *  payload accordingly
+		 */
+		if (slave_port_id <=
+			SB_PGD_TX_PORT_MULTI_CHANNEL_0_END_PORT_ID) {
+			payload_tx_0 = payload_tx_0 | (1 << slave_port_id);
+		} else if (slave_port_id <
+				SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID) {
+				payload_tx_1 = payload_tx_1 |
+				(1 <<
+				(slave_port_id -
+				SB_PGD_TX_PORT_MULTI_CHANNEL_1_START_PORT_ID));
+		} else {
+			ret = -EINVAL;
+			goto err;
+		}
+		multi_chan_cfg_reg_addr =
+				SB_PGD_TX_PORT_MULTI_CHANNEL_0(slave_port_id);
+		/* write to interface device */
+		ret = tabla_interface_reg_write(tab, multi_chan_cfg_reg_addr,
+				payload_tx_0);
+		if (ret < 0) {
+			pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
+								__func__,
+						multi_chan_cfg_reg_addr,
+						payload_tx_0, ret);
+			goto err;
+		}
+		multi_chan_cfg_reg_addr =
+				SB_PGD_TX_PORT_MULTI_CHANNEL_1(slave_port_id);
+		/* ports 8,9 */
+		ret = tabla_interface_reg_write(tab, multi_chan_cfg_reg_addr,
+				payload_tx_1);
+		if (ret < 0) {
+			pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
+								__func__,
+						multi_chan_cfg_reg_addr,
+						payload_tx_1, ret);
+			goto err;
+		}
+		/* configure the slave port for water mark and enable*/
+		wm_payload = (SLAVE_PORT_WATER_MARK_VALUE <<
+				SLAVE_PORT_WATER_MARK_SHIFT) +
+				SLAVE_PORT_ENABLE;
+		ret = tabla_interface_reg_write(tab,
+				SB_PGD_PORT_CFG_BYTE_ADDR(slave_port_id),
+				wm_payload);
+		if (ret < 0) {
+			pr_err("%s:watermark set failure for port[%d] ret[%d]",
+						__func__,
+						slave_port_id, ret);
+		}
+	}
+
+	/* slim_define_ch api */
+	prop.prot = SLIM_AUTO_ISO;
+	prop.baser = SLIM_RATE_4000HZ;
+	prop.dataf = SLIM_CH_DATAF_NOT_DEFINED;
+	prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
+	prop.ratem = (rate/4000);
+	prop.sampleszbits = 16;
+	ret = slim_define_ch(tab->slim, &prop, ch_h, ch_cnt,
+					true, &grph);
+	if (ret < 0) {
+		pr_err("%s: slim_define_ch failed ret[%d]\n",
+					__func__, ret);
+		goto err;
+	}
+	for (i = 0; i < ch_cnt; i++) {
+		ret = slim_connect_src(tab->slim, sph[i],
+							ch_h[i]);
+		if (ret < 0) {
+			pr_err("%s: slim_connect_src failed ret[%d]\n",
+						__func__, ret);
+			goto err;
+		}
+	}
+	/* slim_control_ch */
+	ret = slim_control_ch(tab->slim, grph, SLIM_CH_ACTIVATE,
+					true);
+	if (ret < 0) {
+		pr_err("%s: slim_control_ch failed ret[%d]\n",
+				__func__, ret);
+		goto err;
+	}
+	for (i = 0; i < ch_cnt; i++) {
+		idx = (ch_num[i] - BASE_CH_NUM);
+		tx[idx].grph = grph;
+	}
+	return 0;
+err:
+	/* release all acquired handles */
+	tabla_close_slim_sch_tx(tab, ch_num, ch_cnt);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tabla_cfg_slim_sch_tx);
+
+int tabla_close_slim_sch_rx(struct tabla *tab, unsigned int *ch_num,
+				unsigned int ch_cnt)
+{
+	u16 grph = 0;
+	u32 sph[SLIM_MAX_RX_PORTS] = {0};
+	int i = 0 , idx = 0;
+	int ret = 0;
+	struct tabla_slim_sch_rx *rx = sh_ch.rx;
+
+	pr_debug("%s: ch_cnt[%d]\n", __func__, ch_cnt);
+	for (i = 0; i < ch_cnt; i++) {
+		idx = (ch_num[i] - BASE_CH_NUM -
+				SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
+		sph[i] = rx[idx].sph;
+		grph = rx[idx].grph;
+	}
+
+	/* slim_disconnect_port */
+	ret = slim_disconnect_ports(tab->slim, sph, ch_cnt);
+	if (ret < 0) {
+		pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
+				__func__, ret);
+	}
+	/* slim_control_ch (REMOVE) */
+	ret = slim_control_ch(tab->slim, grph, SLIM_CH_REMOVE, true);
+	if (ret < 0) {
+		pr_err("%s: slim_control_ch failed ret[%d]\n",
+				__func__, ret);
+		goto err;
+	}
+	for (i = 0; i < ch_cnt; i++) {
+		idx = (ch_num[i] - BASE_CH_NUM -
+				SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
+		rx[idx].grph = 0;
+	}
+err:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tabla_close_slim_sch_rx);
+
+int tabla_close_slim_sch_tx(struct tabla *tab, unsigned int *ch_num,
+				unsigned int ch_cnt)
+{
+	u16 grph = 0;
+	u32 sph[SLIM_MAX_TX_PORTS] = {0};
+	int ret = 0;
+	int i = 0 , idx = 0;
+	struct tabla_slim_sch_tx *tx = sh_ch.tx;
+
+	pr_debug("%s: ch_cnt[%d]\n", __func__, ch_cnt);
+	for (i = 0; i < ch_cnt; i++) {
+		idx = (ch_num[i] - BASE_CH_NUM);
+		sph[i] = tx[idx].sph;
+		grph = tx[idx].grph;
+	}
+	/* slim_disconnect_port */
+	ret = slim_disconnect_ports(tab->slim, sph, ch_cnt);
+	if (ret < 0) {
+		pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
+				__func__, ret);
+	}
+	/* slim_control_ch (REMOVE) */
+	ret = slim_control_ch(tab->slim, grph, SLIM_CH_REMOVE, true);
+	if (ret < 0) {
+		pr_err("%s: slim_control_ch failed ret[%d]\n",
+				__func__, ret);
+		goto err;
+	}
+	for (i = 0; i < ch_cnt; i++) {
+		idx = (ch_num[i] - BASE_CH_NUM);
+		tx[idx].grph = 0;
+	}
+err:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tabla_close_slim_sch_tx);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 8f42e5b..3ae639e 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1002,6 +1002,12 @@
 		}
 	}
 
+	/* Clear CDR_EN bit for write operations */
+	if (host->tuning_needed && cmd->mrq->data &&
+			(cmd->mrq->data->flags & MMC_DATA_WRITE))
+		writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG) &
+				~MCI_CDR_EN), host->base + MCI_DLL_CONFIG);
+
 	if ((cmd->flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
 		*c |= MCI_CPSM_PROGENA;
 		host->prog_enable = 1;
@@ -2876,22 +2882,21 @@
  * Select the 3/4 of the range and configure the DLL with the
  * selected DLL clock output phase.
 */
-
 static u8 find_most_appropriate_phase(struct msmsdcc_host *host,
 				u8 *phase_table, u8 total_phases)
 {
-	u8 ret, temp;
-	u8 ranges[16][16] = { {0}, {0} };
+	u8 ret, ranges[16][16] = { {0}, {0} };
 	u8 phases_per_row[16] = {0};
 	int row_index = 0, col_index = 0, selected_row_index = 0, curr_max = 0;
-	int cnt;
+	int i, cnt, phase_0_raw_index = 0, phase_15_raw_index = 0;
+	bool phase_0_found = false, phase_15_found = false;
 
-	for (cnt = 0; cnt <= total_phases; cnt++) {
+	for (cnt = 0; cnt < total_phases; cnt++) {
 		ranges[row_index][col_index] = phase_table[cnt];
 		phases_per_row[row_index] += 1;
 		col_index++;
 
-		if ((cnt + 1) > total_phases) {
+		if ((cnt + 1) == total_phases) {
 			continue;
 		/* check if next phase in phase_table is consecutive or not */
 		} else if ((phase_table[cnt] + 1) != phase_table[cnt + 1]) {
@@ -2900,15 +2905,50 @@
 		}
 	}
 
-	for (cnt = 0; cnt <= total_phases; cnt++) {
+	/* Check if phase-0 is present in first valid window? */
+	if (!ranges[0][0]) {
+		phase_0_found = true;
+		phase_0_raw_index = 0;
+		/* Check if cycle exist between 2 valid windows */
+		for (cnt = 1; cnt <= row_index; cnt++) {
+			if (phases_per_row[cnt]) {
+				for (i = 0; i <= phases_per_row[cnt]; i++) {
+					if (ranges[cnt][i] == 15) {
+						phase_15_found = true;
+						phase_15_raw_index = cnt;
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	/* If 2 valid windows form cycle then merge them as single window */
+	if (phase_0_found && phase_15_found) {
+		/* number of phases in raw where phase 0 is present */
+		u8 phases_0 = phases_per_row[phase_0_raw_index];
+		/* number of phases in raw where phase 15 is present */
+		u8 phases_15 = phases_per_row[phase_15_raw_index];
+
+		cnt = 0;
+		for (i = phases_15; i < (phases_15 + phases_0); i++) {
+			ranges[phase_15_raw_index][i] =
+				ranges[phase_0_raw_index][cnt];
+			cnt++;
+		}
+		phases_per_row[phase_0_raw_index] = 0;
+		phases_per_row[phase_15_raw_index] = phases_15 + phases_0;
+	}
+
+	for (cnt = 0; cnt <= row_index; cnt++) {
 		if (phases_per_row[cnt] > curr_max) {
 			curr_max = phases_per_row[cnt];
 			selected_row_index = cnt;
 		}
 	}
 
-	temp = ((curr_max * 3) / 4);
-	ret = ranges[selected_row_index][temp];
+	i = ((curr_max * 3) / 4) - 1;
+	ret = ranges[selected_row_index][i];
 
 	return ret;
 }
@@ -2981,11 +3021,12 @@
 			!memcmp(data_buf, cmd19_tuning_block, 64)) {
 			/* tuning is successful with this tuning point */
 			tuned_phases[tuned_phase_cnt++] = phase;
+			pr_debug("%s: %s: found good phase = %d\n",
+				mmc_hostname(mmc), __func__, phase);
 		}
 	} while (++phase < 16);
 
 	if (tuned_phase_cnt) {
-		tuned_phase_cnt--;
 		phase = find_most_appropriate_phase(host, tuned_phases,
 							tuned_phase_cnt);
 		/*
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 5c62769..b83e871 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -283,6 +283,14 @@
 	---help---
 	  A driver for Qualcomm WLAN SDIO Libra chipset.
 
+config ATH6K_LEGACY
+	tristate "QCA AR6003 wlan SDIO driver"
+	depends on MMC_MSM && WLAN
+	select WIRELESS_EXT
+	select WEXT_PRIV
+	---help---
+	This module adds support for wireless adapters based on QCA AR6003 chipset running over SDIO.
+
 config WCNSS_CORE
 	tristate "Qualcomm WCNSS CORE driver"
 	depends on ARCH_MSM8960
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 7217434..d99f13a 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -41,12 +41,53 @@
 	struct resource	*rx_irq_res;
 	struct resource	*gpios_5wire;
 	const struct dev_pm_ops *pm_ops;
-	int             triggered;
-	int             smd_channel_ready;
+	int		triggered;
+	int		smd_channel_ready;
+	unsigned int	serial_number;
 	struct wcnss_wlan_config wlan_config;
 	struct delayed_work wcnss_work;
 } *penv = NULL;
 
+static ssize_t wcnss_serial_number_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	if (!penv)
+		return -ENODEV;
+
+	return scnprintf(buf, PAGE_SIZE, "%08X\n", penv->serial_number);
+}
+
+static ssize_t wcnss_serial_number_store(struct device *dev,
+		struct device_attribute *attr, const char * buf, size_t count)
+{
+	unsigned int value;
+
+	if (!penv)
+		return -ENODEV;
+
+	if (sscanf(buf, "%08X", &value) != 1)
+		return -EINVAL;
+
+	penv->serial_number = value;
+	return count;
+}
+
+static DEVICE_ATTR(serial_number, S_IRUSR | S_IWUSR,
+	wcnss_serial_number_show, wcnss_serial_number_store);
+
+static int wcnss_create_sysfs(struct device *dev)
+{
+	if (!dev)
+		return -ENODEV;
+	return device_create_file(dev, &dev_attr_serial_number);
+}
+
+static void wcnss_remove_sysfs(struct device *dev)
+{
+	if (dev)
+		device_remove_file(dev, &dev_attr_serial_number);
+}
+
 static void wcnss_post_bootup(struct work_struct *work)
 {
 	pr_info("%s: Cancel APPS vote for Iris & Riva\n", __func__);
@@ -189,6 +230,14 @@
 }
 EXPORT_SYMBOL(wcnss_wlan_unregister_pm_ops);
 
+unsigned int wcnss_get_serial_number(void)
+{
+	if (penv)
+		return penv->serial_number;
+	return 0;
+}
+EXPORT_SYMBOL(wcnss_get_serial_number);
+
 static int wcnss_wlan_suspend(struct device *dev)
 {
 	if (penv && dev && (dev == &penv->pdev->dev) &&
@@ -272,8 +321,14 @@
 		goto fail_res;
 	}
 
+	/* register sysfs entries */
+	ret = wcnss_create_sysfs(&pdev->dev);
+	if (ret)
+		goto fail_sysfs;
+
 	return 0;
 
+fail_sysfs:
 fail_res:
 	if (penv->pil)
 		pil_put(penv->pil);
@@ -360,6 +415,7 @@
 static int __devexit
 wcnss_wlan_remove(struct platform_device *pdev)
 {
+	wcnss_remove_sysfs(&pdev->dev);
 	return 0;
 }
 
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 2e80692..93de829 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -1893,7 +1893,7 @@
 	INIT_DELAYED_WORK(&chip->calib_ccadc_work, calibrate_ccadc_work);
 	/* begin calibration only on chips > 2.0 */
 	if (chip->revision >= PM8XXX_REVISION_8921_2p0)
-		calibrate_ccadc_work(&(chip->calib_ccadc_work.work));
+		schedule_delayed_work(&chip->calib_ccadc_work, 0);
 
 	/* initial hkadc calibration */
 	schedule_work(&chip->calib_hkadc_work);
diff --git a/drivers/power/pm8xxx-ccadc.c b/drivers/power/pm8xxx-ccadc.c
index 17cf53a..c95fd93 100644
--- a/drivers/power/pm8xxx-ccadc.c
+++ b/drivers/power/pm8xxx-ccadc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -209,7 +209,7 @@
 			return rc;
 		}
 		if ((reg & (START_CONV_BIT | EOC_CONV_BIT)) != EOC_CONV_BIT)
-			msleep(60);
+			msleep(20);
 		else
 			break;
 	}
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 6c5b380..02d1c39 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -75,6 +75,8 @@
 #define SAT_MSG_VER	0x1
 #define SAT_MSG_PROT	0x1
 #define MSM_SAT_SUCCSS	0x20
+#define MSM_MAX_NSATS	2
+#define MSM_MAX_SATCH	32
 
 #define QC_MFGID_LSB	0x2
 #define QC_MFGID_MSB	0x17
@@ -225,7 +227,7 @@
 	int			err;
 	int			ee;
 	struct completion	*wr_comp;
-	struct msm_slim_sat	*satd;
+	struct msm_slim_sat	*satd[MSM_MAX_NSATS];
 	struct msm_slim_endp	pipes[7];
 	struct msm_slim_sps_bam	bam;
 	struct msm_slim_endp	rx_msgq;
@@ -240,6 +242,14 @@
 	bool			reconf_busy;
 	bool			chan_active;
 	enum msm_ctrl_state	state;
+	int			nsats;
+};
+
+struct msm_sat_chan {
+	u8 chan;
+	u16 chanh;
+	int req_rem;
+	int req_def;
 };
 
 struct msm_slim_sat {
@@ -248,7 +258,7 @@
 	struct workqueue_struct *wq;
 	struct work_struct	wd;
 	u8			sat_msgs[SAT_CONCUR_MSG][40];
-	u16			*satch;
+	struct msm_sat_chan	*satch;
 	u8			nsatch;
 	bool			sent_capability;
 	bool			pending_reconf;
@@ -258,6 +268,8 @@
 	spinlock_t lock;
 };
 
+static struct msm_slim_sat *msm_slim_alloc_sat(struct msm_slim_ctrl *dev);
+
 static int msm_slim_rx_enqueue(struct msm_slim_ctrl *dev, u32 *buf, u8 len)
 {
 	spin_lock(&dev->rx_lock);
@@ -364,6 +376,18 @@
 #endif
 }
 
+static struct msm_slim_sat *addr_to_sat(struct msm_slim_ctrl *dev, u8 laddr)
+{
+	struct msm_slim_sat *sat = NULL;
+	int i = 0;
+	while (!sat && i < dev->nsats) {
+		if (laddr == dev->satd[i]->satcl.laddr)
+			sat = dev->satd[i];
+		i++;
+	}
+	return sat;
+}
+
 static irqreturn_t msm_slim_interrupt(int irq, void *d)
 {
 	struct msm_slim_ctrl *dev = d;
@@ -403,8 +427,13 @@
 		dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
 		if (mt == SLIM_MSG_MT_DEST_REFERRED_USER ||
 				mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
-			struct msm_slim_sat *sat = dev->satd;
-			msm_sat_enqueue(sat, rx_buf, len);
+			u8 laddr = (u8)((rx_buf[0] >> 16) & 0xFF);
+			struct msm_slim_sat *sat = addr_to_sat(dev, laddr);
+			if (sat)
+				msm_sat_enqueue(sat, rx_buf, len);
+			else
+				dev_err(dev->dev, "unknown sat:%d message",
+						laddr);
 			writel_relaxed(MGR_INT_RX_MSG_RCVD,
 					dev->base + MGR_INT_CLR);
 			/*
@@ -412,37 +441,21 @@
 			 * queuing work
 			 */
 			mb();
-			queue_work(sat->wq, &sat->wd);
+			if (sat)
+				queue_work(sat->wq, &sat->wd);
 		} else if (mt == SLIM_MSG_MT_CORE &&
 			mc == SLIM_MSG_MC_REPORT_PRESENT) {
 			u8 e_addr[6];
 			msm_get_eaddr(e_addr, rx_buf);
-			if (msm_is_sat_dev(e_addr)) {
-				/*
-				 * Consider possibility that this device may
-				 * be reporting more than once?
-				 */
-				struct msm_slim_sat *sat = dev->satd;
-				msm_sat_enqueue(sat, rx_buf, len);
-				writel_relaxed(MGR_INT_RX_MSG_RCVD, dev->base +
-							MGR_INT_CLR);
-				/*
-				 * Guarantee that CLR bit write goes through
-				 * before queuing work
-				 */
-				mb();
-				queue_work(sat->wq, &sat->wd);
-			} else {
-				msm_slim_rx_enqueue(dev, rx_buf, len);
-				writel_relaxed(MGR_INT_RX_MSG_RCVD, dev->base +
-							MGR_INT_CLR);
-				/*
-				 * Guarantee that CLR bit write goes through
-				 * before signalling completion
-				 */
-				mb();
-				complete(&dev->rx_msgq_notify);
-			}
+			msm_slim_rx_enqueue(dev, rx_buf, len);
+			writel_relaxed(MGR_INT_RX_MSG_RCVD, dev->base +
+						MGR_INT_CLR);
+			/*
+			 * Guarantee that CLR bit write goes through
+			 * before signalling completion
+			 */
+			mb();
+			complete(&dev->rx_msgq_notify);
 		} else if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
 				mc == SLIM_MSG_MC_REPLY_VALUE) {
 			msm_slim_rx_enqueue(dev, rx_buf, len);
@@ -959,18 +972,67 @@
 	int i;
 	int ret = 0;
 	if (mc == SLIM_USR_MC_CHAN_CTRL) {
-		u16 chanh = sat->satch[buf[5]];
+		for (i = 0; i < sat->nsatch; i++) {
+			if (buf[5] == sat->satch[i].chan)
+				break;
+		}
+		if (i >= sat->nsatch)
+			return -ENOTCONN;
 		oper = ((buf[3] & 0xC0) >> 6);
 		/* part of grp. activating/removing 1 will take care of rest */
-		ret = slim_control_ch(&sat->satcl, chanh, oper, false);
+		ret = slim_control_ch(&sat->satcl, sat->satch[i].chanh, oper,
+					false);
+		if (!ret) {
+			for (i = 5; i < len; i++) {
+				int j;
+				for (j = 0; j < sat->nsatch; j++) {
+					if (buf[i] == sat->satch[j].chan) {
+						if (oper == SLIM_CH_REMOVE)
+							sat->satch[j].req_rem++;
+						else
+							sat->satch[j].req_def++;
+						break;
+					}
+				}
+			}
+		}
 	} else {
 		u16 chh[40];
 		struct slim_ch prop;
 		u32 exp;
 		u8 coeff, cc;
 		u8 prrate = buf[6];
-		for (i = 8; i < len; i++)
-			chh[i-8] = sat->satch[buf[i]];
+		if (len <= 8)
+			return -EINVAL;
+		for (i = 8; i < len; i++) {
+			int j = 0;
+			for (j = 0; j < sat->nsatch; j++) {
+				if (sat->satch[j].chan == buf[i]) {
+					chh[i - 8] = sat->satch[j].chanh;
+					break;
+				}
+			}
+			if (j < sat->nsatch) {
+				u16 dummy;
+				ret = slim_query_ch(&sat->satcl, buf[i],
+							&dummy);
+				if (ret)
+					return ret;
+				if (mc == SLIM_USR_MC_DEF_ACT_CHAN)
+					sat->satch[j].req_def++;
+				continue;
+			}
+			if (sat->nsatch >= MSM_MAX_SATCH)
+				return -EXFULL;
+			ret = slim_query_ch(&sat->satcl, buf[i], &chh[i - 8]);
+			if (ret)
+				return ret;
+			sat->satch[j].chan = buf[i];
+			sat->satch[j].chanh = chh[i - 8];
+			if (mc == SLIM_USR_MC_DEF_ACT_CHAN)
+				sat->satch[j].req_def++;
+			sat->nsatch++;
+		}
 		prop.dataf = (enum slim_ch_dataf)((buf[3] & 0xE0) >> 5);
 		prop.auxf = (enum slim_ch_auxf)((buf[4] & 0xC0) >> 5);
 		prop.baser = SLIM_RATE_4000HZ;
@@ -986,17 +1048,18 @@
 		prop.ratem = cc * (1 << exp);
 		if (i > 9)
 			ret = slim_define_ch(&sat->satcl, &prop, chh, len - 8,
-						true, &sat->satch[buf[8]]);
+					true, &chh[0]);
 		else
 			ret = slim_define_ch(&sat->satcl, &prop,
-						&sat->satch[buf[8]], 1, false,
-						NULL);
+					&chh[0], 1, false, NULL);
 		dev_dbg(dev->dev, "define sat grp returned:%d", ret);
+		if (ret)
+			return ret;
 
 		/* part of group so activating 1 will take care of rest */
 		if (mc == SLIM_USR_MC_DEF_ACT_CHAN)
 			ret = slim_control_ch(&sat->satcl,
-					sat->satch[buf[8]],
+					chh[0],
 					SLIM_CH_ACTIVATE, false);
 	}
 	return ret;
@@ -1029,6 +1092,18 @@
 				laddr == (QC_MSM_DEVS - 1))
 				pm_runtime_enable(dev->dev);
 
+			if (!ret && msm_is_sat_dev(e_addr)) {
+				struct msm_slim_sat *sat = addr_to_sat(dev,
+								laddr);
+				if (!sat)
+					sat = msm_slim_alloc_sat(dev);
+				if (!sat)
+					return;
+
+				sat->satcl.laddr = laddr;
+				msm_sat_enqueue(sat, (u32 *)buf, len);
+				queue_work(sat->wq, &sat->wd);
+			}
 		} else if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
 				mc == SLIM_MSG_MC_REPLY_VALUE) {
 			u8 tid = buf[3];
@@ -1064,7 +1139,6 @@
 
 	while ((msm_sat_dequeue(sat, buf)) != -ENODATA) {
 		struct slim_msg_txn txn;
-		int i;
 		u8 len, mc, mt;
 		u32 bw_sl;
 		int ret = 0;
@@ -1072,6 +1146,7 @@
 		bool gen_ack = false;
 		u8 tid;
 		u8 wbuf[8];
+		int i;
 		txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
 		txn.dt = SLIM_MSG_DEST_LOGICALADDR;
 		txn.ec = 0;
@@ -1112,20 +1187,23 @@
 				continue;
 			}
 			/* send a Manager capability msg */
-			if (sat->sent_capability)
-				continue;
+			if (sat->sent_capability) {
+				if (mt == SLIM_MSG_MT_CORE)
+					goto send_capability;
+				else
+					continue;
+			}
 			ret = slim_add_device(&dev->ctrl, &sat->satcl);
 			if (ret) {
 				dev_err(dev->dev,
 					"Satellite-init failed");
 				continue;
 			}
-			/* Satellite owns first 21 channels */
-			sat->satch = kzalloc(21 * sizeof(u16), GFP_KERNEL);
-			sat->nsatch = 20;
-			/* alloc all sat chans */
-			for (i = 0; i < 21; i++)
-				slim_alloc_ch(&sat->satcl, &sat->satch[i]);
+			/* Satellite-channels */
+			sat->satch = kzalloc(MSM_MAX_SATCH *
+					sizeof(struct msm_sat_chan),
+					GFP_KERNEL);
+send_capability:
 			txn.mc = SLIM_USR_MC_MASTER_CAPABILITY;
 			txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
 			txn.la = sat->satcl.laddr;
@@ -1176,6 +1254,20 @@
 			tid = buf[3];
 			gen_ack = true;
 			ret = slim_reconfigure_now(&sat->satcl);
+			for (i = 0; i < sat->nsatch; i++) {
+				struct msm_sat_chan *sch = &sat->satch[i];
+				if (sch->req_rem) {
+					if (!ret)
+						slim_dealloc_ch(&sat->satcl,
+								sch->chanh);
+					sch->req_rem--;
+				} else if (sch->req_def) {
+					if (ret)
+						slim_dealloc_ch(&sat->satcl,
+								sch->chanh);
+					sch->req_def--;
+				}
+			}
 			if (sat->pending_reconf) {
 				msm_slim_put_ctrl(dev);
 				sat->pending_reconf = false;
@@ -1243,6 +1335,44 @@
 	}
 }
 
+static struct msm_slim_sat *msm_slim_alloc_sat(struct msm_slim_ctrl *dev)
+{
+	struct msm_slim_sat *sat;
+	char *name;
+	if (dev->nsats >= MSM_MAX_NSATS)
+		return NULL;
+
+	sat = kzalloc(sizeof(struct msm_slim_sat), GFP_KERNEL);
+	if (!sat) {
+		dev_err(dev->dev, "no memory for satellite");
+		return NULL;
+	}
+	name = kzalloc(SLIMBUS_NAME_SIZE, GFP_KERNEL);
+	if (!name) {
+		dev_err(dev->dev, "no memory for satellite name");
+		kfree(sat);
+		return NULL;
+	}
+	dev->satd[dev->nsats] = sat;
+	sat->dev = dev;
+	snprintf(name, SLIMBUS_NAME_SIZE, "msm_sat%d", dev->nsats);
+	sat->satcl.name = name;
+	spin_lock_init(&sat->lock);
+	INIT_WORK(&sat->wd, slim_sat_rxprocess);
+	sat->wq = create_singlethread_workqueue(sat->satcl.name);
+	if (!sat->wq) {
+		kfree(name);
+		kfree(sat);
+		return NULL;
+	}
+	/*
+	 * Both sats will be allocated from RX thread and RX thread will
+	 * process messages sequentially. No synchronization necessary
+	 */
+	dev->nsats++;
+	return sat;
+}
+
 static void
 msm_slim_rx_msgq_event(struct msm_slim_ctrl *dev, struct sps_event_notify *ev)
 {
@@ -1375,18 +1505,13 @@
 			mc = (buffer[0] >> 8) & 0xff;
 			dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
 			if (mt == SLIM_MSG_MT_DEST_REFERRED_USER ||
-				mt == SLIM_MSG_MT_SRC_REFERRED_USER)
-				sat = dev->satd;
-
+				mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
+				u8 laddr;
+				laddr = (u8)((buffer[0] >> 16) & 0xff);
+				sat = addr_to_sat(dev, laddr);
+			}
 		} else if ((index * 4) >= msg_len) {
 			index = 0;
-			if (mt == SLIM_MSG_MT_CORE &&
-				mc == SLIM_MSG_MC_REPORT_PRESENT) {
-				u8 e_addr[6];
-				msm_get_eaddr(e_addr, buffer);
-				if (msm_is_sat_dev(e_addr))
-					sat = dev->satd;
-			}
 			if (sat) {
 				msm_sat_enqueue(sat, buffer, msg_len);
 				queue_work(sat->wq, &sat->wd);
@@ -1737,11 +1862,6 @@
 	}
 
 
-	dev->rclk = clk_get(dev->dev, "audio_slimbus_clk");
-	if (!dev->rclk) {
-		dev_err(dev->dev, "slimbus clock not found");
-		goto err_clk_get_failed;
-	}
 	dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
 	dev->framer.superfreq =
 		dev->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
@@ -1756,21 +1876,24 @@
 		goto err_request_irq_failed;
 	}
 
-	dev->satd = kzalloc(sizeof(struct msm_slim_sat), GFP_KERNEL);
-	if (!dev->satd) {
-		ret = -ENOMEM;
-		goto err_sat_failed;
+	msm_slim_prg_slew(pdev, dev);
+
+	/* Register with framework before enabling frame, clock */
+	ret = slim_add_numbered_controller(&dev->ctrl);
+	if (ret) {
+		dev_err(dev->dev, "error adding controller\n");
+		goto err_ctrl_failed;
 	}
 
-	msm_slim_prg_slew(pdev, dev);
+
+	dev->rclk = clk_get(dev->dev, "audio_slimbus_clk");
+	if (!dev->rclk) {
+		dev_err(dev->dev, "slimbus clock not found");
+		goto err_clk_get_failed;
+	}
 	clk_set_rate(dev->rclk, SLIM_ROOT_FREQ);
 	clk_enable(dev->rclk);
 
-	dev->satd->dev = dev;
-	dev->satd->satcl.name  = "msm_sat_dev";
-	spin_lock_init(&dev->satd->lock);
-	INIT_WORK(&dev->satd->wd, slim_sat_rxprocess);
-	dev->satd->wq = create_singlethread_workqueue("msm_slim_sat");
 	/* Component register initialization */
 	writel_relaxed(1, dev->base + COMP_CFG);
 	writel_relaxed((EE_MGR_RSC_GRP | EE_NGD_2 | EE_NGD_1),
@@ -1796,13 +1919,6 @@
 	 */
 	wmb();
 
-	/* Register with framework before enabling frame, clock */
-	ret = slim_add_numbered_controller(&dev->ctrl);
-	if (ret) {
-		dev_err(dev->dev, "error adding controller\n");
-		goto err_ctrl_failed;
-	}
-
 	/* Framer register initialization */
 	writel_relaxed((0xA << REF_CLK_GEAR) | (0xA << CLK_GEAR) |
 		(1 << ROOT_FREQ) | (1 << FRM_ACTIVE) | 1,
@@ -1855,13 +1971,9 @@
 
 err_ctrl_failed:
 	writel_relaxed(0, dev->base + COMP_CFG);
-	kfree(dev->satd);
-err_sat_failed:
-	free_irq(dev->irq, dev);
-err_request_irq_failed:
-	clk_disable(dev->rclk);
-	clk_put(dev->rclk);
 err_clk_get_failed:
+	kfree(dev->satd);
+err_request_irq_failed:
 	msm_slim_sps_exit(dev);
 err_sps_init_failed:
 	iounmap(dev->bam.base);
@@ -1882,13 +1994,20 @@
 	struct resource *bam_mem;
 	struct resource *slim_mem;
 	struct resource *slew_mem = dev->slew_mem;
-	struct msm_slim_sat *sat = dev->satd;
-	slim_remove_device(&sat->satcl);
+	int i;
+	for (i = 0; i < dev->nsats; i++) {
+		struct msm_slim_sat *sat = dev->satd[i];
+		int j;
+		for (j = 0; j < sat->nsatch; j++)
+			slim_dealloc_ch(&sat->satcl, sat->satch[j].chanh);
+		slim_remove_device(&sat->satcl);
+		kfree(sat->satch);
+		destroy_workqueue(sat->wq);
+		kfree(sat->satcl.name);
+		kfree(sat);
+	}
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
-	kfree(sat->satch);
-	destroy_workqueue(sat->wq);
-	kfree(sat);
 	free_irq(dev->irq, dev);
 	slim_del_controller(&dev->ctrl);
 	clk_put(dev->rclk);
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 84cb3f5..3aa4553 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -3,7 +3,7 @@
  * MSM 7k High speed uart driver
  *
  * Copyright (c) 2008 Google Inc.
- * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2012, Code Aurora Forum. All rights reserved.
  * Modified: Nick Pelly <npelly@google.com>
  *
  * All source code in this file is licensed under the following license
@@ -656,7 +656,6 @@
 	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
 
 	spin_lock_irqsave(&uport->lock, flags);
-	clk_enable(msm_uport->clk);
 
 	/*
 	 * Disable Rx channel of UARTDM
@@ -764,9 +763,7 @@
 	}
 
 	msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
-	/* calling other hardware component here clk_disable API. */
 	mb();
-	clk_disable(msm_uport->clk);
 	spin_unlock_irqrestore(&uport->lock, flags);
 }
 
@@ -778,16 +775,11 @@
 {
 	unsigned int data;
 	unsigned int ret = 0;
-	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-	clk_enable(msm_uport->clk);
 
 	data = msm_hs_read(uport, UARTDM_SR_ADDR);
 	if (data & UARTDM_SR_TXEMT_BMSK)
 		ret = TIOCSER_TEMT;
 
-	clk_disable(msm_uport->clk);
-
 	return ret;
 }
 EXPORT_SYMBOL(msm_hs_tx_empty);
@@ -817,8 +809,6 @@
 	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
 	unsigned int data;
 
-	clk_enable(msm_uport->clk);
-
 	/* disable dlink */
 	data = msm_hs_read(uport, UARTDM_DMEN_ADDR);
 	data &= ~UARTDM_RX_DM_EN_BMSK;
@@ -835,8 +825,6 @@
 	}
 	if (msm_uport->rx.flush != FLUSH_SHUTDOWN)
 		msm_uport->rx.flush = FLUSH_STOP;
-
-	clk_disable(msm_uport->clk);
 }
 
 /*  Transmit the next chunk of data */
@@ -1011,7 +999,6 @@
 
 	spin_lock_irqsave(&uport->lock, flags);
 
-	clk_enable(msm_uport->clk);
 	msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE);
 
 	/* overflow is not connect to data in a FIFO */
@@ -1085,7 +1072,6 @@
 		schedule_delayed_work(&msm_uport->rx.flip_insert_work
 				      , msecs_to_jiffies(RETRY_TIMEOUT));
 	}
-	clk_disable(msm_uport->clk);
 	/* release wakelock in 500ms, not immediately, because higher layers
 	 * don't always take wakelocks when they should */
 	wake_lock_timeout(&msm_uport->rx.wake_lock, HZ / 2);
@@ -1100,15 +1086,11 @@
 {
 	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
 
-	clk_enable(msm_uport->clk);
-
 	if (msm_uport->tx.tx_ready_int_en == 0) {
 		msm_uport->tx.tx_ready_int_en = 1;
 		if (msm_uport->tx.dma_in_flight == 0)
 			msm_hs_submit_tx_locked(uport);
 	}
-
-	clk_disable(msm_uport->clk);
 }
 
 /*
@@ -1138,14 +1120,12 @@
 				tlet_ptr, struct msm_hs_port, tx.tlet);
 
 	spin_lock_irqsave(&(msm_uport->uport.lock), flags);
-	clk_enable(msm_uport->clk);
 
 	msm_uport->imr_reg |= UARTDM_ISR_TX_READY_BMSK;
 	msm_hs_write(&(msm_uport->uport), UARTDM_IMR_ADDR, msm_uport->imr_reg);
 	/* Calling clk API. Hence mb() requires. */
 	mb();
 
-	clk_disable(msm_uport->clk);
 	spin_unlock_irqrestore(&(msm_uport->uport.lock), flags);
 }
 
@@ -1198,9 +1178,6 @@
 {
 	unsigned int set_rts;
 	unsigned int data;
-	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-	clk_enable(msm_uport->clk);
 
 	/* RTS is active low */
 	set_rts = TIOCM_RTS & mctrl ? 0 : 1;
@@ -1217,9 +1194,7 @@
 		data |= UARTDM_MR1_RX_RDY_CTL_BMSK;
 		msm_hs_write(uport, UARTDM_MR1_ADDR, data);
 	}
-	/* Calling CLOCK API. Hence mb() requires. */
 	mb();
-	clk_disable(msm_uport->clk);
 }
 
 void msm_hs_set_mctrl(struct uart_port *uport,
@@ -1238,16 +1213,11 @@
 {
 	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
 
-	clk_enable(msm_uport->clk);
-
 	/* Enable DELTA_CTS Interrupt */
 	msm_uport->imr_reg |= UARTDM_ISR_DELTA_CTS_BMSK;
 	msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
-	/* Calling CLOCK API. Hence mb() requires here. */
 	mb();
 
-	clk_disable(msm_uport->clk);
-
 }
 
 /*
@@ -1259,14 +1229,10 @@
 static void msm_hs_break_ctl(struct uart_port *uport, int ctl)
 {
 	unsigned long flags;
-	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
 
 	spin_lock_irqsave(&uport->lock, flags);
-	clk_enable(msm_uport->clk);
 	msm_hs_write(uport, UARTDM_CR_ADDR, ctl ? START_BREAK : STOP_BREAK);
-	/* Calling CLOCK API. Hence mb() requires here. */
 	mb();
-	clk_disable(msm_uport->clk);
 	spin_unlock_irqrestore(&uport->lock, flags);
 }
 
@@ -1295,18 +1261,12 @@
 /*  Handle CTS changes (Called from interrupt handler) */
 static void msm_hs_handle_delta_cts_locked(struct uart_port *uport)
 {
-	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-	clk_enable(msm_uport->clk);
-
 	/* clear interrupt */
 	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_CTS);
 	/* Calling CLOCK API. Hence mb() requires here. */
 	mb();
 	uport->icount.cts++;
 
-	clk_disable(msm_uport->clk);
-
 	/* clear the IOCTL TIOCMIWAIT if called */
 	wake_up_interruptible(&uport->state->port.delta_msr_wait);
 }
@@ -1999,8 +1959,6 @@
 	tasklet_kill(&msm_uport->rx.tlet);
 	cancel_delayed_work_sync(&msm_uport->rx.flip_insert_work);
 
-	clk_enable(msm_uport->clk);
-
 	pm_runtime_disable(uport->dev);
 	pm_runtime_set_suspended(uport->dev);
 
@@ -2018,7 +1976,6 @@
 	 */
 	mb();
 
-	clk_disable(msm_uport->clk);  /* to balance local clk_enable() */
 	if (msm_uport->clk_state != MSM_HS_CLK_OFF) {
 		clk_disable(msm_uport->clk);  /* to balance clk_state */
 		if (msm_uport->pclk)
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 35327cc..ff4bbad 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -858,6 +858,32 @@
 	*idx = (*idx + 1) & (DBG_DATA_MAX-1);
 }
 
+
+static unsigned int ep_addr_txdbg_mask;
+module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
+static unsigned int ep_addr_rxdbg_mask;
+module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
+
+static int allow_dbg_print(u8 addr)
+{
+	int dir, num;
+
+	/* allow bus wide events */
+	if (addr == 0xff)
+		return 1;
+
+	dir = addr & USB_ENDPOINT_DIR_MASK ? TX : RX;
+	num = addr & ~USB_ENDPOINT_DIR_MASK;
+	num = 1 << num;
+
+	if ((dir == TX) && (num & ep_addr_txdbg_mask))
+		return 1;
+	if ((dir == RX) && (num & ep_addr_rxdbg_mask))
+		return 1;
+
+	return 0;
+}
+
 /**
  * dbg_print:  prints the common part of the event
  * @addr:   endpoint address
@@ -871,6 +897,9 @@
 	unsigned int stamp;
 	unsigned long flags;
 
+	if (!allow_dbg_print(addr))
+		return;
+
 	write_lock_irqsave(&dbg_data.lck, flags);
 
 	do_gettimeofday(&tval);
@@ -1407,7 +1436,7 @@
 
 	n = hw_ep_bit(mEp->num, mEp->dir);
 	pr_info("%s: prime:%08x stat:%08x ep#%d dir:%s"
-			"dTD_update_fail_count: %lu"
+			"dTD_update_fail_count: %lu "
 			"mEp->dTD_update_fail_count: %lu\n", __func__,
 			hw_cread(CAP_ENDPTPRIME, ~0),
 			hw_cread(CAP_ENDPTSTAT, ~0),
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 69a36af..380ef87 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -755,6 +755,8 @@
 
 		/* copy descriptors, and track endpoint copies */
 		f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
+		if (!f->hs_descriptors)
+			goto fail;
 
 		acm->hs.in = usb_find_endpoint(acm_hs_function,
 				f->hs_descriptors, &acm_hs_in_desc);
@@ -772,6 +774,11 @@
 	return 0;
 
 fail:
+	if (f->hs_descriptors)
+		usb_free_descriptors(f->hs_descriptors);
+	if (f->descriptors)
+		usb_free_descriptors(f->descriptors);
+
 	if (acm->notify_req)
 		gs_free_req(acm->notify, acm->notify_req);
 
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index 66cdcb1..aab5b98 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/uaccess.h>
 #include <linux/usb.h>
+#include <linux/debugfs.h>
 #include <mach/diag_bridge.h>
 
 #define DRIVER_DESC	"USB host diag bridge driver"
@@ -35,6 +36,12 @@
 	struct kref		kref;
 	struct diag_bridge_ops	*ops;
 	struct platform_device	*pdev;
+
+	/* debugging counters */
+	unsigned long		bytes_to_host;
+	unsigned long		bytes_to_mdm;
+	unsigned		pending_reads;
+	unsigned		pending_writes;
 };
 struct diag_bridge *__dev;
 
@@ -84,6 +91,9 @@
 			urb->transfer_buffer,
 			urb->transfer_buffer_length,
 			urb->status < 0 ? urb->status : urb->actual_length);
+
+	dev->bytes_to_host += urb->actual_length;
+	dev->pending_reads--;
 }
 
 int diag_bridge_read(char *data, int size)
@@ -119,10 +129,12 @@
 	usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
 				diag_bridge_read_cb, dev);
 	usb_anchor_urb(urb, &dev->submitted);
+	dev->pending_reads++;
 
 	ret = usb_submit_urb(urb, GFP_ATOMIC);
 	if (ret) {
 		dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret);
+		dev->pending_reads--;
 		usb_unanchor_urb(urb);
 		usb_free_urb(urb);
 		return ret;
@@ -151,6 +163,9 @@
 			urb->transfer_buffer,
 			urb->transfer_buffer_length,
 			urb->status < 0 ? urb->status : urb->actual_length);
+
+	dev->bytes_to_mdm += urb->actual_length;
+	dev->pending_writes--;
 }
 
 int diag_bridge_write(char *data, int size)
@@ -186,10 +201,12 @@
 	usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
 				diag_bridge_write_cb, dev);
 	usb_anchor_urb(urb, &dev->submitted);
+	dev->pending_writes++;
 
 	ret = usb_submit_urb(urb, GFP_ATOMIC);
 	if (ret) {
-		err("submitting urb failed err:%d", ret);
+		dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret);
+		dev->pending_writes--;
 		usb_unanchor_urb(urb);
 		usb_free_urb(urb);
 		return ret;
@@ -211,6 +228,79 @@
 	kfree(dev);
 }
 
+#if defined(CONFIG_DEBUG_FS)
+#define DEBUG_BUF_SIZE	512
+static ssize_t diag_read_stats(struct file *file, char __user *ubuf,
+				size_t count, loff_t *ppos)
+{
+	struct diag_bridge	*dev = __dev;
+	char			*buf;
+	int			ret;
+
+	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = scnprintf(buf, DEBUG_BUF_SIZE,
+			"epin:%d, epout:%d\n"
+			"bytes to host: %lu\n"
+			"bytes to mdm: %lu\n"
+			"pending reads: %u\n"
+			"pending writes: %u\n"
+			"last error: %d\n",
+			dev->in_epAddr, dev->out_epAddr,
+			dev->bytes_to_host, dev->bytes_to_mdm,
+			dev->pending_reads, dev->pending_writes,
+			dev->err);
+
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t diag_reset_stats(struct file *file, const char __user *buf,
+				 size_t count, loff_t *ppos)
+{
+	struct diag_bridge	*dev = __dev;
+
+	dev->bytes_to_host = dev->bytes_to_mdm = 0;
+	dev->pending_reads = dev->pending_writes = 0;
+
+	return count;
+}
+
+const struct file_operations diag_stats_ops = {
+	.read = diag_read_stats,
+	.write = diag_reset_stats,
+};
+
+static struct dentry *dent;
+
+static void diag_bridge_debugfs_init(void)
+{
+	struct dentry *dfile;
+
+	dent = debugfs_create_dir("diag_bridge", 0);
+	if (IS_ERR(dent))
+		return;
+
+	dfile = debugfs_create_file("status", 0444, dent, 0, &diag_stats_ops);
+	if (!dfile || IS_ERR(dfile))
+		debugfs_remove(dent);
+}
+
+static void diag_bridge_debugfs_cleanup(void)
+{
+	if (dent) {
+		debugfs_remove_recursive(dent);
+		dent = NULL;
+	}
+}
+#else
+static inline void diag_bridge_debugfs_init(void) { }
+static inline void diag_bridge_debugfs_cleanup(void) { }
+#endif
+
 static int
 diag_bridge_probe(struct usb_interface *ifc, const struct usb_device_id *id)
 {
@@ -265,7 +355,7 @@
 	}
 
 	usb_set_intfdata(ifc, dev);
-
+	diag_bridge_debugfs_init();
 	platform_device_add(dev->pdev);
 
 	dev_dbg(&dev->udev->dev, "%s: complete\n", __func__);
@@ -286,6 +376,7 @@
 	dev_dbg(&dev->udev->dev, "%s:\n", __func__);
 
 	platform_device_del(dev->pdev);
+	diag_bridge_debugfs_cleanup();
 	kref_put(&dev->kref, diag_bridge_delete);
 	usb_set_intfdata(ifc, NULL);
 }
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 00e4fda..4e1895f 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -37,11 +37,13 @@
 #include <linux/usb/msm_hsusb_hw.h>
 #include <linux/regulator/consumer.h>
 #include <linux/mfd/pm8xxx/pm8921-charger.h>
+#include <linux/mfd/pm8xxx/misc.h>
 #include <linux/pm_qos_params.h>
 #include <linux/power_supply.h>
 
 #include <mach/clk.h>
 #include <mach/msm_xo.h>
+#include <mach/msm_bus.h>
 
 #define MSM_USB_BASE	(motg->regs)
 #define DRIVER_NAME	"msm_otg"
@@ -570,6 +572,9 @@
 		writel_relaxed(val, USB_OTGSC);
 		ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
 		ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL);
+	} else if (pdata->otg_control == OTG_PMIC_CONTROL) {
+		/* Enable PMIC pull-up */
+		pm8xxx_usb_id_pullup(1);
 	}
 
 	return 0;
@@ -607,7 +612,7 @@
 	struct usb_bus *bus = otg->host;
 	struct msm_otg_platform_data *pdata = motg->pdata;
 	int cnt = 0;
-	bool host_bus_suspend;
+	bool host_bus_suspend, dcp;
 	u32 phy_ctrl_val = 0, cmd_val;
 	u32 portsc;
 
@@ -616,6 +621,7 @@
 
 	disable_irq(motg->irq);
 	host_bus_suspend = otg->host && !test_bit(ID, &motg->inputs);
+	dcp = motg->chg_type == USB_DCP_CHARGER;
 	/*
 	 * Chipidea 45-nm PHY suspend sequence:
 	 *
@@ -688,7 +694,11 @@
 		cmd_val |= ULPI_STP_CTRL;
 	writel_relaxed(cmd_val, USB_USBCMD);
 
-	if (motg->caps & ALLOW_PHY_RETENTION && !host_bus_suspend) {
+	/*
+	 * BC1.2 spec mandates PD to enable VDP_SRC when charging from DCP.
+	 * PHY retention and collapse can not happen with VDP_SRC enabled.
+	 */
+	if (motg->caps & ALLOW_PHY_RETENTION && !host_bus_suspend && !dcp) {
 		phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
 		if (motg->pdata->otg_control == OTG_PHY_CONTROL)
 			/* Enable PHY HV interrupts to wake MPM/Link */
@@ -707,7 +717,8 @@
 	/* usb phy no more require TCXO clock, hence vote for TCXO disable */
 	clk_disable_unprepare(motg->xo_handle);
 
-	if (motg->caps & ALLOW_PHY_POWER_COLLAPSE && !host_bus_suspend) {
+	if (motg->caps & ALLOW_PHY_POWER_COLLAPSE &&
+			!host_bus_suspend && !dcp) {
 		msm_hsusb_ldo_enable(motg, 0);
 		motg->lpm_flags |= PHY_PWR_COLLAPSED;
 	}
@@ -1122,6 +1133,7 @@
 
 static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
 {
+	int ret;
 	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
 	struct msm_otg_platform_data *pdata = motg->pdata;
 
@@ -1142,11 +1154,27 @@
 		 * power collapse(pc) while running in peripheral mode.
 		 */
 		otg_pm_qos_update_latency(motg, 1);
+		/* Configure BUS performance parameters for MAX bandwidth */
+		if (motg->bus_perf_client) {
+			ret = msm_bus_scale_client_update_request(
+					motg->bus_perf_client, 1);
+			if (ret)
+				dev_err(motg->otg.dev, "%s: Failed to vote for "
+					   "bus bandwidth %d\n", __func__, ret);
+		}
 		usb_gadget_vbus_connect(otg->gadget);
 	} else {
 		dev_dbg(otg->dev, "gadget off\n");
 		usb_gadget_vbus_disconnect(otg->gadget);
 		otg_pm_qos_update_latency(motg, 0);
+		/* Configure BUS performance parameters to default */
+		if (motg->bus_perf_client) {
+			ret = msm_bus_scale_client_update_request(
+					motg->bus_perf_client, 0);
+			if (ret)
+				dev_err(motg->otg.dev, "%s: Failed to devote "
+					   "for bus bw %d\n", __func__, ret);
+		}
 		if (pdata->setup_gpio)
 			pdata->setup_gpio(OTG_STATE_UNDEFINED);
 	}
@@ -1283,6 +1311,8 @@
 		ulpi_write(otg, 0x01, 0x0C);
 		ulpi_write(otg, 0x10, 0x0F);
 		ulpi_write(otg, 0x10, 0x12);
+		/* Disable PMIC ID pull-up */
+		pm8xxx_usb_id_pullup(0);
 		/* Enable ACA ID detection */
 		ulpi_write(otg, 0x20, 0x85);
 		aca_id_turned_on = true;
@@ -1415,6 +1445,9 @@
 		ulpi_write(otg, chg_det, 0x34);
 		break;
 	case SNPS_28NM_INTEGRATED_PHY:
+		/* Turn off VDP_SRC */
+		ulpi_write(otg, 0x3, 0x86);
+		msleep(20);
 		/*
 		 * Configure DM as current source, DP as current sink
 		 * and enable battery charging comparators.
@@ -1616,8 +1649,8 @@
 
 #define MSM_CHG_DCD_POLL_TIME		(100 * HZ/1000) /* 100 msec */
 #define MSM_CHG_DCD_MAX_RETRIES		6 /* Tdcd_tmout = 6 * 100 msec */
-#define MSM_CHG_PRIMARY_DET_TIME	(40 * HZ/1000) /* TVDPSRC_ON */
-#define MSM_CHG_SECONDARY_DET_TIME	(40 * HZ/1000) /* TVDMSRC_ON */
+#define MSM_CHG_PRIMARY_DET_TIME	(50 * HZ/1000) /* TVDPSRC_ON */
+#define MSM_CHG_SECONDARY_DET_TIME	(50 * HZ/1000) /* TVDMSRC_ON */
 static void msm_chg_detect_work(struct work_struct *w)
 {
 	struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
@@ -1834,6 +1867,8 @@
 			case USB_CHG_STATE_DETECTED:
 				switch (motg->chg_type) {
 				case USB_DCP_CHARGER:
+					/* Enable VDP_SRC */
+					ulpi_write(otg, 0x2, 0x85);
 					msm_otg_notify_charger(motg,
 							IDEV_CHG_MAX);
 					pm_runtime_put_noidle(otg->dev);
@@ -2601,6 +2636,14 @@
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 
+	if (motg->pdata->bus_scale_table) {
+		motg->bus_perf_client =
+		    msm_bus_scale_register_client(motg->pdata->bus_scale_table);
+		if (!motg->bus_perf_client)
+			dev_err(motg->otg.dev, "%s: Failed to register BUS "
+						"scaling client!!\n", __func__);
+	}
+
 	return 0;
 
 remove_otg:
@@ -2702,6 +2745,9 @@
 	if (motg->pdata->swfi_latency)
 		pm_qos_remove_request(&motg->pm_qos_req_dma);
 
+	if (motg->bus_perf_client)
+		msm_bus_scale_unregister_client(motg->bus_perf_client);
+
 	kfree(motg);
 	return 0;
 }
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index f261931..d3f8b2b 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -174,6 +174,10 @@
         select FB_MSM_MIPI_DSI
         default n
 
+config FB_MSM_MIPI_DSI_NT35510
+	bool
+	select FB_MSM_MIPI_DSI
+
 config FB_MSM_MIPI_DSI_TC358764_DSI2LVDS
 	bool
 	select FB_MSM_MIPI_DSI
@@ -286,6 +290,16 @@
 	select FB_MSM_MIPI_DSI_RENESAS
 	default n
 
+config FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT
+	bool
+	select FB_MSM_MIPI_DSI_NT35510
+	default n
+
+config FB_MSM_MIPI_NT35510_CMD_WVGA_PT
+	bool
+	select FB_MSM_MIPI_DSI_NT35510
+	default n
+
 config FB_MSM_MIPI_CHIMEI_WXGA
 	bool "LVDS Chimei WXGA Panel using Toshiba MIPI DSI-to-LVDS bridge."
 	select FB_MSM_MIPI_DSI_TC358764_DSI2LVDS
@@ -295,6 +309,15 @@
 	  The panel is connected to the host
 	  via Toshiba DSI-to-LVDS bridge.
 
+config FB_MSM_MIPI_CHIMEI_WUXGA
+	bool "LVDS Chimei WUXGA Panel using Toshiba MIPI DSI-to-LVDS bridge."
+	select FB_MSM_MIPI_DSI_TC358764_DSI2LVDS
+	---help---
+	  Support for Chimei WUXGA (1920x1200) panel.
+	  The panel is using a serial LVDS input.
+	  The panel is connected to the host
+	  via Toshiba DSI-to-LVDS bridge.
+
 config FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
 	bool
 	select FB_MSM_MIPI_DSI_TRULY
@@ -428,8 +451,11 @@
 	select FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
 	select FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
 	select FB_MSM_MIPI_NOVATEK_CMD_QHD_PT
+	select FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT
+	select FB_MSM_MIPI_NT35510_CMD_WVGA_PT
 	select FB_MSM_MIPI_SIMULATOR_VIDEO
 	select FB_MSM_MIPI_CHIMEI_WXGA
+	select FB_MSM_MIPI_CHIMEI_WUXGA
 	---help---
 	  Support for MIPI panel auto detect
 
@@ -463,10 +489,20 @@
 	select FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT
 	select FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
 	select FB_MSM_MIPI_NOVATEK_CMD_QHD_PT
+	select FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT
+	select FB_MSM_MIPI_NT35510_CMD_WVGA_PT
 	select FB_MSM_MIPI_SIMULATOR_VIDEO
 	---help---
 	  Support for LCDC + MIPI panel auto detect
 
+config FB_MSM_LVDS_MIPI_PANEL_DETECT
+	bool "LVDS + MIPI Panel Auto Detect"
+	select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
+	select FB_MSM_LVDS_CHIMEI_WXGA
+	select FB_MSM_MIPI_CHIMEI_WXGA
+	---help---
+	  Support for LVDS + MIPI panel auto detect
+
 config FB_MSM_MDDI_PRISM_WVGA
 	bool "MDDI Prism WVGA Panel"
 	select FB_MSM_MDDI
@@ -525,10 +561,22 @@
 	bool "MIPI Chimei WXGA PT Panel"
 	select FB_MSM_MIPI_CHIMEI_WXGA
 
+config FB_MSM_MIPI_CHIMEI_WUXGA_PANEL
+	bool "MIPI Chimei WUXGA Panel"
+	select FB_MSM_MIPI_CHIMEI_WUXGA
+
 config FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT_PANEL
 	bool "MIPI Truly Video WVGA PT Panel"
 	select FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
 
+config FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT_PANEL
+	bool "MIPI NT35510 Video WVGA PT Panel"
+	select FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT
+
+config FB_MSM_MIPI_NT35510_CMD_WVGA_PT_PANEL
+	bool "MIPI NT35510 Command WVGA PT Panel"
+	select FB_MSM_MIPI_NT35510_CMD_WVGA_PT
+
 config FB_MSM_MIPI_SIMULATOR_VIDEO_PANEL
 	bool "MIPI Simulator Video Panel"
 	select FB_MSM_MIPI_SIMULATOR_VIDEO
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index 2d40b15..bd7628d 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -76,6 +76,7 @@
 obj-$(CONFIG_FB_MSM_MIPI_DSI_NOVATEK) += mipi_novatek.o
 obj-$(CONFIG_FB_MSM_MIPI_DSI_RENESAS) += mipi_renesas.o
 obj-$(CONFIG_FB_MSM_MIPI_DSI_TRULY) += mipi_truly.o
+obj-$(CONFIG_FB_MSM_MIPI_DSI_NT35510) += mipi_NT35510.o
 obj-$(CONFIG_FB_MSM_MIPI_DSI_SIMULATOR) += mipi_simulator.o
 
 # MIPI Bridge
@@ -116,7 +117,9 @@
 obj-y += mipi_toshiba_video_wvga_pt.o mipi_toshiba_video_wsvga_pt.o
 obj-y += mipi_novatek_video_qhd_pt.o mipi_novatek_cmd_qhd_pt.o
 obj-y += mipi_renesas_video_fwvga_pt.o mipi_renesas_cmd_fwvga_pt.o
+obj-y += mipi_NT35510_video_wvga_pt.o mipi_NT35510_cmd_wvga_pt.o
 obj-y += mipi_chimei_wxga_pt.o
+obj-y += mipi_chimei_wuxga.o
 obj-y += mipi_truly_video_wvga_pt.o
 else
 obj-$(CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT) += mipi_toshiba_video_wvga_pt.o
@@ -125,9 +128,13 @@
 obj-$(CONFIG_FB_MSM_MIPI_NOVATEK_CMD_QHD_PT) += mipi_novatek_cmd_qhd_pt.o
 obj-$(CONFIG_FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT) += mipi_renesas_video_fwvga_pt.o
 obj-$(CONFIG_FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT) += mipi_renesas_cmd_fwvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT) += mipi_renesas_video_fwvga_pt.o
 obj-$(CONFIG_FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT) += mipi_truly_video_wvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_NT35510_CMD_WVGA_PT) += mipi_NT35510_cmd_wvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT) += mipi_NT35510_video_wvga_pt.o
 obj-$(CONFIG_FB_MSM_MIPI_SIMULATOR_VIDEO) += mipi_simulator_video.o
 obj-$(CONFIG_FB_MSM_MIPI_CHIMEI_WXGA) += mipi_chimei_wxga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_CHIMEI_WUXGA) += mipi_chimei_wuxga.o
 endif
 
 obj-$(CONFIG_FB_MSM_LCDC_PANEL) += lcdc_panel.o
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 7fd4c56..07a075c 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1000,14 +1000,15 @@
 		return;
 
 	external_common_state->speaker_allocation_block = sad[1];
-	DEV_DBG("EDID: speaker allocation data=%s%s%s%s%s%s%s\n",
+	DEV_DBG("EDID: speaker allocation data SP byte = %08x %s%s%s%s%s%s%s\n",
+		sad[1],
 		(sad[1] & BIT(0)) ? "FL/FR," : "",
 		(sad[1] & BIT(1)) ? "LFE," : "",
 		(sad[1] & BIT(2)) ? "FC," : "",
 		(sad[1] & BIT(3)) ? "RL/RR," : "",
 		(sad[1] & BIT(4)) ? "RC," : "",
 		(sad[1] & BIT(5)) ? "FLC/FRC," : "",
-		(sad[1] & BIT(6)) ? "LFE," : "");
+		(sad[1] & BIT(6)) ? "RLC/RRC," : "");
 }
 
 static void hdmi_edid_extract_audio_data_blocks(const uint8 *in_buf)
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 56a6483..93e6d40 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -64,6 +64,8 @@
 EXPORT_SYMBOL(hdmi_msm_state_mutex);
 static DEFINE_MUTEX(hdcp_auth_state_mutex);
 
+static void hdmi_msm_dump_regs(const char *prefix);
+
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 static void hdmi_msm_hdcp_enable(void);
 #else
@@ -3280,14 +3282,23 @@
 }
 EXPORT_SYMBOL(hdmi_audio_packet_enable);
 
-static void hdmi_msm_audio_info_setup(boolean enabled, int num_of_channels,
-	int level_shift, boolean down_mix)
+
+/* TO-DO: return -EINVAL when num_of_channels and channel_allocation
+ *  does not match CEA 861-D spec.
+*/
+int hdmi_msm_audio_info_setup(bool enabled, u32 num_of_channels,
+	u32 channel_allocation, u32 level_shift, bool down_mix)
 {
-	uint32 channel_allocation = 0;	/* Default to FR,FL */
 	uint32 channel_count = 1;	/* Default to 2 channels
 					   -> See Table 17 in CEA-D spec */
 	uint32 check_sum, audio_info_0_reg, audio_info_1_reg;
 	uint32 audio_info_ctrl_reg;
+	u32 aud_pck_ctrl_2_reg;
+	u32 layout;
+
+	layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+	aud_pck_ctrl_2_reg = 1 | (layout << 1);
+	HDMI_OUTP(0x00044, aud_pck_ctrl_2_reg);
 
 	/* Please see table 20 Audio InfoFrame in HDMI spec
 	   FL  = front left
@@ -3310,6 +3321,7 @@
 	if (enabled) {
 		switch (num_of_channels) {
 		case MSM_HDMI_AUDIO_CHANNEL_2:
+			channel_allocation = 0;	/* Default to FR,FL */
 			break;
 		case MSM_HDMI_AUDIO_CHANNEL_4:
 			channel_count = 3;
@@ -3327,6 +3339,9 @@
 			channel_allocation = 0x1f;
 			break;
 		default:
+			pr_err("%s(): Unsupported num_of_channels = %u\n",
+					__func__, num_of_channels);
+			return -EINVAL;
 			break;
 		}
 
@@ -3382,7 +3397,14 @@
 	}
 	/* HDMI_INFOFRAME_CTRL0[0x002C] */
 	HDMI_OUTP(0x002C, audio_info_ctrl_reg);
+
+
+	hdmi_msm_dump_regs("HDMI-AUDIO-ON: ");
+
+	return 0;
+
 }
+EXPORT_SYMBOL(hdmi_msm_audio_info_setup);
 
 static void hdmi_msm_en_gc_packet(boolean av_mute_is_requested)
 {
@@ -3488,7 +3510,7 @@
 	hdmi_msm_audio_acr_setup(TRUE,
 		external_common_state->video_resolution,
 		msm_hdmi_sample_rate, channels);
-	hdmi_msm_audio_info_setup(TRUE, channels, 0, FALSE);
+	hdmi_msm_audio_info_setup(TRUE, channels, 0, 0, FALSE);
 
 	/* Turn on Audio FIFO and SAM DROP ISR */
 	HDMI_OUTP(0x02CC, HDMI_INP(0x02CC) | BIT(1) | BIT(3));
@@ -3519,7 +3541,7 @@
 			return -ETIMEDOUT;
 		}
 	}
-	hdmi_msm_audio_info_setup(FALSE, 0, 0, FALSE);
+	hdmi_msm_audio_info_setup(FALSE, 0, 0, 0, FALSE);
 	hdmi_msm_audio_acr_setup(FALSE, 0, 0, 0);
 	DEV_INFO("HDMI Audio: Disabled\n");
 	return 0;
@@ -4042,7 +4064,7 @@
 			return rc;
 		}
 	}
-	hdmi_msm_audio_info_setup(TRUE, 0, 0, FALSE);
+	hdmi_msm_audio_info_setup(TRUE, 0, 0, 0, FALSE);
 
 	mutex_lock(&external_common_state_hpd_mutex);
 	hdmi_msm_state->panel_power_on = TRUE;
diff --git a/drivers/video/msm/lvds.c b/drivers/video/msm/lvds.c
index 7ef437c..a69c64f 100644
--- a/drivers/video/msm/lvds.c
+++ b/drivers/video/msm/lvds.c
@@ -19,9 +19,10 @@
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/delay.h>
-#include <mach/hardware.h>
 #include <linux/io.h>
-
+#include <mach/hardware.h>
+#include <mach/msm_iomap.h>
+#include <mach/clk.h>
 #include <asm/system.h>
 #include <asm/mach-types.h>
 #include <linux/semaphore.h>
@@ -29,10 +30,9 @@
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
-#include <mach/clk.h>
 
 #include "msm_fb.h"
-
+#include "mdp4.h"
 static int lvds_probe(struct platform_device *pdev);
 static int lvds_remove(struct platform_device *pdev);
 
@@ -57,6 +57,126 @@
 
 static struct lcdc_platform_data *lvds_pdata;
 
+static void lvds_init(struct msm_fb_data_type *mfd)
+{
+	unsigned int lvds_intf, lvds_phy_cfg0;
+
+	MDP_OUTP(MDP_BASE + 0xc2034, 0x33);
+	usleep(1000);
+
+	/* LVDS PHY PLL configuration */
+	MDP_OUTP(MDP_BASE + 0xc3000, 0x08);
+	MDP_OUTP(MDP_BASE + 0xc3004, 0x87);
+	MDP_OUTP(MDP_BASE + 0xc3008, 0x30);
+	MDP_OUTP(MDP_BASE + 0xc300c, 0x06);
+	MDP_OUTP(MDP_BASE + 0xc3014, 0x20);
+	MDP_OUTP(MDP_BASE + 0xc3018, 0x0F);
+	MDP_OUTP(MDP_BASE + 0xc301c, 0x01);
+	MDP_OUTP(MDP_BASE + 0xc3020, 0x41);
+	MDP_OUTP(MDP_BASE + 0xc3024, 0x0d);
+	MDP_OUTP(MDP_BASE + 0xc3028, 0x07);
+	MDP_OUTP(MDP_BASE + 0xc302c, 0x00);
+	MDP_OUTP(MDP_BASE + 0xc3030, 0x1c);
+	MDP_OUTP(MDP_BASE + 0xc3034, 0x01);
+	MDP_OUTP(MDP_BASE + 0xc3038, 0x00);
+	MDP_OUTP(MDP_BASE + 0xc3040, 0xC0);
+	MDP_OUTP(MDP_BASE + 0xc3044, 0x00);
+	MDP_OUTP(MDP_BASE + 0xc3048, 0x30);
+	MDP_OUTP(MDP_BASE + 0xc304c, 0x00);
+
+	MDP_OUTP(MDP_BASE + 0xc3000, 0x11);
+	MDP_OUTP(MDP_BASE + 0xc3064, 0x05);
+	MDP_OUTP(MDP_BASE + 0xc3050, 0x20);
+
+	MDP_OUTP(MDP_BASE + 0xc3000, 0x01);
+	/* Wait until LVDS PLL is locked and ready */
+	while (!readl_relaxed(MDP_BASE + 0xc3080))
+		cpu_relax();
+
+	writel_relaxed(0x00, mmss_cc_base + 0x0264);
+	writel_relaxed(0x00, mmss_cc_base + 0x0094);
+
+	writel_relaxed(0x02, mmss_cc_base + 0x00E4);
+
+	writel_relaxed((0x80 | readl_relaxed(mmss_cc_base + 0x00E4)),
+	       mmss_cc_base + 0x00E4);
+	usleep(1000);
+	writel_relaxed((~0x80 & readl_relaxed(mmss_cc_base + 0x00E4)),
+	       mmss_cc_base + 0x00E4);
+
+	writel_relaxed(0x05, mmss_cc_base + 0x0094);
+	writel_relaxed(0x02, mmss_cc_base + 0x0264);
+	/* Wait until LVDS pixel clock output is enabled */
+	mb();
+
+	if (mfd->panel_info.bpp == 24) {
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
+		MDP_OUTP(MDP_BASE +  0xc2014, 0x03040508);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
+		MDP_OUTP(MDP_BASE +  0xc2018, 0x00000102);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
+		MDP_OUTP(MDP_BASE +  0xc201c, 0x0c0d1011);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
+		MDP_OUTP(MDP_BASE +  0xc2020, 0x00090a0b);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
+		MDP_OUTP(MDP_BASE +  0xc2024, 0x151a191a);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
+		MDP_OUTP(MDP_BASE +  0xc2028, 0x00121314);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_3_TO_0 */
+		MDP_OUTP(MDP_BASE +  0xc202c, 0x1706071b);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_6_TO_4 */
+		MDP_OUTP(MDP_BASE +  0xc2030, 0x000e0f16);
+
+		if (mfd->panel_info.lvds.channel_mode ==
+			LVDS_DUAL_CHANNEL_MODE) {
+			lvds_intf = 0x0001ff80;
+			lvds_phy_cfg0 = BIT(6) | BIT(7);
+			if (mfd->panel_info.lvds.channel_swap)
+				lvds_intf |= BIT(4);
+		} else {
+			lvds_intf = 0x00010f84;
+			lvds_phy_cfg0 = BIT(6);
+		}
+	} else if (mfd->panel_info.bpp == 18) {
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
+		MDP_OUTP(MDP_BASE +  0xc2014, 0x03040508);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
+		MDP_OUTP(MDP_BASE +  0xc2018, 0x00000102);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
+		MDP_OUTP(MDP_BASE +  0xc201c, 0x0c0d1011);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
+		MDP_OUTP(MDP_BASE +  0xc2020, 0x00090a0b);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
+		MDP_OUTP(MDP_BASE +  0xc2024, 0x1518191a);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
+		MDP_OUTP(MDP_BASE +  0xc2028, 0x00121314);
+
+		if (mfd->panel_info.lvds.channel_mode ==
+			LVDS_DUAL_CHANNEL_MODE) {
+			lvds_intf = 0x00017788;
+			lvds_phy_cfg0 = BIT(6) | BIT(7);
+			if (mfd->panel_info.lvds.channel_swap)
+				lvds_intf |= BIT(4);
+		} else {
+			lvds_intf = 0x0001078c;
+			lvds_phy_cfg0 = BIT(6);
+		}
+	}
+
+	/* MDP_LVDSPHY_CFG0 */
+	MDP_OUTP(MDP_BASE +  0xc3100, lvds_phy_cfg0);
+	/* MDP_LCDC_LVDS_INTF_CTL */
+	MDP_OUTP(MDP_BASE +  0xc2000, lvds_intf);
+	MDP_OUTP(MDP_BASE +  0xc3108, 0x30);
+	lvds_phy_cfg0 |= BIT(4);
+
+	/* Wait until LVDS PHY registers are configured */
+	mb();
+	usleep(1);
+	/* MDP_LVDSPHY_CFG0, enable serialization */
+	MDP_OUTP(MDP_BASE +  0xc3100, lvds_phy_cfg0);
+}
+
 static int lvds_off(struct platform_device *pdev)
 {
 	int ret = 0;
@@ -65,7 +185,8 @@
 	mfd = platform_get_drvdata(pdev);
 	ret = panel_next_off(pdev);
 
-	clk_disable(lvds_clk);
+	if (lvds_clk)
+		clk_disable(lvds_clk);
 
 	if (lvds_pdata && lvds_pdata->lcdc_power_save)
 		lvds_pdata->lcdc_power_save(0);
@@ -97,22 +218,24 @@
 #endif
 	mfd = platform_get_drvdata(pdev);
 
-	mfd->fbi->var.pixclock = clk_round_rate(lvds_clk,
-					mfd->fbi->var.pixclock);
-	ret = clk_set_rate(lvds_clk, mfd->fbi->var.pixclock);
-	if (ret) {
-		pr_err("%s: Can't set lvds clock to rate %u\n",
-			__func__, mfd->fbi->var.pixclock);
-		goto out;
+	if (lvds_clk) {
+		mfd->fbi->var.pixclock = clk_round_rate(lvds_clk,
+			mfd->fbi->var.pixclock);
+		ret = clk_set_rate(lvds_clk, mfd->fbi->var.pixclock);
+		if (ret) {
+			pr_err("%s: Can't set lvds clock to rate %u\n",
+				__func__, mfd->fbi->var.pixclock);
+			goto out;
+		}
+		clk_enable(lvds_clk);
 	}
 
-	clk_enable(lvds_clk);
-
 	if (lvds_pdata && lvds_pdata->lcdc_power_save)
 		lvds_pdata->lcdc_power_save(1);
 	if (lvds_pdata && lvds_pdata->lcdc_gpio_config)
 		ret = lvds_pdata->lcdc_gpio_config(1);
 
+	lvds_init(mfd);
 	ret = panel_next_on(pdev);
 
 out:
@@ -182,8 +305,11 @@
 		mfd->fb_imgType = MDP_RGB_565;
 
 	fbi = mfd->fbi;
-	fbi->var.pixclock = clk_round_rate(lvds_clk,
-					mfd->panel_info.clk_rate);
+	if (lvds_clk) {
+		fbi->var.pixclock = clk_round_rate(lvds_clk,
+			mfd->panel_info.clk_rate);
+	}
+
 	fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch;
 	fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch;
 	fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch;
@@ -224,9 +350,9 @@
 static int __init lvds_driver_init(void)
 {
 	lvds_clk = clk_get(NULL, "lvds_clk");
-	if (IS_ERR(lvds_clk)) {
+	if (IS_ERR_OR_NULL(lvds_clk)) {
 		pr_err("Couldnt find lvds_clk\n");
-		return -EINVAL;
+		lvds_clk = NULL;
 	}
 
 	return lvds_register_driver();
diff --git a/drivers/video/msm/lvds_chimei_wxga.c b/drivers/video/msm/lvds_chimei_wxga.c
index 2c6b6d4..9a385b9 100644
--- a/drivers/video/msm/lvds_chimei_wxga.c
+++ b/drivers/video/msm/lvds_chimei_wxga.c
@@ -11,9 +11,19 @@
  */
 
 #include "msm_fb.h"
+#include <linux/pwm.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
 
-static struct msm_panel_common_pdata *cm_pdata;
+#define LVDS_CHIMEI_PWM_FREQ_HZ 300
+#define LVDS_CHIMEI_PWM_PERIOD_USEC (USEC_PER_SEC / LVDS_CHIMEI_PWM_FREQ_HZ)
+#define LVDS_CHIMEI_PWM_LEVEL 255
+#define LVDS_CHIMEI_PWM_DUTY_LEVEL \
+	(LVDS_CHIMEI_PWM_PERIOD_USEC / LVDS_CHIMEI_PWM_LEVEL)
+
+
+static struct lvds_panel_platform_data *cm_pdata;
 static struct platform_device *cm_fbpdev;
+static struct pwm_device *bl_lpm;
 
 static int lvds_chimei_panel_on(struct platform_device *pdev)
 {
@@ -27,6 +37,26 @@
 
 static void lvds_chimei_set_backlight(struct msm_fb_data_type *mfd)
 {
+	int ret;
+
+	pr_debug("%s: back light level %d\n", __func__, mfd->bl_level);
+
+	if (bl_lpm) {
+		ret = pwm_config(bl_lpm, LVDS_CHIMEI_PWM_DUTY_LEVEL *
+			mfd->bl_level, LVDS_CHIMEI_PWM_PERIOD_USEC);
+		if (ret) {
+			pr_err("pwm_config on lpm failed %d\n", ret);
+			return;
+		}
+		if (mfd->bl_level) {
+			ret = pwm_enable(bl_lpm);
+			if (ret)
+				pr_err("pwm enable/disable on lpm failed"
+					"for bl %d\n",	mfd->bl_level);
+		} else {
+			pwm_disable(bl_lpm);
+		}
+	}
 }
 
 static int __devinit lvds_chimei_probe(struct platform_device *pdev)
@@ -40,6 +70,17 @@
 		return 0;
 	}
 
+	if (cm_pdata != NULL)
+		bl_lpm = pwm_request(cm_pdata->gpio[0],
+			"backlight");
+
+	if (bl_lpm == NULL || IS_ERR(bl_lpm)) {
+		pr_err("%s pwm_request() failed\n", __func__);
+		bl_lpm = NULL;
+	}
+	pr_debug("bl_lpm = %p lpm = %d\n", bl_lpm,
+		cm_pdata->gpio[0]);
+
 	cm_fbpdev = msm_fb_add_device(pdev);
 	if (!cm_fbpdev) {
 		dev_err(&pdev->dev, "failed to add msm_fb device\n");
@@ -85,8 +126,8 @@
 		return ret;
 
 	pinfo = &lvds_chimei_panel_data.panel_info;
-	pinfo->xres = 320;
-	pinfo->yres = 240;
+	pinfo->xres = 1366;
+	pinfo->yres = 768;
 	MSM_FB_SINGLE_MODE_PANEL(pinfo);
 	pinfo->type = LVDS_PANEL;
 	pinfo->pdest = DISPLAY_1;
@@ -94,7 +135,7 @@
 	pinfo->bpp = 24;
 	pinfo->fb_num = 2;
 	pinfo->clk_rate = 75000000;
-	pinfo->bl_max = 15;
+	pinfo->bl_max = 255;
 	pinfo->bl_min = 1;
 
 	/*
@@ -107,12 +148,14 @@
 	pinfo->lcdc.v_back_porch = 0;
 	pinfo->lcdc.v_front_porch = 38;
 	pinfo->lcdc.v_pulse_width = 20;
-	pinfo->lcdc.border_clr = 0xffff00;
 	pinfo->lcdc.underflow_clr = 0xff;
 	pinfo->lcdc.hsync_skew = 0;
 	pinfo->lvds.channel_mode = LVDS_SINGLE_CHANNEL_MODE;
-	pinfo->lcdc.xres_pad = 1046;
-	pinfo->lcdc.yres_pad = 528;
+
+	/* Set border color, padding only for reducing active display region */
+	pinfo->lcdc.border_clr = 0x0;
+	pinfo->lcdc.xres_pad = 0;
+	pinfo->lcdc.yres_pad = 0;
 
 	ret = platform_device_register(&this_device);
 	if (ret)
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 512480c..43520e0 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -468,11 +468,16 @@
 int mdp_ppp_pipe_wait(void)
 {
 	int ret = 1;
+	boolean wait;
+	unsigned long flag;
 
 	/* wait 5 seconds for the operation to complete before declaring
 	the MDP hung */
+	spin_lock_irqsave(&mdp_spin_lock, flag);
+	wait = mdp_ppp_waiting;
+	spin_unlock_irqrestore(&mdp_spin_lock, flag);
 
-	if (mdp_ppp_waiting == TRUE) {
+	if (wait == TRUE) {
 		ret = wait_for_completion_interruptible_timeout(&mdp_ppp_comp,
 								5 * HZ);
 
@@ -548,6 +553,7 @@
 
 void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd)
 {
+	unsigned long flag;
 	/* complete all the writes before starting */
 	wmb();
 
@@ -561,7 +567,9 @@
 
 		mdp_enable_irq(term);
 		INIT_COMPLETION(mdp_ppp_comp);
+		spin_lock_irqsave(&mdp_spin_lock, flag);
 		mdp_ppp_waiting = TRUE;
+		spin_unlock_irqrestore(&mdp_spin_lock, flag);
 		outpdw(MDP_BASE + 0x30, 0x1000);
 		wait_for_completion_killable(&mdp_ppp_comp);
 		mdp_disable_irq(term);
@@ -812,128 +820,137 @@
 {
 	uint32 mdp_interrupt = 0;
 	struct mdp_dma_data *dma;
+	unsigned long flag;
 
+	/* Ensure all the register write are complete */
+	mb();
 	mdp_is_in_isr = TRUE;
-	do {
-		mdp_interrupt = inp32(MDP_INTR_STATUS);
-		outp32(MDP_INTR_CLEAR, mdp_interrupt);
 
-		mdp_interrupt &= mdp_intr_mask;
+	mdp_interrupt = inp32(MDP_INTR_STATUS);
+	outp32(MDP_INTR_CLEAR, mdp_interrupt);
 
-		if (mdp_interrupt & TV_ENC_UNDERRUN) {
-			mdp_interrupt &= ~(TV_ENC_UNDERRUN);
-			mdp_tv_underflow_cnt++;
-		}
+	mdp_interrupt &= mdp_intr_mask;
 
-		if (!mdp_interrupt)
-			break;
+	if (mdp_interrupt & TV_ENC_UNDERRUN) {
+		mdp_interrupt &= ~(TV_ENC_UNDERRUN);
+		mdp_tv_underflow_cnt++;
+	}
 
-		/* DMA3 TV-Out Start */
-		if (mdp_interrupt & TV_OUT_DMA3_START) {
-			/* let's disable TV out interrupt */
-			mdp_intr_mask &= ~TV_OUT_DMA3_START;
-			outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+	if (!mdp_interrupt)
+		goto out;
 
-			dma = &dma3_data;
-			if (dma->waiting) {
-				dma->waiting = FALSE;
-				complete(&dma->comp);
-			}
-		}
-#ifndef CONFIG_FB_MSM_MDP22
-		if (mdp_interrupt & MDP_HIST_DONE) {
-			outp32(MDP_BASE + 0x94018, 0x3);
-			outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
-			complete(&mdp_hist_comp);
-		}
+	/* DMA3 TV-Out Start */
+	if (mdp_interrupt & TV_OUT_DMA3_START) {
+		/* let's disable TV out interrupt */
+		mdp_intr_mask &= ~TV_OUT_DMA3_START;
+		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
 
-		/* LCDC UnderFlow */
-		if (mdp_interrupt & LCDC_UNDERFLOW) {
-			mdp_lcdc_underflow_cnt++;
-			/*when underflow happens HW resets all the histogram
-			 registers that were set before so restore them back
-			 to normal.*/
-			MDP_OUTP(MDP_BASE + 0x94010, 1);
-			MDP_OUTP(MDP_BASE + 0x9401c, 2);
-			if (mdp_is_hist_start == TRUE) {
-				MDP_OUTP(MDP_BASE + 0x94004,
-						 mdp_hist_frame_cnt);
-				MDP_OUTP(MDP_BASE + 0x94000, 1);
-			}
-		}
-		/* LCDC Frame Start */
-		if (mdp_interrupt & LCDC_FRAME_START) {
-			/* let's disable LCDC interrupt */
-			mdp_intr_mask &= ~LCDC_FRAME_START;
-			outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-
-			dma = &dma2_data;
-			if (dma->waiting) {
-				dma->waiting = FALSE;
-				complete(&dma->comp);
-			}
-		}
-
-		/* DMA2 LCD-Out Complete */
-		if (mdp_interrupt & MDP_DMA_S_DONE) {
-			dma = &dma_s_data;
-			dma->busy = FALSE;
-			mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF,
-				      TRUE);
+		dma = &dma3_data;
+		if (dma->waiting) {
+			dma->waiting = FALSE;
 			complete(&dma->comp);
 		}
-		/* DMA_E LCD-Out Complete */
-		if (mdp_interrupt & MDP_DMA_E_DONE) {
-			dma = &dma_s_data;
+	}
+#ifndef CONFIG_FB_MSM_MDP22
+	if (mdp_interrupt & MDP_HIST_DONE) {
+		outp32(MDP_BASE + 0x94018, 0x3);
+		outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
+		complete(&mdp_hist_comp);
+	}
+
+	/* LCDC UnderFlow */
+	if (mdp_interrupt & LCDC_UNDERFLOW) {
+		mdp_lcdc_underflow_cnt++;
+		/*when underflow happens HW resets all the histogram
+		 registers that were set before so restore them back
+		 to normal.*/
+		MDP_OUTP(MDP_BASE + 0x94010, 1);
+		MDP_OUTP(MDP_BASE + 0x9401c, 2);
+		if (mdp_is_hist_start == TRUE) {
+			MDP_OUTP(MDP_BASE + 0x94004,
+					 mdp_hist_frame_cnt);
+			MDP_OUTP(MDP_BASE + 0x94000, 1);
+		}
+	}
+
+	/* LCDC Frame Start */
+	if (mdp_interrupt & LCDC_FRAME_START) {
+		/* let's disable LCDC interrupt */
+		mdp_intr_mask &= ~LCDC_FRAME_START;
+		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+
+		dma = &dma2_data;
+		if (dma->waiting) {
+			dma->waiting = FALSE;
+			complete(&dma->comp);
+		}
+	}
+
+	/* DMA2 LCD-Out Complete */
+	if (mdp_interrupt & MDP_DMA_S_DONE) {
+		dma = &dma_s_data;
+		dma->busy = FALSE;
+		mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+			complete(&dma->comp);
+	}
+
+	/* DMA_E LCD-Out Complete */
+	if (mdp_interrupt & MDP_DMA_E_DONE) {
+		dma = &dma_s_data;
+		dma->busy = FALSE;
+		mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+		complete(&dma->comp);
+	}
+
+#endif
+
+	/* DMA2 LCD-Out Complete */
+	if (mdp_interrupt & MDP_DMA_P_DONE) {
+		struct timeval now;
+
+		mdp_dma2_last_update_time = ktime_sub(ktime_get_real(),
+			mdp_dma2_last_update_time);
+		if (mdp_debug[MDP_DMA2_BLOCK]) {
+			jiffies_to_timeval(jiffies, &now);
+			mdp_dma2_timeval.tv_usec =
+			    now.tv_usec - mdp_dma2_timeval.tv_usec;
+		}
+#ifndef CONFIG_FB_MSM_MDP303
+		dma = &dma2_data;
+		spin_lock_irqsave(&mdp_spin_lock, flag);
+		dma->busy = FALSE;
+		spin_unlock_irqrestore(&mdp_spin_lock, flag);
+		mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+		complete(&dma->comp);
+#else
+		if (mdp_prim_panel_type == MIPI_CMD_PANEL) {
+			dma = &dma2_data;
+			spin_lock_irqsave(&mdp_spin_lock, flag);
 			dma->busy = FALSE;
-			mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_OFF,
+			spin_unlock_irqrestore(&mdp_spin_lock, flag);
+			mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF,
 				TRUE);
 			complete(&dma->comp);
 		}
-
 #endif
+	}
 
-		/* DMA2 LCD-Out Complete */
-		if (mdp_interrupt & MDP_DMA_P_DONE) {
-			struct timeval now;
-
-			mdp_dma2_last_update_time = ktime_sub(ktime_get_real(),
-				mdp_dma2_last_update_time);
-			if (mdp_debug[MDP_DMA2_BLOCK]) {
-				jiffies_to_timeval(jiffies, &now);
-				mdp_dma2_timeval.tv_usec =
-				    now.tv_usec - mdp_dma2_timeval.tv_usec;
-			}
-#ifndef CONFIG_FB_MSM_MDP303
-			dma = &dma2_data;
-			dma->busy = FALSE;
-			mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF,
-				      TRUE);
-			complete(&dma->comp);
-#else
-			if (mdp_prim_panel_type == MIPI_CMD_PANEL) {
-				dma = &dma2_data;
-				dma->busy = FALSE;
-				mdp_pipe_ctrl(MDP_DMA2_BLOCK,
-					MDP_BLOCK_POWER_OFF, TRUE);
-				complete(&dma->comp);
-			}
-#endif
-		}
-		/* PPP Complete */
-		if (mdp_interrupt & MDP_PPP_DONE) {
+	/* PPP Complete */
+	if (mdp_interrupt & MDP_PPP_DONE) {
 #ifdef	CONFIG_FB_MSM_MDP31
-			MDP_OUTP(MDP_BASE + 0x00100, 0xFFFF);
+		MDP_OUTP(MDP_BASE + 0x00100, 0xFFFF);
 #endif
-			mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
-			if (mdp_ppp_waiting) {
-				mdp_ppp_waiting = FALSE;
-				complete(&mdp_ppp_comp);
-			}
+		mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+		spin_lock_irqsave(&mdp_spin_lock, flag);
+		if (mdp_ppp_waiting) {
+			mdp_ppp_waiting = FALSE;
+			complete(&mdp_ppp_comp);
 		}
-	} while (1);
+		spin_unlock_irqrestore(&mdp_spin_lock, flag);
+	}
 
-	mdp_is_in_isr = FALSE;
+out:
+mdp_is_in_isr = FALSE;
 
 	return IRQ_HANDLED;
 }
@@ -1083,12 +1100,12 @@
 static int mdp_off(struct platform_device *pdev)
 {
 	int ret = 0;
+
 	mdp_histogram_ctrl(FALSE);
 
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	ret = panel_next_off(pdev);
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
 	return ret;
 }
 
@@ -1098,9 +1115,12 @@
 
 #ifdef CONFIG_FB_MSM_MDP40
 	struct msm_fb_data_type *mfd;
+	mdp4_overlay_ctrl_db_reset();
+
+	mfd = platform_get_drvdata(pdev);
+
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	if (is_mdp4_hw_reset()) {
-		mfd = platform_get_drvdata(pdev);
 		mdp_vsync_cfg_regs(mfd, FALSE);
 		mdp4_hw_init();
 		outpdw(MDP_BASE + 0x0038, mdp4_display_intf);
@@ -1112,6 +1132,14 @@
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	ret = panel_next_on(pdev);
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+#ifdef CONFIG_FB_MSM_MDP40
+	if (mfd->panel.type == MIPI_CMD_PANEL)
+		mdp4_dsi_cmd_overlay_restore();
+	else if (mfd->panel.type == MDDI_PANEL)
+		mdp4_mddi_overlay_restore();
+#endif
+
 	return ret;
 }
 
@@ -1193,7 +1221,7 @@
 		return -EINVAL;
 	}
 	if (mdp_bus_scale_handle < 1) {
-		printk(KERN_ERR "%s invalid bus handle\n", __func__);
+		pr_debug("%s invalid bus handle\n", __func__);
 		return -EINVAL;
 	}
 	return msm_bus_scale_client_update_request(mdp_bus_scale_handle,
@@ -1290,7 +1318,7 @@
 	if (IS_ERR(mdp_pclk))
 		mdp_pclk = NULL;
 
-	if (mdp_rev == MDP_REV_42) {
+	if (mdp_rev >= MDP_REV_42) {
 		mdp_lut_clk = clk_get(NULL, "lut_mdp");
 		if (IS_ERR(mdp_lut_clk)) {
 			ret = PTR_ERR(mdp_lut_clk);
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 3862823..155bc54 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -26,6 +26,7 @@
 extern spinlock_t mdp_spin_lock;
 extern struct mdp4_statistic mdp4_stat;
 extern uint32 mdp4_extn_disp;
+extern char *mmss_cc_base;	/* mutimedia sub system clock control */
 
 #define MDP4_OVERLAYPROC0_BASE	0x10000
 #define MDP4_OVERLAYPROC1_BASE	0x18000
@@ -417,6 +418,7 @@
 			struct mdp4_overlay_pipe *pipe);
 int mdp4_overlay_dtv_unset(struct msm_fb_data_type *mfd,
 			struct mdp4_overlay_pipe *pipe);
+void mdp4_dma_e_done_dtv(void);
 #else
 static inline void  mdp4_overlay_dtv_ov_done_push(struct msm_fb_data_type *mfd,
 			struct mdp4_overlay_pipe *pipe)
@@ -438,6 +440,10 @@
 {
 	return 0;
 }
+static inline void mdp4_dma_e_done_dtv(void)
+{
+	return;
+}
 #endif
 
 #ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
@@ -513,7 +519,6 @@
 void mdp4_overlay1_done_atv(void);
 void mdp4_primary_vsync_lcdc(void);
 void mdp4_external_vsync_dtv(void);
-void mdp4_mddi_overlay_restore(void);
 void mdp4_overlay_lcdc_wait4vsync(struct msm_fb_data_type *mfd);
 void mdp4_overlay_lcdc_vsync_push(struct msm_fb_data_type *mfd,
 				struct mdp4_overlay_pipe *pipe);
@@ -523,11 +528,16 @@
 
 #ifndef CONFIG_FB_MSM_MIPI_DSI
 void mdp4_mddi_dma_busy_wait(struct msm_fb_data_type *mfd);
+void mdp4_mddi_overlay_restore(void);
 #else
 static inline void mdp4_mddi_dma_busy_wait(struct msm_fb_data_type *mfd)
 {
 	/* empty */
 }
+static inline void mdp4_mddi_overlay_restore(void)
+{
+	/* empty */
+}
 #endif
 
 void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
@@ -629,6 +639,7 @@
 void mdp4_dsi_blt_dmap_busy_wait(struct msm_fb_data_type *mfd);
 void mdp4_overlay_dsi_video_vsync_push(struct msm_fb_data_type *mfd,
 				struct mdp4_overlay_pipe *pipe);
+void mdp4_dsi_cmd_overlay_restore(void);
 #else
 static inline void mdp4_dsi_cmd_dma_busy_wait(struct msm_fb_data_type *mfd)
 {
@@ -643,6 +654,10 @@
 {
 	/* empty */
 }
+static inline void mdp4_dsi_cmd_overlay_restore(void)
+{
+	/* empty */
+}
 #endif /* MIPI_DSI */
 
 void mdp4_dsi_cmd_kickoff_ui(struct msm_fb_data_type *mfd,
@@ -651,7 +666,6 @@
 				struct mdp4_overlay_pipe *pipe);
 void mdp4_dsi_cmd_overlay_kickoff(struct msm_fb_data_type *mfd,
 				struct mdp4_overlay_pipe *pipe);
-void mdp4_dsi_cmd_overlay_restore(void);
 
 void mdp4_overlay_panel_3d(int mixer_num, uint32 panel_3d);
 int mdp4_overlay_3d_sbys(struct fb_info *info, struct msmfb_overlay_3d *req);
@@ -674,6 +688,7 @@
 uint32_t mdp4_ss_table_value(int8_t param, int8_t index);
 void mdp4_overlay_status_write(enum mdp4_overlay_status type, bool val);
 bool mdp4_overlay_status_read(enum mdp4_overlay_status type);
+void mdp4_overlay_ctrl_db_reset(void);
 
 int mdp4_overlay_writeback_on(struct platform_device *pdev);
 int mdp4_overlay_writeback_off(struct platform_device *pdev);
@@ -682,7 +697,6 @@
 		struct mdp4_overlay_pipe *pipe);
 void mdp4_writeback_dma_busy_wait(struct msm_fb_data_type *mfd);
 void mdp4_overlay1_done_writeback(struct mdp_dma_data *dma);
-void mdp4_dma_e_done_dtv(void);
 
 int mdp4_writeback_start(struct fb_info *info);
 int mdp4_writeback_stop(struct fb_info *info);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 8b61024..bf53c73 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -110,6 +110,14 @@
 	return overlay_status[type];
 }
 
+void mdp4_overlay_ctrl_db_reset(void)
+{
+	int i;
+
+	for (i = MDP4_MIXER0; i < MDP4_MIXER_MAX; i++)
+		ctrl->mixer_cfg[i] = 0;
+}
+
 int mdp4_overlay_mixer_play(int mixer_num)
 {
 	if (mixer_num == MDP4_MIXER2)
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 52a402c..3f12827 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -110,6 +110,8 @@
 	if (mfd->key != MFD_KEY)
 		return -EINVAL;
 
+	mdp4_overlay_ctrl_db_reset();
+
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 848e6b9..3dece1f 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -45,73 +45,6 @@
 static struct mdp4_overlay_pipe *lcdc_pipe;
 static struct completion lcdc_comp;
 
-static void lvds_init(struct msm_fb_data_type *mfd)
-{
-	unsigned int lvds_intf, lvds_phy_cfg0;
-
-	if (mfd->panel_info.bpp == 24) {
-		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
-		MDP_OUTP(MDP_BASE +  0xc2014, 0x03040508);
-		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
-		MDP_OUTP(MDP_BASE +  0xc2018, 0x00000102);
-		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
-		MDP_OUTP(MDP_BASE +  0xc201c, 0x0c0d1011);
-		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
-		MDP_OUTP(MDP_BASE +  0xc2020, 0x00090a0b);
-		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
-		MDP_OUTP(MDP_BASE +  0xc2024, 0x1518191a);
-		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
-		MDP_OUTP(MDP_BASE +  0xc2028, 0x00121314);
-		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_3_TO_0 */
-		MDP_OUTP(MDP_BASE +  0xc202c, 0x0f16171b);
-		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_6_TO_4 */
-		MDP_OUTP(MDP_BASE +  0xc2030, 0x0006070e);
-
-		if (mfd->panel_info.lvds.channel_mode ==
-			LVDS_DUAL_CHANNEL_MODE) {
-			lvds_intf = 0x0001ff80;
-			lvds_phy_cfg0 = BIT(6) | BIT(7);
-			if (mfd->panel_info.lvds.channel_swap)
-				lvds_intf |= BIT(4);
-		} else {
-			lvds_intf = 0x00010f84;
-			lvds_phy_cfg0 = BIT(6);
-		}
-	} else if (mfd->panel_info.bpp == 18) {
-		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
-		MDP_OUTP(MDP_BASE +  0xc2014, 0x03040508);
-		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
-		MDP_OUTP(MDP_BASE +  0xc2018, 0x00000102);
-		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
-		MDP_OUTP(MDP_BASE +  0xc201c, 0x0c0d1011);
-		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
-		MDP_OUTP(MDP_BASE +  0xc2020, 0x00090a0b);
-		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
-		MDP_OUTP(MDP_BASE +  0xc2024, 0x1518191a);
-		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
-		MDP_OUTP(MDP_BASE +  0xc2028, 0x00121314);
-
-		if (mfd->panel_info.lvds.channel_mode ==
-			LVDS_DUAL_CHANNEL_MODE) {
-			lvds_intf = 0x00017788;
-			lvds_phy_cfg0 = BIT(6) | BIT(7);
-			if (mfd->panel_info.lvds.channel_swap)
-				lvds_intf |= BIT(4);
-		} else {
-			lvds_intf = 0x0001078c;
-			lvds_phy_cfg0 = BIT(6);
-		}
-	}
-
-	/* MDP_LVDSPHY_CFG0 */
-	MDP_OUTP(MDP_BASE +  0xc3100, lvds_phy_cfg0);
-	/* MDP_LCDC_LVDS_INTF_CTL */
-	MDP_OUTP(MDP_BASE +  0xc2000, lvds_intf);
-	lvds_phy_cfg0 |= BIT(4);
-	/* MDP_LVDSPHY_CFG0, enable serialization */
-	MDP_OUTP(MDP_BASE +  0xc3100, lvds_phy_cfg0);
-}
-
 int mdp_lcdc_on(struct platform_device *pdev)
 {
 	int lcdc_width;
@@ -160,6 +93,8 @@
 	if (mfd->key != MFD_KEY)
 		return -EINVAL;
 
+	mdp4_overlay_ctrl_db_reset();
+
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
@@ -303,9 +238,6 @@
 #endif
 	mdp_histogram_ctrl(TRUE);
 
-	if (mfd->panel.type == LVDS_PANEL)
-		lvds_init(mfd);
-
 	ret = panel_next_on(pdev);
 	if (ret == 0) {
 		/* enable LCDC block */
diff --git a/drivers/video/msm/mdp_dma.c b/drivers/video/msm/mdp_dma.c
index f9f7954..3997814 100644
--- a/drivers/video/msm/mdp_dma.c
+++ b/drivers/video/msm/mdp_dma.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -478,16 +478,20 @@
 void mdp_dma2_update(struct msm_fb_data_type *mfd)
 #endif
 {
+	unsigned long flag;
+
 	down(&mfd->dma->mutex);
 	if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
 		down(&mfd->sem);
 		mfd->ibuf_flushed = TRUE;
 		mdp_dma2_update_lcd(mfd);
 
+		spin_lock_irqsave(&mdp_spin_lock, flag);
 		mdp_enable_irq(MDP_DMA2_TERM);
 		mfd->dma->busy = TRUE;
 		INIT_COMPLETION(mfd->dma->comp);
 
+		spin_unlock_irqrestore(&mdp_spin_lock, flag);
 		/* schedule DMA to start */
 		mdp_dma_schedule(mfd, MDP_DMA2_TERM);
 		up(&mfd->sem);
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 19dfe82..199e472 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/msm/mdp_ppp.c
@@ -1,7 +1,7 @@
 /* drivers/video/msm/src/drv/mdp/mdp_ppp.c
  *
  * Copyright (C) 2007 Google Incorporated
- * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -52,6 +52,7 @@
 	[MDP_RGBX_8888] = 4,
 	[MDP_Y_CBCR_H2V1] = 1,
 	[MDP_Y_CBCR_H2V2] = 1,
+	[MDP_Y_CBCR_H2V2_ADRENO] = 1,
 	[MDP_Y_CRCB_H2V1] = 1,
 	[MDP_Y_CRCB_H2V2] = 1,
 	[MDP_YCRYCB_H2V1] = 2,
@@ -535,14 +536,16 @@
 
 #define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \
 				(img == MDP_Y_CBCR_H2V2) | \
+				(img == MDP_Y_CBCR_H2V2_ADRENO) | \
 				(img == MDP_Y_CRCB_H2V1) | \
 				(img == MDP_Y_CBCR_H2V1))
 
 #define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
 
 #define Y_TO_CRCB_RATIO(format) \
-	((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ?  2 :\
-	(format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ?  1 : 1)
+	((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CBCR_H2V2_ADRENO || \
+	  format == MDP_Y_CRCB_H2V2) ?  2 : (format == MDP_Y_CBCR_H2V1 || \
+	  format == MDP_Y_CRCB_H2V1) ?  1 : 1)
 
 #ifdef CONFIG_ANDROID_PMEM
 static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
@@ -589,6 +592,7 @@
 	uint32 src_width;
 	uint32 src_height;
 	uint32 src0_ystride;
+	uint32 src0_y1stride;
 	uint32 dst_roi_width;
 	uint32 dst_roi_height;
 	uint32 ppp_src_cfg_reg, ppp_operation_reg, ppp_dst_cfg_reg;
@@ -868,6 +872,7 @@
 		break;
 
 	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CBCR_H2V2_ADRENO:
 	case MDP_Y_CRCB_H2V2:
 		inpBpp = 1;
 		src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
@@ -1059,7 +1064,16 @@
 		}
 	}
 
-	src0_ystride = src_width * inpBpp;
+	if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO)
+		src0_ystride = ALIGN(src_width, 32) * inpBpp;
+	else
+		src0_ystride = src_width * inpBpp;
+
+	if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO)
+		src0_y1stride = 2 * ALIGN(src_width/2, 32);
+	else
+		src0_y1stride = src0_ystride;
+
 	dest0_ystride = iBuf->ibuf_width * iBuf->bpp;
 
 	/* no need to care about rotation since it's the real-XY. */
@@ -1121,7 +1135,7 @@
 	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x010c, src0); /* comp.plane 0 */
 	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0110, src1); /* comp.plane 1 */
 	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x011c,
-		 (src0_ystride << 16 | src0_ystride));
+		 (src0_y1stride << 16 | src0_ystride));
 
 	/* setup for rgb 565 */
 	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0124, ppp_src_cfg_reg);
@@ -1362,9 +1376,16 @@
 	iBuf.mdpImg.imgType = req->src.format;
 
 	iBuf.mdpImg.bmy_addr = (uint32 *) (src_start + req->src.offset);
-	iBuf.mdpImg.cbcr_addr =
-	    (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
-			req->src.width * req->src.height);
+
+	if (iBuf.mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO)
+		iBuf.mdpImg.cbcr_addr =
+			(uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
+				ALIGN((ALIGN(req->src.width, 32) *
+				ALIGN(req->src.height, 32)), 4096));
+	else
+		iBuf.mdpImg.cbcr_addr =
+			(uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
+				req->src.width * req->src.height);
 
 	iBuf.mdpImg.mdpOp = MDPOP_NOP;
 
diff --git a/drivers/video/msm/mdp_ppp_v20.c b/drivers/video/msm/mdp_ppp_v20.c
index 8828a8f..e2a6564 100644
--- a/drivers/video/msm/mdp_ppp_v20.c
+++ b/drivers/video/msm/mdp_ppp_v20.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1625,6 +1625,7 @@
 		 * offsite in vertical axis
 		 */
 	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CBCR_H2V2_ADRENO:
 	case MDP_Y_CRCB_H2V2:
 		/* floor( luma_interp_point_left / 2) */
 		chroma_interp_point_left = luma_interp_point_left >> 1;
@@ -1678,6 +1679,7 @@
 			break;
 
 		case MDP_Y_CBCR_H2V2:
+		case MDP_Y_CBCR_H2V2_ADRENO:
 		case MDP_Y_CRCB_H2V2:
 			/*
 			 * cosite in horizontal dir, and offsite in vertical dir
diff --git a/drivers/video/msm/mipi_NT35510.c b/drivers/video/msm/mipi_NT35510.c
new file mode 100644
index 0000000..930b4e9
--- /dev/null
+++ b/drivers/video/msm/mipi_NT35510.c
@@ -0,0 +1,586 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_NT35510.h"
+
+static struct msm_panel_common_pdata *mipi_nt35510_pdata;
+static struct dsi_buf nt35510_tx_buf;
+static struct dsi_buf nt35510_rx_buf;
+
+#define NT35510_SLEEP_OFF_DELAY 150
+#define NT35510_DISPLAY_ON_DELAY 150
+
+/* common setting */
+static char exit_sleep[2] = {0x11, 0x00};
+static char display_on[2] = {0x29, 0x00};
+static char display_off[2] = {0x28, 0x00};
+static char enter_sleep[2] = {0x10, 0x00};
+static char write_ram[2] = {0x2c, 0x00}; /* write ram */
+
+static struct dsi_cmd_desc nt35510_display_off_cmds[] = {
+	{DTYPE_DCS_WRITE, 1, 0, 0, 150, sizeof(display_off), display_off},
+	{DTYPE_DCS_WRITE, 1, 0, 0, 150, sizeof(enter_sleep), enter_sleep}
+};
+
+static char cmd0[6] = {
+	0xF0, 0x55, 0xAA, 0x52,
+	0x08, 0x01,
+};
+static char cmd1[4] = {
+	0xBC, 0x00, 0xA0, 0x00,
+};
+static char cmd2[4] = {
+	0xBD, 0x00, 0xA0, 0x00,
+};
+static char cmd3[3] = {
+	0xBE, 0x00, 0x79,
+};
+static char cmd4[53] = {
+	0xD1, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char cmd5[53] = {
+	0xD2, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char cmd6[53] = {
+	0xD3, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char cmd7[53] = {
+	0xD4, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char cmd8[53] = {
+	0xD5, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char cmd9[53] = {
+	0xD6, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char cmd10[4] = {
+	0xB0, 0x0A, 0x0A, 0x0A,
+};
+static char cmd11[4] = {
+	0xB1, 0x0A, 0x0A, 0x0A,
+};
+static char cmd12[4] = {
+	0xBA, 0x24, 0x24, 0x24,
+};
+static char cmd13[4] = {
+	0xB9, 0x24, 0x24, 0x24,
+};
+static char cmd14[4] = {
+	0xB8, 0x24, 0x24, 0x24,
+};
+static char cmd15[6] = {
+	0xF0, 0x55, 0xAA, 0x52,
+	0x08, 0x00,
+};
+static char cmd16[2] = {
+	0xB3, 0x00,
+};
+static char cmd17[2] = {
+	0xB4, 0x10,
+};
+static char cmd18[2] = {
+	0xB6, 0x02,
+};
+static char cmd19[3] = {
+	0xB1, 0xEC, 0x00,
+};
+static char cmd20[4] = {
+	0xBC, 0x05, 0x05, 0x05,
+};
+static char cmd21[3] = {
+	0xB7, 0x20, 0x20,
+};
+static char cmd22[5] = {
+	0xB8, 0x01, 0x03, 0x03,
+	0x03,
+};
+static char cmd23[19] = {
+	0xC8, 0x01, 0x00, 0x78,
+	0x50, 0x78, 0x50, 0x78,
+	0x50, 0x78, 0x50, 0xC8,
+	0x3C, 0x3C, 0xC8, 0xC8,
+	0x3C, 0x3C, 0xC8,
+};
+static char cmd24[6] = {
+	0xBD, 0x01, 0x84, 0x07,
+	0x31, 0x00,
+};
+static char cmd25[6] = {
+	0xBE, 0x01, 0x84, 0x07,
+	0x31, 0x00,
+};
+static char cmd26[6] = {
+	0xBF, 0x01, 0x84, 0x07,
+	0x31, 0x00,
+};
+static char cmd27[2] = {
+	0x35, 0x00,
+};
+static char config_MADCTL[2] = {0x36, 0x00};
+static struct dsi_cmd_desc nt35510_cmd_display_on_cmds[] = {
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd0), cmd0},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd1), cmd1},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd2), cmd2},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd3), cmd3},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd4), cmd4},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd5), cmd5},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd6), cmd6},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd7), cmd7},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd8), cmd8},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd9), cmd9},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd10), cmd10},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd11), cmd11},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd12), cmd12},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd13), cmd13},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd14), cmd14},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd15), cmd15},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd16), cmd16},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd17), cmd17},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd18), cmd18},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd19), cmd19},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd20), cmd20},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd21), cmd21},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd22), cmd22},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd23), cmd23},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd24), cmd24},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd25), cmd25},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd26), cmd26},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd27), cmd27},
+
+	{DTYPE_DCS_WRITE, 1, 0, 0, 150,	sizeof(exit_sleep), exit_sleep},
+	{DTYPE_DCS_WRITE, 1, 0, 0, 10,	sizeof(display_on), display_on},
+
+	{DTYPE_DCS_WRITE1, 1, 0, 0, 150,
+		sizeof(config_MADCTL), config_MADCTL},
+
+	{DTYPE_DCS_WRITE, 1, 0, 0, 10,	sizeof(write_ram), write_ram},
+};
+
+static char video0[6] = {
+	0xF0, 0x55, 0xAA, 0x52,
+	0x08, 0x01,
+};
+static char video1[4] = {
+	0xBC, 0x00, 0xA0, 0x00,
+};
+static char video2[4] = {
+	0xBD, 0x00, 0xA0, 0x00,
+};
+static char video3[3] = {
+	0xBE, 0x00, 0x79,
+};
+static char video4[53] = {
+	0xD1, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char video5[53] = {
+	0xD2, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char video6[53] = {
+	0xD3, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char video7[53] = {
+	0xD4, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char video8[53] = {
+	0xD5, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char video9[53] = {
+	0xD6, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char video10[4] = {
+	0xB0, 0x0A, 0x0A, 0x0A,
+};
+static char video11[4] = {
+	0xB1, 0x0A, 0x0A, 0x0A,
+};
+static char video12[4] = {
+	0xBA, 0x24, 0x24, 0x24,
+};
+static char video13[4] = {
+	0xB9, 0x24, 0x24, 0x24,
+};
+static char video14[4] = {
+	0xB8, 0x24, 0x24, 0x24,
+};
+static char video15[6] = {
+	0xF0, 0x55, 0xAA, 0x52,
+	0x08, 0x00,
+};
+static char video16[2] = {
+	0xB3, 0x00,
+};
+static char video17[2] = {
+	0xB4, 0x10,
+};
+static char video18[2] = {
+	0xB6, 0x02,
+};
+static char video19[3] = {
+	0xB1, 0xFC, 0x06,
+};
+static char video20[4] = {
+	0xBC, 0x05, 0x05, 0x05,
+};
+static char video21[3] = {
+	0xB7, 0x20, 0x20,
+};
+static char video22[5] = {
+	0xB8, 0x01, 0x03, 0x03,
+	0x03,
+};
+static char video23[19] = {
+	0xC8, 0x01, 0x00, 0x78,
+	0x50, 0x78, 0x50, 0x78,
+	0x50, 0x78, 0x50, 0xC8,
+	0x3C, 0x3C, 0xC8, 0xC8,
+	0x3C, 0x3C, 0xC8,
+};
+static char video24[6] = {
+	0xBD, 0x01, 0x84, 0x07,
+	0x31, 0x00,
+};
+static char video25[6] = {
+	0xBE, 0x01, 0x84, 0x07,
+	0x31, 0x00,
+};
+static char video26[6] = {
+	0xBF, 0x01, 0x84, 0x07,
+	0x31, 0x00,
+};
+static char video27[2] = {
+	0x35, 0x00,
+};
+static struct dsi_cmd_desc nt35510_video_display_on_cmds[] = {
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video0), video0},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video1), video1},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video2), video2},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video3), video3},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video4), video4},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video5), video5},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video6), video6},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video7), video7},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video8), video8},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video9), video9},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video10), video10},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video11), video11},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video12), video12},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video13), video13},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video14), video14},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video15), video15},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video16), video16},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video17), video17},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video18), video18},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video19), video19},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video20), video20},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video21), video21},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video22), video22},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video23), video23},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video24), video24},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video25), video25},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video26), video26},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video27), video27},
+	{DTYPE_DCS_WRITE, 1, 0, 0, NT35510_SLEEP_OFF_DELAY, sizeof(exit_sleep),
+			exit_sleep},
+	{DTYPE_DCS_WRITE, 1, 0, 0, NT35510_DISPLAY_ON_DELAY, sizeof(display_on),
+			display_on},
+};
+
+static int mipi_nt35510_lcd_on(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+	struct mipi_panel_info *mipi;
+
+	mfd = platform_get_drvdata(pdev);
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	mipi  = &mfd->panel_info.mipi;
+
+	if (mipi->mode == DSI_VIDEO_MODE) {
+		mipi_dsi_cmds_tx(mfd, &nt35510_tx_buf,
+			nt35510_video_display_on_cmds,
+			ARRAY_SIZE(nt35510_video_display_on_cmds));
+	} else if (mipi->mode == DSI_CMD_MODE) {
+		mipi_dsi_cmds_tx(mfd, &nt35510_tx_buf,
+			nt35510_cmd_display_on_cmds,
+			ARRAY_SIZE(nt35510_cmd_display_on_cmds));
+	}
+
+	return 0;
+}
+
+static int mipi_nt35510_lcd_off(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+
+	pr_debug("mipi_nt35510_lcd_off E\n");
+
+	mfd = platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return -ENODEV;
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	mipi_dsi_cmds_tx(mfd, &nt35510_tx_buf, nt35510_display_off_cmds,
+			ARRAY_SIZE(nt35510_display_off_cmds));
+
+	pr_debug("mipi_nt35510_lcd_off X\n");
+	return 0;
+}
+
+static int __devinit mipi_nt35510_lcd_probe(struct platform_device *pdev)
+{
+	pr_debug("%s\n", __func__);
+
+	if (pdev->id == 0) {
+		mipi_nt35510_pdata = pdev->dev.platform_data;
+		return 0;
+	}
+
+	msm_fb_add_device(pdev);
+
+	return 0;
+}
+
+static struct platform_driver this_driver = {
+	.probe  = mipi_nt35510_lcd_probe,
+	.driver = {
+		.name   = "mipi_NT35510",
+	},
+};
+
+static void mipi_nt35510_set_backlight(struct msm_fb_data_type *mfd)
+{
+	/* Add backlight changes later*/
+	return;
+}
+
+static struct msm_fb_panel_data nt35510_panel_data = {
+	.on	= mipi_nt35510_lcd_on,
+	.off = mipi_nt35510_lcd_off,
+	.set_backlight = mipi_nt35510_set_backlight,
+};
+
+static int ch_used[3];
+
+static int mipi_nt35510_lcd_init(void)
+{
+	mipi_dsi_buf_alloc(&nt35510_tx_buf, DSI_BUF_SIZE);
+	mipi_dsi_buf_alloc(&nt35510_rx_buf, DSI_BUF_SIZE);
+
+	return platform_driver_register(&this_driver);
+}
+int mipi_nt35510_device_register(struct msm_panel_info *pinfo,
+					u32 channel, u32 panel)
+{
+	struct platform_device *pdev = NULL;
+	int ret;
+
+	if ((channel >= 3) || ch_used[channel])
+		return -ENODEV;
+
+	ch_used[channel] = TRUE;
+
+	ret = mipi_nt35510_lcd_init();
+	if (ret) {
+		pr_err("mipi_nt35510_lcd_init() failed with ret %u\n", ret);
+		return ret;
+	}
+
+	pdev = platform_device_alloc("mipi_NT35510", (panel << 8)|channel);
+	if (!pdev)
+		return -ENOMEM;
+
+	nt35510_panel_data.panel_info = *pinfo;
+
+	ret = platform_device_add_data(pdev, &nt35510_panel_data,
+				sizeof(nt35510_panel_data));
+	if (ret) {
+		pr_debug("%s: platform_device_add_data failed!\n", __func__);
+		goto err_device_put;
+	}
+
+	ret = platform_device_add(pdev);
+	if (ret) {
+		pr_debug("%s: platform_device_register failed!\n", __func__);
+		goto err_device_put;
+	}
+
+	return 0;
+
+err_device_put:
+	platform_device_put(pdev);
+	return ret;
+}
diff --git a/drivers/video/msm/mipi_NT35510.h b/drivers/video/msm/mipi_NT35510.h
new file mode 100644
index 0000000..5c81875
--- /dev/null
+++ b/drivers/video/msm/mipi_NT35510.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MIPI_NT35510_H
+#define MIPI_NT35510_H
+
+int mipi_nt35510_device_register(struct msm_panel_info *pinfo,
+					u32 channel, u32 panel);
+
+#endif  /* MIPI_NT35510_H */
diff --git a/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c b/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
new file mode 100644
index 0000000..2c4ee3e
--- /dev/null
+++ b/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
@@ -0,0 +1,98 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_NT35510.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_cmd_mode_phy_db = {
+	/* DSI Bit Clock at 500 MHz, 2 lane, RGB888 */
+	/* regulator */
+	{0x03, 0x01, 0x01, 0x00},
+	/* timing   */
+	{0xb9, 0x8e, 0x1f, 0x00, 0x98, 0x9c, 0x22, 0x90,
+	0x18, 0x03, 0x04},
+	/* phy ctrl */
+	{0x7f, 0x00, 0x00, 0x00},
+	/* strength */
+	{0xbb, 0x02, 0x06, 0x00},
+	/* pll control */
+	{0x01, 0xec, 0x31, 0xd2, 0x00, 0x40, 0x37, 0x62,
+	0x01, 0x0f, 0x07,
+	0x05, 0x14, 0x03, 0x0, 0x0, 0x0, 0x20, 0x0, 0x02, 0x0},
+};
+
+static int mipi_cmd_nt35510_wvga_pt_init(void)
+{
+	int ret;
+
+	if (msm_fb_detect_client("mipi_cmd_nt35510_wvga"))
+		return 0;
+
+	pinfo.xres = 480;
+	pinfo.yres = 800;
+	pinfo.type = MIPI_CMD_PANEL;
+	pinfo.pdest = DISPLAY_1;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 24;
+	pinfo.lcdc.h_back_porch = 100;
+	pinfo.lcdc.h_front_porch = 100;
+	pinfo.lcdc.h_pulse_width = 8;
+	pinfo.lcdc.v_back_porch = 20;
+	pinfo.lcdc.v_front_porch = 20;
+	pinfo.lcdc.v_pulse_width = 1;
+
+	pinfo.lcdc.border_clr = 0;	/* blk */
+	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
+	pinfo.lcdc.hsync_skew = 0;
+	pinfo.bl_max = 100;
+	pinfo.bl_min = 1;
+	pinfo.fb_num = 2;
+
+	pinfo.clk_rate = 499000000;
+
+	pinfo.lcd.vsync_enable = TRUE;
+	pinfo.lcd.hw_vsync_mode = TRUE;
+	pinfo.lcd.refx100 = 6000; /* adjust refx100 to prevent tearing */
+
+	pinfo.mipi.mode = DSI_CMD_MODE;
+	pinfo.mipi.dst_format = DSI_CMD_DST_FORMAT_RGB888;
+	pinfo.mipi.vc = 0;
+	pinfo.mipi.rgb_swap = DSI_RGB_SWAP_RGB;
+	pinfo.mipi.data_lane0 = TRUE;
+	pinfo.mipi.data_lane1 = TRUE;
+	pinfo.mipi.t_clk_post = 0x20;
+	pinfo.mipi.t_clk_pre = 0x2F;
+	pinfo.mipi.stream = 0; /* dma_p */
+	pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_SW;
+	pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+	pinfo.mipi.te_sel = 1; /* TE from vsync gpio */
+	pinfo.mipi.interleave_max = 1;
+	pinfo.mipi.insert_dcs_cmd = TRUE;
+	pinfo.mipi.wr_mem_continue = 0x3c;
+	pinfo.mipi.wr_mem_start = 0x2c;
+	pinfo.mipi.dsi_phy_db = &dsi_cmd_mode_phy_db;
+	pinfo.mipi.tx_eot_append = 0x01;
+	pinfo.mipi.rx_eot_ignore = 0x0;
+	pinfo.mipi.dlane_swap = 0x01;
+
+	ret = mipi_nt35510_device_register(&pinfo, MIPI_DSI_PRIM,
+						MIPI_DSI_PANEL_WVGA_PT);
+	if (ret)
+		pr_err("%s: failed to register device!\n", __func__);
+
+	return ret;
+}
+
+module_init(mipi_cmd_nt35510_wvga_pt_init);
diff --git a/drivers/video/msm/mipi_NT35510_video_wvga_pt.c b/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
new file mode 100644
index 0000000..82e03b2
--- /dev/null
+++ b/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
@@ -0,0 +1,108 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_NT35510.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+	/* DSI Bit Clock at 500 MHz, 2 lane, RGB888 */
+	/* regulator */
+	{0x03, 0x01, 0x01, 0x00},
+	/* timing   */
+	{0xb9, 0x8e, 0x1f, 0x00, 0x98, 0x9c, 0x22, 0x90,
+	0x18, 0x03, 0x04},
+	/* phy ctrl */
+	{0x7f, 0x00, 0x00, 0x00},
+	/* strength */
+	{0xbb, 0x02, 0x06, 0x00},
+	/* pll control */
+	{0x00, 0xec, 0x31, 0xd2, 0x00, 0x40, 0x37, 0x62,
+	0x01, 0x0f, 0x07,
+	0x05, 0x14, 0x03, 0x0, 0x0, 0x0, 0x20, 0x0, 0x02, 0x0},
+};
+
+static int mipi_video_nt35510_wvga_pt_init(void)
+{
+	int ret;
+
+	if (msm_fb_detect_client("mipi_video_nt35510_wvga"))
+		return 0;
+
+	pinfo.xres = 480;
+	pinfo.yres = 800;
+	pinfo.type = MIPI_VIDEO_PANEL;
+	pinfo.pdest = DISPLAY_1;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 24;
+	pinfo.lcdc.h_back_porch = 100;
+	pinfo.lcdc.h_front_porch = 100;
+	pinfo.lcdc.h_pulse_width = 8;
+	pinfo.lcdc.v_back_porch = 20;
+	pinfo.lcdc.v_front_porch = 20;
+	pinfo.lcdc.v_pulse_width = 1;
+	pinfo.lcdc.border_clr = 0;	/* blk */
+	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
+	/* number of dot_clk cycles HSYNC active edge is
+	delayed from VSYNC active edge */
+	pinfo.lcdc.hsync_skew = 0;
+	pinfo.clk_rate = 499000000;
+	pinfo.bl_max = 100; /*16; CHECK THIS!!!*/
+	pinfo.bl_min = 1;
+	pinfo.fb_num = 2;
+
+	pinfo.mipi.mode = DSI_VIDEO_MODE;
+	/* send HSA and HE following VS/VE packet */
+	pinfo.mipi.pulse_mode_hsa_he = TRUE;
+	pinfo.mipi.hfp_power_stop = TRUE; /* LP-11 during the HFP period */
+	pinfo.mipi.hbp_power_stop = TRUE; /* LP-11 during the HBP period */
+	pinfo.mipi.hsa_power_stop = TRUE; /* LP-11 during the HSA period */
+	/* LP-11 or let Command Mode Engine send packets in
+	HS or LP mode for the BLLP of the last line of a frame */
+	pinfo.mipi.eof_bllp_power_stop = TRUE;
+	/* LP-11 or let Command Mode Engine send packets in
+	HS or LP mode for packets sent during BLLP period */
+	pinfo.mipi.bllp_power_stop = TRUE;
+
+	pinfo.mipi.traffic_mode = DSI_BURST_MODE;
+	pinfo.mipi.dst_format =  DSI_VIDEO_DST_FORMAT_RGB888;
+	pinfo.mipi.vc = 0;
+	pinfo.mipi.rgb_swap = DSI_RGB_SWAP_RGB; /* RGB */
+	pinfo.mipi.data_lane0 = TRUE;
+	pinfo.mipi.data_lane1 = TRUE;
+
+	pinfo.mipi.t_clk_post = 0x20;
+	pinfo.mipi.t_clk_pre = 0x2f;
+
+	pinfo.mipi.stream = 0; /* dma_p */
+	pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_NONE;
+	pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+	pinfo.mipi.frame_rate = 60; /* FIXME */
+
+	pinfo.mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+	pinfo.mipi.dlane_swap = 0x01;
+	/* append EOT at the end of data burst */
+	pinfo.mipi.tx_eot_append = 0x01;
+
+	ret = mipi_nt35510_device_register(&pinfo, MIPI_DSI_PRIM,
+						MIPI_DSI_PANEL_WVGA_PT);
+
+	if (ret)
+		pr_err("%s: failed to register device!\n", __func__);
+
+	return ret;
+}
+
+module_init(mipi_video_nt35510_wvga_pt_init);
diff --git a/drivers/video/msm/mipi_chimei_wuxga.c b/drivers/video/msm/mipi_chimei_wuxga.c
new file mode 100644
index 0000000..c63df46
--- /dev/null
+++ b/drivers/video/msm/mipi_chimei_wuxga.c
@@ -0,0 +1,196 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*
+ * Chimei WUXGA LVDS Panel driver.
+ * The panel model is N101JSF-L21.
+ *
+ * The panel interface includes:
+ * 1. LVDS input for video (clock & data).
+ * 2. few configuration	pins to control 3D module: Enable, Mode (2D/3D).
+ * 3. Backlight LED control (PWM 200 HZ).
+ *
+ * This panel is controled via the Toshiba DSI-to-LVDS bridge.
+ *
+ */
+
+/* #define DEBUG 1 */
+
+#include "msm_fb.h"
+#include "msm_fb_panel.h"
+#include "mipi_dsi.h"
+#include "mipi_tc358764_dsi2lvds.h"
+
+#define MHZ (1000*1000)
+
+/**
+ * Panel info parameters.
+ * The panel info is passed to the mipi framebuffer driver.
+ */
+static struct msm_panel_info chimei_wuxga_pinfo;
+
+/**
+ * The mipi_dsi_phy_ctrl is calculated according to the
+ * "dsi_timing_program.xlsm" excel sheet.
+ * Output is based on: 1200x1920, RGB565, 4 lanes , 58 frames
+ * per second.
+ */
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+	/* DSIPHY_REGULATOR_CTRL */
+	.regulator = {0x03, 0x0a, 0x04, 0x00, 0x20}, /* common 8960 */
+	/* DSIPHY_CTRL */
+	.ctrl = {0x5f, 0x00, 0x00, 0x10}, /* common 8960 */
+	/* DSIPHY_STRENGTH_CTRL */
+	.strength = {0xff, 0x00, 0x06, 0x00}, /* common 8960 */
+	/* DSIPHY_TIMING_CTRL */
+	.timing = { 0xC9, 0x92, 0x29, /* panel specific */
+	0, /* DSIPHY_TIMING_CTRL_3 = 0 */
+	0x2E, 0x9B, 0x2C, 0x94, 0x2E, 0x03, 0x04},  /* panel specific */
+
+	/* DSIPHY_PLL_CTRL */
+	.pll = { 0x00, /* common 8960 */
+	/* VCO */
+	0x32, (0x01 | 0x30) , (0x19 | 0xC0), /* panel specific */
+	0x00, 0x50, 0x48, 0x63,
+	0x77, 0x88, 0x99, /* Auto update by dsi-mipi driver */
+	0x00, 0x14, 0x03, 0x00, 0x02, /* common 8960 */
+	0x00, 0x20, 0x00, 0x01 }, /* common 8960 */
+};
+
+/**
+ * Module init.
+ *
+ * Register the panel-info.
+ *
+ * Some parameters are from the panel datasheet
+ * and other are *calculated* by the "dsi_timing_program.xlsm"
+ * excel file
+ *
+ * @return int
+ */
+static int __init mipi_chimei_wuxga_init(void)
+{
+	int ret;
+	struct msm_panel_info *pinfo = &chimei_wuxga_pinfo;
+
+	if (msm_fb_detect_client("mipi_video_chimei_wuxga"))
+		return 0;
+
+	pr_info("mipi-dsi chimei wuxga (1200x1920) driver ver 1.0.\n");
+
+	/* Portrait */
+	pinfo->xres = 1200;
+	pinfo->yres = 1920;
+	pinfo->type =  MIPI_VIDEO_PANEL;
+	pinfo->pdest = DISPLAY_1; /* Primary Display */
+	pinfo->wait_cycle = 0;
+	pinfo->bpp = 24; /* RGB565 requires 24 bits-per-pixel :-O */
+	pinfo->fb_num = 2; /* using two frame buffers */
+
+	/*
+	 * The CMI panel requires 80 MHZ LVDS-CLK.
+	 * The D2L bridge drives the LVDS-CLK from the DSI-CLK.
+	 * The DSI-CLK = bitclk/2, 640 MHZ/2= 320 MHZ.
+	 * LVDS-CLK = DSI-CLK/4 , 320 MHZ/4= 80 MHZ.
+	 */
+
+	pinfo->clk_rate = 640 * MHZ ; /* bitclk Calculated */
+
+	/*
+	 * this panel is operated by DE,
+	 * vsycn and hsync are ignored
+	 */
+
+	pinfo->lcdc.h_front_porch = 16;	/* thfp */
+	pinfo->lcdc.h_back_porch = 160;	/* thb */
+	pinfo->lcdc.h_pulse_width = 32;	/* thpw */
+
+	pinfo->lcdc.v_front_porch = 0;	/* tvfp */
+	pinfo->lcdc.v_back_porch = 26;	/* tvb */
+	pinfo->lcdc.v_pulse_width = 6;	/* tvpw */
+
+	pinfo->lcdc.border_clr = 0;		/* black */
+	pinfo->lcdc.underflow_clr = 0xff;	/* blue */
+
+	pinfo->lcdc.hsync_skew = 0;
+
+	/* Backlight levels - controled via PMIC pwm gpio */
+	pinfo->bl_max = 15;
+	pinfo->bl_min = 1;
+
+	/* mipi - general */
+	pinfo->mipi.vc = 0; /* virtual channel */
+	pinfo->mipi.rgb_swap = DSI_RGB_SWAP_RGB;
+	pinfo->mipi.tx_eot_append = true;
+	pinfo->mipi.t_clk_post = 34;		/* Calculated */
+	pinfo->mipi.t_clk_pre = 69;		/* Calculated */
+
+	pinfo->mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+
+	/* Four lanes are recomended for 1920x1200 at 60 frames per second */
+	pinfo->mipi.frame_rate = 45; /* 45 frames per second */
+	pinfo->mipi.data_lane0 = true;
+	pinfo->mipi.data_lane1 = true;
+	pinfo->mipi.data_lane2 = true;
+	pinfo->mipi.data_lane3 = true;
+
+	pinfo->mipi.mode = DSI_VIDEO_MODE;
+	/*
+	 * Note: The CMI panel input is RGB888,
+	 * thus the DSI-to-LVDS bridge output is RGB888.
+	 * This parameter selects the DSI-Core output to the bridge.
+	 */
+	pinfo->mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB565;
+
+	/* mipi - video mode */
+	pinfo->mipi.traffic_mode = DSI_NON_BURST_SYNCH_EVENT;
+	pinfo->mipi.pulse_mode_hsa_he = false; /* sync mode */
+
+	pinfo->mipi.hfp_power_stop = false;
+	pinfo->mipi.hbp_power_stop = false;
+	pinfo->mipi.hsa_power_stop = false;
+	pinfo->mipi.eof_bllp_power_stop = false;
+	pinfo->mipi.bllp_power_stop = false;
+
+	/* mipi - command mode */
+	pinfo->mipi.te_sel = 1; /* TE from vsycn gpio */
+	pinfo->mipi.interleave_max = 1;
+	/* The bridge supports only Generic Read/Write commands */
+	pinfo->mipi.insert_dcs_cmd = false;
+	pinfo->mipi.wr_mem_continue = 0;
+	pinfo->mipi.wr_mem_start = 0;
+	pinfo->mipi.stream = false; /* dma_p */
+	pinfo->mipi.mdp_trigger = DSI_CMD_TRIGGER_NONE;
+	pinfo->mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+	/*
+	 * toshiba d2l chip does not need max_pkt_size dcs cmd
+	 * client reply len is directly configure through
+	 * RDPKTLN register (0x0404)
+	 */
+	pinfo->mipi.no_max_pkt_size = 1;
+	pinfo->mipi.force_clk_lane_hs = 1;
+
+	pinfo->is_3d_panel = FB_TYPE_3D_PANEL;
+
+	ret = mipi_tc358764_dsi2lvds_register(pinfo, MIPI_DSI_PRIM, 1);
+	if (ret)
+		pr_err("%s: failed to register device!\n", __func__);
+
+	return ret;
+}
+
+module_init(mipi_chimei_wuxga_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Chimei WUXGA LVDS Panel driver");
+MODULE_AUTHOR("Amir Samuelov <amirs@codeaurora.org>");
diff --git a/drivers/video/msm/mipi_novatek.c b/drivers/video/msm/mipi_novatek.c
index caa4114..ed0dee4 100644
--- a/drivers/video/msm/mipi_novatek.c
+++ b/drivers/video/msm/mipi_novatek.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -461,6 +461,7 @@
 	struct mipi_panel_info *mipi;
 	struct platform_device *current_pdev;
 	static struct mipi_dsi_phy_ctrl *phy_settings;
+	static char dlane_swap;
 
 	if (pdev->id == 0) {
 		mipi_novatek_pdata = pdev->dev.platform_data;
@@ -471,6 +472,11 @@
 		}
 
 		if (mipi_novatek_pdata
+			&& mipi_novatek_pdata->dlane_swap) {
+			dlane_swap = (mipi_novatek_pdata->dlane_swap);
+		}
+
+		if (mipi_novatek_pdata
 			 && mipi_novatek_pdata->fpga_3d_config_addr)
 			mipi_novatek_3d_init(mipi_novatek_pdata
 	->fpga_3d_config_addr, mipi_novatek_pdata->fpga_ctrl_mode);
@@ -499,6 +505,9 @@
 
 		if (phy_settings != NULL)
 			mipi->dsi_phy_db = phy_settings;
+
+		if (dlane_swap)
+			mipi->dlane_swap = dlane_swap;
 	}
 	return 0;
 }
diff --git a/drivers/video/msm/mipi_tc358764_dsi2lvds.c b/drivers/video/msm/mipi_tc358764_dsi2lvds.c
index 8055bd0..fcb5163 100644
--- a/drivers/video/msm/mipi_tc358764_dsi2lvds.c
+++ b/drivers/video/msm/mipi_tc358764_dsi2lvds.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -68,7 +68,9 @@
 #include <linux/i2c.h>
 #include <linux/delay.h>
 #include <linux/pwm.h>
+#include <linux/gpio.h>
 #include "msm_fb.h"
+#include "mdp4.h"
 #include "mipi_dsi.h"
 #include "mipi_tc358764_dsi2lvds.h"
 
@@ -186,7 +188,11 @@
 #define DEBUG01		0x05A4	/* LVDS Data */
 
 /* PWM */
-#define PWM_FREQ_HZ	(66*1000)	/* 66 KHZ */
+static u32 d2l_pwm_freq_hz = (66*1000);
+
+/* 1366x768 uses pwm at 66 KHZ */
+/* 1200x1920 uses pwm at 25 KHZ */
+#define PWM_FREQ_HZ	(d2l_pwm_freq_hz)
 #define PWM_LEVEL 15
 #define PWM_PERIOD_USEC (USEC_PER_SEC / PWM_FREQ_HZ)
 #define PWM_DUTY_LEVEL (PWM_PERIOD_USEC / PWM_LEVEL)
@@ -213,10 +219,17 @@
 static struct dsi_buf d2l_rx_buf;
 static int led_pwm;
 static struct pwm_device *bl_pwm;
+static struct pwm_device *tn_pwm;
 static int bl_level;
 static u32 d2l_gpio_out_mask;
 static u32 d2l_gpio_out_val;
+static u32 d2l_3d_gpio_enable;
+static u32 d2l_3d_gpio_mode;
+static int d2l_enable_3d;
+
 static int mipi_d2l_init(void);
+static int mipi_d2l_enable_3d(struct msm_fb_data_type *mfd,
+			      bool enable, bool mode);
 
 /**
  * Read a bridge register
@@ -236,7 +249,7 @@
 	mipi_dsi_buf_init(&d2l_tx_buf);
 	mipi_dsi_buf_init(&d2l_rx_buf);
 
-	/* mutex had been acquried at dsi_on */
+	/* mutex had been acquired at mipi_dsi_on */
 	len = mipi_dsi_cmds_rx(mfd, &d2l_tx_buf, &d2l_rx_buf,
 			       &cmd_read_reg, len);
 
@@ -247,7 +260,6 @@
 
 	pr_debug("%s: reg=0x%x.data=0x%08x.\n", __func__, reg, data);
 
-
 	return data;
 }
 
@@ -256,9 +268,9 @@
  *
  * @param mfd
  *
- * @return register data value
+ * @return int
  */
-static u32 mipi_d2l_write_reg(struct msm_fb_data_type *mfd, u16 reg, u32 data)
+static int mipi_d2l_write_reg(struct msm_fb_data_type *mfd, u16 reg, u32 data)
 {
 	struct wr_cmd_payload payload;
 	struct dsi_cmd_desc cmd_write_reg = {
@@ -268,35 +280,25 @@
 	payload.addr = reg;
 	payload.data = data;
 
-	/* mutex had been acquried at dsi_on */
+	/* mutex had been acquired at mipi_dsi_on */
 	mipi_dsi_cmds_tx(mfd, &d2l_tx_buf, &cmd_write_reg, 1);
 
 	pr_debug("%s: reg=0x%x. data=0x%x.\n", __func__, reg, data);
 
-	return data;
+	return 0;
 }
 
-/*
+static void mipi_d2l_read_status(struct msm_fb_data_type *mfd)
+{
+	mipi_d2l_read_reg(mfd, DSI_LANESTATUS0);	/* 0x214 */
+	mipi_d2l_read_reg(mfd, DSI_LANESTATUS1);	/* 0x218 */
+	mipi_d2l_read_reg(mfd, DSI_INTSTATUS);		/* 0x220 */
+	mipi_d2l_read_reg(mfd, SYSSTAT);		/* 0x500 */
+}
+
+/**
  * Init the D2L bridge via the DSI interface for Video.
  *
- *	Register		Addr	Value
- *  ===================================================
- *  PPI_TX_RX_TA		0x013C	0x00040004
- *  PPI_LPTXTIMECNT	        0x0114	0x00000004
- *  PPI_D0S_CLRSIPOCOUNT	0x0164	0x00000003
- *  PPI_D1S_CLRSIPOCOUNT	0x0168	0x00000003
- *  PPI_D2S_CLRSIPOCOUNT	0x016C	0x00000003
- *  PPI_D3S_CLRSIPOCOUNT	0x0170	0x00000003
- *  PPI_LANEENABLE	        0x0134	0x0000001F
- *  DSI_LANEENABLE	        0x0210	0x0000001F
- *  PPI_STARTPPI	        0x0104	0x00000001
- *  DSI_STARTDSI	        0x0204	0x00000001
- *  VPCTRL			0x0450	0x01000120
- *  HTIM1			0x0454	0x002C0028
- *  VTIM1			0x045C	0x001E0008
- *  VFUEN			0x0464	0x00000001
- *  LVCFG			0x049C	0x00000001
- *
  * VPCTRL.EVTMODE (0x20) configuration bit is needed to determine whether
  * video timing information is delivered in pulse mode or event mode.
  * In pulse mode, both Sync Start and End packets are required.
@@ -304,15 +306,22 @@
  *
  * @param mfd
  *
- * @return register data value
+ * @return int
  */
 static int mipi_d2l_dsi_init_sequence(struct msm_fb_data_type *mfd)
 {
 	struct mipi_panel_info *mipi = &mfd->panel_info.mipi;
 	u32 lanes_enable;
 	u32 vpctrl;
-	u32 htime1 = 0x002C0028;
-	u32 vtime1 = 0x001E0008;
+	u32 htime1;
+	u32 vtime1;
+	u32 ppi_tx_rx_ta; /* BTA Bus-Turn-Around */
+	u32 lvcfg;
+	u32 hbpr;	/* Horizontal Back Porch */
+	u32 hpw;	/* Horizontal Pulse Width */
+	u32 vbpr;	/* Vertical Back Porch */
+	u32 vpw;	/* Vertical Pulse Width */
+	bool vesa_rgb888 = false;
 
 	lanes_enable = 0x01; /* clock-lane enable */
 	lanes_enable |= (mipi->data_lane0 << 1);
@@ -330,25 +339,57 @@
 		return -EINVAL;
 	}
 
+	if (mfd->panel_info.clk_rate > 800*1000*1000) {
+		pr_err("%s.unsupported clk_rate %d.\n",
+		       __func__, mfd->panel_info.clk_rate);
+		return -EINVAL;
+	}
+
+	pr_debug("%s.xres=%d.yres=%d.\n",
+		__func__, mfd->panel_info.xres, mfd->panel_info.yres);
+
+	hbpr = mfd->panel_info.lcdc.h_back_porch;
+	hpw	= mfd->panel_info.lcdc.h_pulse_width;
+	vbpr = mfd->panel_info.lcdc.v_back_porch;
+	vpw	= mfd->panel_info.lcdc.v_pulse_width;
+
+	htime1 = (hbpr << 16) + hpw;
+	vtime1 = (vbpr << 16) + vpw;
+	lvcfg = 0x0003; /* PCLK=DCLK/3, Dual Link, LVEN */
+	vpctrl = 0x01000120; /* Output RGB888 , Event-Mode , */
+	ppi_tx_rx_ta = 0x00040004;
+
+	if (mfd->panel_info.xres == 1366) {
+		ppi_tx_rx_ta = 0x00040004;
+		lvcfg = 0x01; /* LVEN */
+		vesa_rgb888 = true;
+	}
+
+	if (mfd->panel_info.xres == 1200) {
+		lvcfg = 0x0103; /* PCLK=DCLK/4, Dual Link, LVEN */
+		vesa_rgb888 = true;
+	}
+
 	pr_debug("%s.htime1=0x%x.\n", __func__, htime1);
 	pr_debug("%s.vtime1=0x%x.\n", __func__, vtime1);
 	pr_debug("%s.vpctrl=0x%x.\n", __func__, vpctrl);
-	pr_debug("%s.lanes_enable=0x%x.\n", __func__, lanes_enable);
-
+	pr_debug("%s.lvcfg=0x%x.\n", __func__, lvcfg);
 
 	mipi_d2l_write_reg(mfd, SYSRST, 0xFF);
 	msleep(30);
 
-	/* VESA format instead of JEIDA format for RGB888 */
-	mipi_d2l_write_reg(mfd, LVMX0003, 0x03020100);
-	mipi_d2l_write_reg(mfd, LVMX0407, 0x08050704);
-	mipi_d2l_write_reg(mfd, LVMX0811, 0x0F0E0A09);
-	mipi_d2l_write_reg(mfd, LVMX1215, 0x100D0C0B);
-	mipi_d2l_write_reg(mfd, LVMX1619, 0x12111716);
-	mipi_d2l_write_reg(mfd, LVMX2023, 0x1B151413);
-	mipi_d2l_write_reg(mfd, LVMX2427, 0x061A1918);
+	if (vesa_rgb888) {
+		/* VESA format instead of JEIDA format for RGB888 */
+		mipi_d2l_write_reg(mfd, LVMX0003, 0x03020100);
+		mipi_d2l_write_reg(mfd, LVMX0407, 0x08050704);
+		mipi_d2l_write_reg(mfd, LVMX0811, 0x0F0E0A09);
+		mipi_d2l_write_reg(mfd, LVMX1215, 0x100D0C0B);
+		mipi_d2l_write_reg(mfd, LVMX1619, 0x12111716);
+		mipi_d2l_write_reg(mfd, LVMX2023, 0x1B151413);
+		mipi_d2l_write_reg(mfd, LVMX2427, 0x061A1918);
+	}
 
-	mipi_d2l_write_reg(mfd, PPI_TX_RX_TA, 0x00040004); /* BTA */
+	mipi_d2l_write_reg(mfd, PPI_TX_RX_TA, ppi_tx_rx_ta); /* BTA */
 	mipi_d2l_write_reg(mfd, PPI_LPTXTIMECNT, 0x00000004);
 	mipi_d2l_write_reg(mfd, PPI_D0S_CLRSIPOCOUNT, 0x00000003);
 	mipi_d2l_write_reg(mfd, PPI_D1S_CLRSIPOCOUNT, 0x00000003);
@@ -363,7 +404,7 @@
 	mipi_d2l_write_reg(mfd, HTIM1, htime1);
 	mipi_d2l_write_reg(mfd, VTIM1, vtime1);
 	mipi_d2l_write_reg(mfd, VFUEN, 0x00000001);
-	mipi_d2l_write_reg(mfd, LVCFG, 0x00000001); /* Enables LVDS tx */
+	mipi_d2l_write_reg(mfd, LVCFG, lvcfg); /* Enables LVDS tx */
 
 	return 0;
 }
@@ -400,6 +441,35 @@
 		return ret;
 	}
 
+	return 0;
+}
+
+/**
+ * Set TN CLK.
+ *
+ * @param pwm
+ * @param level
+ *
+ * @return int
+ */
+static int mipi_d2l_set_tn_clk(struct pwm_device *pwm, u32 usec)
+{
+	int ret = 0;
+
+	pr_debug("%s: usec=%d.\n", __func__, usec);
+
+	ret = pwm_config(pwm, usec/2 , usec);
+	if (ret) {
+		pr_err("%s: pwm_config() failed err=%d.\n", __func__, ret);
+		return ret;
+	}
+
+	ret = pwm_enable(pwm);
+	if (ret) {
+		pr_err("%s: pwm_enable() failed err=%d\n",
+		       __func__, ret);
+		return ret;
+	}
 
 	return 0;
 }
@@ -446,9 +516,14 @@
 		return ret;
 
 	mipi_d2l_write_reg(mfd, GPIOC, d2l_gpio_out_mask);
-	/* Set GPIOs: gpio#4=U/D=0 , gpio#3=L/R=1 , gpio#2,1=CABC=0. */
+	/* Set gpio#4=U/D=0, gpio#3=L/R=1 , gpio#2,1=CABC=0, gpio#0=NA. */
 	mipi_d2l_write_reg(mfd, GPIOO, d2l_gpio_out_val);
 
+	if (mfd->panel_info.xres == 1366)
+		d2l_pwm_freq_hz = (66*1000);
+	else
+		d2l_pwm_freq_hz = (25*1000);
+
 	if (bl_level == 0)
 		bl_level = PWM_LEVEL * 2 / 3 ; /* Default ON value */
 
@@ -460,6 +535,10 @@
 			       __func__, ret);
 	}
 
+	mipi_d2l_read_status(mfd);
+
+	mipi_d2l_enable_3d(mfd, false, false);
+
 	pr_info("%s.ret=%d.\n", __func__, ret);
 
 	return ret;
@@ -510,6 +589,98 @@
 	.set_backlight = mipi_d2l_set_backlight,
 };
 
+static int mipi_d2l_enable_3d(struct msm_fb_data_type *mfd,
+			      bool enable, bool mode)
+{
+	u32 tn_usec = 1000000 / 66; /* 66 HZ */
+
+	pr_debug("%s.enable=%d.mode=%d.\n", __func__, enable, mode);
+
+	gpio_direction_output(d2l_3d_gpio_enable, enable);
+	gpio_direction_output(d2l_3d_gpio_mode, mode);
+
+	mipi_d2l_set_tn_clk(tn_pwm, tn_usec);
+
+	return 0;
+}
+
+static ssize_t mipi_d2l_enable_3d_read(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	return snprintf((char *)buf, sizeof(buf), "%u\n", d2l_enable_3d);
+}
+
+static ssize_t mipi_d2l_enable_3d_write(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf,
+				size_t count)
+{
+	int ret = -1;
+	u32 data = 0;
+
+	if (sscanf((char *)buf, "%u", &data) != 1) {
+		dev_err(dev, "%s. Invalid input.\n", __func__);
+		ret = -EINVAL;
+	} else {
+		d2l_enable_3d = data;
+		if (data == 1) /* LANDSCAPE */
+			mipi_d2l_enable_3d(d2l_mfd, true, true);
+		else if (data == 2) /* PORTRAIT */
+			mipi_d2l_enable_3d(d2l_mfd, true, false);
+		else if (data == 0)
+			mipi_d2l_enable_3d(d2l_mfd, false, false);
+		else
+			pr_err("%s.Invalid value=%d.\n", __func__, data);
+	}
+
+	return count;
+}
+
+static struct device_attribute mipi_d2l_3d_barrier_attributes[] = {
+	__ATTR(enable_3d_barrier, 0666,
+	       mipi_d2l_enable_3d_read,
+	       mipi_d2l_enable_3d_write),
+};
+
+static int mipi_dsi_3d_barrier_sysfs_register(struct device *dev)
+{
+	int ret;
+
+	pr_debug("%s.d2l_3d_gpio_enable=%d.\n", __func__, d2l_3d_gpio_enable);
+	pr_debug("%s.d2l_3d_gpio_mode=%d.\n", __func__, d2l_3d_gpio_mode);
+
+	ret  = device_create_file(dev, mipi_d2l_3d_barrier_attributes);
+	if (ret) {
+		pr_err("%s.failed to create 3D sysfs.\n", __func__);
+		goto err_device_create_file;
+	}
+
+	ret = gpio_request(d2l_3d_gpio_enable, "d2l_3d_gpio_enable");
+	if (ret) {
+		pr_err("%s.failed to get d2l_3d_gpio_enable=%d.\n",
+		       __func__, d2l_3d_gpio_enable);
+		goto err_d2l_3d_gpio_enable;
+	}
+
+	ret = gpio_request(d2l_3d_gpio_mode, "d2l_3d_gpio_mode");
+	if (ret) {
+		pr_err("%s.failed to get d2l_3d_gpio_mode=%d.\n",
+		       __func__, d2l_3d_gpio_mode);
+		goto err_d2l_3d_gpio_mode;
+	}
+
+	return 0;
+
+err_d2l_3d_gpio_mode:
+	gpio_free(d2l_3d_gpio_enable);
+err_d2l_3d_gpio_enable:
+	device_remove_file(dev, mipi_d2l_3d_barrier_attributes);
+err_device_create_file:
+
+	return ret;
+}
+
 /**
  * Probe for device.
  *
@@ -530,7 +701,6 @@
 	pr_debug("%s.id=%d.\n", __func__, pdev->id);
 
 	if (pdev->id == 0) {
-		/* d2l_common_pdata = platform_get_drvdata(pdev); */
 		d2l_common_pdata = pdev->dev.platform_data;
 
 		if (d2l_common_pdata == NULL) {
@@ -541,6 +711,8 @@
 		led_pwm = d2l_common_pdata->gpio_num[0];
 		d2l_gpio_out_mask = d2l_common_pdata->gpio_num[1] >> 8;
 		d2l_gpio_out_val = d2l_common_pdata->gpio_num[1] & 0xFF;
+		d2l_3d_gpio_enable = d2l_common_pdata->gpio_num[2];
+		d2l_3d_gpio_mode = d2l_common_pdata->gpio_num[3];
 
 		mipi_dsi_buf_alloc(&d2l_tx_buf, DSI_BUF_SIZE);
 		mipi_dsi_buf_alloc(&d2l_rx_buf, DSI_BUF_SIZE);
@@ -567,10 +739,20 @@
 
 		}
 	} else {
-		pr_info("%s. led_pwm is invalid.\n", __func__);
+		pr_err("%s. led_pwm is invalid.\n", __func__);
 	}
 
-	/* pinfo = platform_get_drvdata(pdev); */
+	tn_pwm = pwm_request(1, "3D_TN_clk");
+	if (tn_pwm == NULL || IS_ERR(tn_pwm)) {
+		pr_err("%s pwm_request() failed.id=%d.tn_pwm=%d.\n",
+		       __func__, 1, (int) tn_pwm);
+		tn_pwm = NULL;
+		return -EIO;
+	} else {
+		pr_debug("%s.pwm_request() ok.pwm-id=%d.\n", __func__, 1);
+
+	}
+
 	pinfo = pdev->dev.platform_data;
 
 	if (pinfo == NULL) {
@@ -584,6 +766,9 @@
 
 	msm_fb_add_device(pdev);
 
+	if (pinfo->is_3d_panel)
+		mipi_dsi_3d_barrier_sysfs_register(&(pdev->dev));
+
 	return ret;
 }
 
@@ -667,6 +852,7 @@
 static int mipi_d2l_init(void)
 {
 	pr_debug("%s.\n", __func__);
+
 	return platform_driver_register(&d2l_driver);
 }
 
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 42fa2ba..489e6d2 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -1520,8 +1520,8 @@
 			pdata->set_backlight(mfd);
 			bl_level_old = unset_bl_level;
 			up(&mfd->sem);
+			bl_updated = 1;
 		}
-		bl_updated = 1;
 	}
 
 	++mfd->panel_info.frame_count;
@@ -2624,8 +2624,8 @@
 			pdata->set_backlight(mfd);
 			bl_level_old = unset_bl_level;
 			up(&mfd->sem);
+			bl_updated = 1;
 		}
-		bl_updated = 1;
 	}
 
 	return ret;
diff --git a/include/linux/leds-pm8xxx.h b/include/linux/leds-pm8xxx.h
index 3f31498..18e6398 100644
--- a/include/linux/leds-pm8xxx.h
+++ b/include/linux/leds-pm8xxx.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -34,6 +34,8 @@
 	PM8XXX_ID_LED_2,
 	PM8XXX_ID_FLASH_LED_0,
 	PM8XXX_ID_FLASH_LED_1,
+	PM8XXX_ID_WLED,
+	PM8XXX_ID_MAX,
 };
 
 /**
@@ -50,6 +52,48 @@
 	PM8XXX_LED_MODE_DTEST4
 };
 
+/* current boost limit */
+enum wled_current_bost_limit {
+	WLED_CURR_LIMIT_105mA,
+	WLED_CURR_LIMIT_385mA,
+	WLED_CURR_LIMIT_525mA,
+	WLED_CURR_LIMIT_805mA,
+	WLED_CURR_LIMIT_980mA,
+	WLED_CURR_LIMIT_1260mA,
+	WLED_CURR_LIMIT_1400mA,
+	WLED_CURR_LIMIT_1680mA,
+};
+
+/* over voltage protection threshold */
+enum wled_ovp_threshold {
+	WLED_OVP_35V,
+	WLED_OVP_32V,
+	WLED_OVP_29V,
+	WLED_OVP_37V,
+};
+
+/**
+ *  wled_config_data - wled configuration data
+ *  @num_strings - number of wled strings supported
+ *  @ovp_val - over voltage protection threshold
+ *  @boost_curr_lim - boot current limit
+ *  @cp_select - high pole capacitance
+ *  @ctrl_delay_us - delay in activation of led
+ *  @dig_mod_gen_en - digital module generator
+ *  @cs_out_en - current sink output enable
+ *  @op_fdbck - selection of output as feedback for the boost
+ */
+struct wled_config_data {
+	u8	num_strings;
+	u8	ovp_val;
+	u8	boost_curr_lim;
+	u8	cp_select;
+	u8	ctrl_delay_us;
+	bool	dig_mod_gen_en;
+	bool	cs_out_en;
+	bool	op_fdbck;
+};
+
 /**
  * pm8xxx_led_config - led configuration parameters
  * @id - LED id
@@ -57,6 +101,7 @@
  * @max_current - maximum current that LED can sustain
  * @pwm_channel - PWM channel ID the LED is driven to
  * @pwm_period_us - PWM period value in micro seconds
+ * @default_state - default state of the led
  * @pwm_duty_cycles - PWM duty cycle information
  */
 struct pm8xxx_led_config {
@@ -65,7 +110,9 @@
 	u16	max_current;
 	int	pwm_channel;
 	u32	pwm_period_us;
+	bool	default_state;
 	struct pm8xxx_pwm_duty_cycles *pwm_duty_cycles;
+	struct wled_config_data	*wled_cfg;
 };
 
 /**
diff --git a/include/linux/mfd/pm8xxx/pm8038.h b/include/linux/mfd/pm8xxx/pm8038.h
index 203095a..4d3c78f 100644
--- a/include/linux/mfd/pm8xxx/pm8038.h
+++ b/include/linux/mfd/pm8xxx/pm8038.h
@@ -30,6 +30,7 @@
 #include <linux/mfd/pm8xxx/pm8xxx-adc.h>
 #include <linux/mfd/pm8xxx/pm8921-charger.h>
 #include <linux/mfd/pm8xxx/pm8921-bms.h>
+#include <linux/leds-pm8xxx.h>
 #include <linux/mfd/pm8xxx/ccadc.h>
 
 #define PM8038_CORE_DEV_NAME "pm8038-core"
@@ -75,6 +76,7 @@
 	struct pm8921_charger_platform_data	*charger_pdata;
 	struct pm8921_bms_platform_data		*bms_pdata;
 	struct pm8xxx_adc_platform_data		*adc_pdata;
+	struct pm8xxx_led_platform_data		*leds_pdata;
 	struct pm8xxx_ccadc_platform_data	*ccadc_pdata;
 };
 
diff --git a/include/linux/mfd/wcd9310/core.h b/include/linux/mfd/wcd9310/core.h
index 982803d..8605ac6 100644
--- a/include/linux/mfd/wcd9310/core.h
+++ b/include/linux/mfd/wcd9310/core.h
@@ -14,6 +14,7 @@
 #define __MFD_TABLA_CORE_H__
 
 #include <linux/interrupt.h>
+#include <linux/wakelock.h>
 
 #define TABLA_NUM_IRQ_REGS 3
 
@@ -55,6 +56,12 @@
 	TABLA_NUM_IRQS,
 };
 
+enum tabla_pm_state {
+	TABLA_PM_SLEEPABLE,
+	TABLA_PM_AWAKE,
+	TABLA_PM_ASLEEP,
+};
+
 struct tabla {
 	struct device *dev;
 	struct slim_device *slim;
@@ -78,23 +85,33 @@
 			 int bytes, void *src, bool interface_reg);
 
 	struct regulator_bulk_data *supplies;
+
+	enum tabla_pm_state pm_state;
+	struct mutex pm_lock;
+	/* pm_wq notifies change of pm_state */
+	wait_queue_head_t pm_wq;
+	struct wake_lock wlock;
+	int wlock_holders;
 };
 
 int tabla_reg_read(struct tabla *tabla, unsigned short reg);
-int tabla_reg_write(struct tabla *tabla, unsigned short reg,
-		u8 val);
+int tabla_reg_write(struct tabla *tabla, unsigned short reg, u8 val);
 int tabla_interface_reg_read(struct tabla *tabla, unsigned short reg);
-int tabla_interface_reg_write(struct tabla *tabla, unsigned short reg,
-		u8 val);
-int tabla_bulk_read(struct tabla *tabla, unsigned short reg,
-			int count, u8 *buf);
-int tabla_bulk_write(struct tabla *tabla, unsigned short reg,
-			int count, u8 *buf);
+int tabla_interface_reg_write(struct tabla *tabla, unsigned short reg, u8 val);
+int tabla_bulk_read(struct tabla *tabla, unsigned short reg, int count,
+		    u8 *buf);
+int tabla_bulk_write(struct tabla *tabla, unsigned short reg, int count,
+		     u8 *buf);
 int tabla_irq_init(struct tabla *tabla);
 void tabla_irq_exit(struct tabla *tabla);
 int tabla_get_logical_addresses(u8 *pgd_la, u8 *inf_la);
 int tabla_get_intf_type(void);
 
+void tabla_lock_sleep(struct tabla *tabla);
+void tabla_unlock_sleep(struct tabla *tabla);
+enum tabla_pm_state tabla_pm_cmpxchg(struct tabla *tabla, enum tabla_pm_state o,
+				     enum tabla_pm_state n);
+
 static inline int tabla_request_irq(struct tabla *tabla, int irq,
 				     irq_handler_t handler, const char *name,
 				     void *data)
diff --git a/include/linux/mfd/wcd9310/wcd9310-slimslave.h b/include/linux/mfd/wcd9310/wcd9310-slimslave.h
new file mode 100644
index 0000000..0bbf96f
--- /dev/null
+++ b/include/linux/mfd/wcd9310/wcd9310-slimslave.h
@@ -0,0 +1,102 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __WCD9310_SLIMSLAVE_H_
+#define __WCD9310_SLIMSLAVE_H_
+
+#include <linux/slimbus/slimbus.h>
+#include <linux/mfd/wcd9310/core.h>
+
+/* Local to the core only */
+#define SLIM_MAX_RX_PORTS 7
+#define SLIM_MAX_TX_PORTS 10
+
+/* Channel numbers to be used for each port */
+enum {
+	SLIM_TX_1   = 128,
+	SLIM_TX_2   = 129,
+	SLIM_TX_3   = 130,
+	SLIM_TX_4   = 131,
+	SLIM_TX_5   = 132,
+	SLIM_TX_6   = 133,
+	SLIM_TX_7   = 134,
+	SLIM_TX_8   = 135,
+	SLIM_TX_9   = 136,
+	SLIM_TX_10  = 137,
+	SLIM_RX_1   = 138,
+	SLIM_RX_2   = 139,
+	SLIM_RX_3   = 140,
+	SLIM_RX_4   = 141,
+	SLIM_RX_5   = 142,
+	SLIM_RX_6   = 143,
+	SLIM_RX_7   = 144,
+	SLIM_MAX    = 145
+};
+
+/*
+ *  client is expected to give port ids in the range of 1-10 for Tx ports and
+ *  1-7 for Rx ports, we need to add offset for getting the absolute slave
+ *  port id before configuring the HW
+ */
+#define SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS 10
+#define SB_PGD_OFFSET_OF_TX_SLAVE_DEV_PORTS     -1
+#define SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS 7
+#define SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS     9
+
+/* below details are taken from SLIMBUS slave SWI */
+#define SB_PGD_PORT_BASE 0x000
+
+#define SB_PGD_PORT_CFG_BYTE_ADDR(port_num) \
+		(SB_PGD_PORT_BASE + 0x040 + 1*port_num)
+
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_0(port_num) \
+		(SB_PGD_PORT_BASE + 0x100 + 4*port_num)
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_0_START_PORT_ID   0
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_0_END_PORT_ID     7
+
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_1(port_num) \
+		(SB_PGD_PORT_BASE + 0x101 + 4*port_num)
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_1_START_PORT_ID   8
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID     9
+
+#define SB_PGD_RX_PORT_MULTI_CHANNEL_0(port_num) \
+		(SB_PGD_PORT_BASE + 0x180 + 4*port_num)
+#define SB_PGD_RX_PORT_MULTI_CHANNEL_0_START_PORT_ID   10
+#define SB_PGD_RX_PORT_MULTI_CHANNEL_0_END_PORT_ID     16
+
+/* slave port water mark level
+ *   (0: 6bytes, 1: 9bytes, 2: 12 bytes, 3: 15 bytes)
+ */
+#define SLAVE_PORT_WATER_MARK_VALUE 2
+#define SLAVE_PORT_WATER_MARK_SHIFT 1
+#define SLAVE_PORT_ENABLE           1
+#define SLAVE_PORT_DISABLE          0
+
+#define BASE_CH_NUM 128
+
+
+int tabla_init_slimslave(struct tabla *tabla, u8 tabla_pgd_la);
+
+int tabla_deinit_slimslave(struct tabla *tabla);
+
+int tabla_cfg_slim_sch_rx(struct tabla *tabla, unsigned int *ch_num,
+				unsigned int tot_ch, unsigned int rate);
+int tabla_cfg_slim_sch_tx(struct tabla *tabla, unsigned int *ch_num,
+				unsigned int tot_ch, unsigned int rate);
+int tabla_close_slim_sch_rx(struct tabla *tabla, unsigned int *ch_num,
+				unsigned int tot_ch);
+int tabla_close_slim_sch_tx(struct tabla *tabla, unsigned int *ch_num,
+				unsigned int tot_ch);
+int tabla_get_channel(struct tabla *tabla,
+			unsigned int *rx_ch,
+			unsigned int *tx_ch);
+#endif /* __WCD9310_SLIMSLAVE_H_ */
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 427465d..07d5af65 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -1,6 +1,7 @@
 /* include/linux/msm_mdp.h
  *
  * Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2012 Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -77,6 +78,7 @@
 	MDP_RGB_565,      /* RGB 565 planer */
 	MDP_XRGB_8888,    /* RGB 888 padded */
 	MDP_Y_CBCR_H2V2,  /* Y and CbCr, pseudo planer w/ Cb is in MSB */
+	MDP_Y_CBCR_H2V2_ADRENO,
 	MDP_ARGB_8888,    /* ARGB 888 */
 	MDP_RGB_888,      /* RGB 888 planer */
 	MDP_Y_CRCB_H2V2,  /* Y and CrCb, pseudo planer w/ Cr is in MSB */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 2cbe6ce..037cfe7 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -164,6 +164,7 @@
  * @enable_dcd: Enable Data Contact Detection circuit. if not set
  *              wait for 600msec before proceeding to primary
  *              detection.
+ * @bus_scale_table: parameters for bus bandwidth requirements
  */
 struct msm_otg_platform_data {
 	int *phy_init_seq;
@@ -179,6 +180,7 @@
 	bool disable_reset_on_disconnect;
 	u32 swfi_latency;
 	bool enable_dcd;
+	struct msm_bus_scale_pdata *bus_scale_table;
 };
 
 /**
@@ -211,6 +213,7 @@
 	collapse when cable is connected.
  * @id_timer: The timer used for polling ID line to detect ACA states.
  * @xo_handle: TCXO buffer handle
+ * @bus_perf_client: Bus performance client handle to request BUS bandwidth
  */
 struct msm_otg {
 	struct otg_transceiver otg;
@@ -241,6 +244,7 @@
 	struct timer_list id_timer;
 	unsigned long caps;
 	struct clk *xo_handle;
+	uint32_t bus_perf_client;
 	/*
 	 * Allowing PHY power collpase turns off the HSUSB 3.3v and 1.8v
 	 * analog regulators while going to low power mode.
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index c97c664..9759b32 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -42,6 +42,7 @@
 				enum wcnss_opcode opcode);
 int req_riva_power_on_lock(char *driver_name);
 int free_riva_power_on_lock(char *driver_name);
+unsigned int wcnss_get_serial_number(void);
 #define wcnss_wlan_get_drvdata(dev) dev_get_drvdata(dev)
 #define wcnss_wlan_set_drvdata(dev, data) dev_set_drvdata((dev), (data))
 
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 8d2852b..87fbbd2 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -217,7 +217,8 @@
 #define PP_SNAP  0x01
 #define PP_RAW_SNAP ((0x01)<<1)
 #define PP_PREV  ((0x01)<<2)
-#define PP_MASK		(PP_SNAP|PP_RAW_SNAP|PP_PREV)
+#define PP_THUMB ((0x01)<<3)
+#define PP_MASK		(PP_SNAP|PP_RAW_SNAP|PP_PREV|PP_THUMB)
 
 #define MSM_CAM_CTRL_CMD_DONE  0
 #define MSM_CAM_SENSOR_VFE_CMD 1
@@ -295,6 +296,7 @@
 		struct msm_pp_frame_sp sp;
 		struct msm_pp_frame_mp mp[MAX_PLANES];
 	};
+	int node_type;
 };
 
 struct msm_cam_evt_divert_frame {
@@ -509,6 +511,9 @@
 	uint32_t window_height_lastline;
 };
 
+#define VIDEO_NODE 0
+#define MCTL_NODE 1
+
 #define OUTPUT_1	0
 #define OUTPUT_2	1
 #define OUTPUT_1_AND_2            2   /* snapshot only */
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 7caafb6..5dd1445 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -58,6 +58,7 @@
 #define MSG_ID_STATS_AWB_AEC            39
 #define MSG_ID_OUTPUT_PRIMARY           40
 #define MSG_ID_OUTPUT_SECONDARY         41
+#define MSG_ID_STATS_COMPOSITE          42
 
 /* ISP command IDs */
 #define VFE_CMD_DUMMY_0                                 0
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 30f1a7c..097ba39 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -234,10 +234,18 @@
 				/* HDMI_5Point1 (6-ch) = 2 */
 				/* HDMI_6Point1 (8-ch) = 3 */
 	u16	data_type;	/* HDMI_Linear = 0 */
-				/* HDMI_non_Linaer = 1 */
+				/* HDMI_non_Linear = 1 */
 } __attribute__ ((packed));
 
 
+struct afe_port_hdmi_multi_ch_cfg {
+	u16	data_type;		/* HDMI_Linear = 0 */
+					/* HDMI_non_Linear = 1 */
+	u16	channel_allocation;	/* The default is 0 (Stereo) */
+	u16	reserved;		/* must be set to 0 */
+} __packed;
+
+
 /* Slimbus Device Ids */
 #define AFE_SLIMBUS_DEVICE_1		0x0
 #define AFE_SLIMBUS_DEVICE_2		0x1
@@ -264,6 +272,16 @@
 	u16	reserved;
 } __packed;
 
+struct afe_port_slimbus_sch_cfg {
+	u16	slimbus_dev_id;		/* SLIMBUS Device id.*/
+	u16	bit_width;		/**  bit width of the samples, 16, 24.*/
+	u16	data_format;		/** data format.*/
+	u16	num_channels;		/** Number of channels.*/
+	u16	reserved;
+	/** Slave channel  mapping for respective channels.*/
+	u8	slave_ch_mapping[8];
+} __packed;
+
 struct afe_port_rtproxy_cfg {
 	u16	bitwidth;	/* 16,24,32 */
 	u16	interleaved;    /* interleaved = 1 */
@@ -277,13 +295,17 @@
 } __packed;
 
 #define AFE_PORT_AUDIO_IF_CONFIG 0x000100d3
+#define AFE_PORT_AUDIO_SLIM_SCH_CONFIG 0x000100e4
+#define AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG	0x000100D9
 
 union afe_port_config {
-	struct afe_port_pcm_cfg         pcm;
-	struct afe_port_mi2s_cfg        mi2s;
-	struct afe_port_hdmi_cfg        hdmi;
-	struct afe_port_slimbus_cfg	slimbus;
-	struct afe_port_rtproxy_cfg     rtproxy;
+	struct afe_port_pcm_cfg           pcm;
+	struct afe_port_mi2s_cfg          mi2s;
+	struct afe_port_hdmi_cfg          hdmi;
+	struct afe_port_hdmi_multi_ch_cfg hdmi_multi_ch;
+	struct afe_port_slimbus_cfg	  slimbus;
+	struct afe_port_slimbus_sch_cfg	  slim_sch;
+	struct afe_port_rtproxy_cfg       rtproxy;
 } __attribute__((packed));
 
 struct afe_audioif_config_command {
@@ -482,6 +504,20 @@
 
 #define ADM_CMD_COPP_CLOSE                               0x00010305
 
+#define ADM_CMD_MULTI_CHANNEL_COPP_OPEN                  0x00010310
+struct adm_multi_ch_copp_open_command {
+	struct apr_hdr hdr;
+	u16 flags;
+	u16 mode; /* 1-RX, 2-Live TX, 3-Non Live TX */
+	u16 endpoint_id1;
+	u16 endpoint_id2;
+	u32 topology_id;
+	u16 channel_config;
+	u16 reserved;
+	u32 rate;
+	u8 dev_channel_mapping[8];
+} __packed;
+
 #define ADM_CMD_MEMORY_MAP				0x00010C30
 struct adm_cmd_memory_map{
 	struct apr_hdr	hdr;
@@ -635,6 +671,9 @@
 	u16 reserved;
 } __attribute__ ((packed));
 
+#define ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN               0x00010311
+
+
 #define ASM_STREAM_PRIORITY_NORMAL	0
 #define ASM_STREAM_PRIORITY_LOW		1
 #define ASM_STREAM_PRIORITY_HIGH	2
@@ -676,6 +715,125 @@
 	u16 interleaved;
 };
 
+#define PCM_CHANNEL_NULL 0
+
+/* Front left channel. */
+#define PCM_CHANNEL_FL    1
+
+/* Front right channel. */
+#define PCM_CHANNEL_FR    2
+
+/* Front center channel. */
+#define PCM_CHANNEL_FC    3
+
+/* Left surround channel.*/
+#define PCM_CHANNEL_LS   4
+
+/* Right surround channel.*/
+#define PCM_CHANNEL_RS   5
+
+/* Low frequency effect channel. */
+#define PCM_CHANNEL_LFE  6
+
+/* Center surround channel; Rear center channel. */
+#define PCM_CHANNEL_CS   7
+
+/* Left back channel; Rear left channel. */
+#define PCM_CHANNEL_LB   8
+
+/* Right back channel; Rear right channel. */
+#define PCM_CHANNEL_RB   9
+
+/* Top surround channel. */
+#define PCM_CHANNEL_TS   10
+
+/* Center vertical height channel.*/
+#define PCM_CHANNEL_CVH  11
+
+/* Mono surround channel.*/
+#define PCM_CHANNEL_MS   12
+
+/* Front left of center. */
+#define PCM_CHANNEL_FLC  13
+
+/* Front right of center. */
+#define PCM_CHANNEL_FRC  14
+
+/* Rear left of center. */
+#define PCM_CHANNEL_RLC  15
+
+/* Rear right of center. */
+#define PCM_CHANNEL_RRC  16
+
+#define PCM_FORMAT_MAX_NUM_CHANNEL  8
+
+
+/*
+ *  Multiple-channel PCM decoder format block structure used in the
+ *  #ASM_STREAM_CMD_OPEN_WRITE command.
+ *  The data must be in little-endian format.
+ */
+struct asm_multi_channel_pcm_fmt_blk {
+
+	u16 num_channels;	/*
+				 * Number of channels.
+				 * Supported values:1 to 8
+				 */
+
+	u16 bits_per_sample;	/*
+				 * Number of bits per sample per channel.
+				 * Supported values: 16, 24 When used for
+				 * playback, the client must send 24-bit
+				 * samples packed in 32-bit words. The
+				 * 24-bit samples must be placed in the most
+				 * significant 24 bits of the 32-bit word. When
+				 * used for recording, the aDSP sends 24-bit
+				 * samples packed in 32-bit words. The 24-bit
+				 * samples are placed in the most significant
+				 * 24 bits of the 32-bit word.
+				 */
+
+	u32 sample_rate;	/*
+				 * Number of samples per second
+				 * (in Hertz). Supported values:
+				 * 2000 to 48000
+				 */
+
+	u16 is_signed;		/*
+				 * Flag that indicates the samples
+				 * are signed (1).
+				 */
+
+	u16 is_interleaved;	/*
+				 * Flag that indicates whether the channels are
+				 * de-interleaved (0) or interleaved (1).
+				 * Interleaved format means corresponding
+				 * samples from the left and right channels are
+				 * interleaved within the buffer.
+				 * De-interleaved format means samples from
+				 * each channel are contiguous in the buffer.
+				 * The samples from one channel immediately
+				 * follow those of the previous channel.
+				 */
+
+	u8 channel_mapping[8];	/*
+				 * Supported values:
+				 * PCM_CHANNEL_NULL, PCM_CHANNEL_FL,
+				 * PCM_CHANNEL_FR, PCM_CHANNEL_FC,
+				 * PCM_CHANNEL_LS, PCM_CHANNEL_RS,
+				 * PCM_CHANNEL_LFE, PCM_CHANNEL_CS,
+				 * PCM_CHANNEL_LB, PCM_CHANNEL_RB,
+				 * PCM_CHANNEL_TS, PCM_CHANNEL_CVH,
+				 * PCM_CHANNEL_MS, PCM_CHANNEL_FLC,
+				 * PCM_CHANNEL_FRC, PCM_CHANNEL_RLC,
+				 * PCM_CHANNEL_RRC.
+				 * Channel[i] mapping describes channel I. Each
+				 * element i of the array describes channel I
+				 * inside the buffer where  I < num_channels.
+				 * An unused channel is set to zero.
+				 */
+};
+
 struct asm_adpcm_cfg {
 	u16 ch_cfg;
 	u16 bits_per_sample;
@@ -878,6 +1036,7 @@
 #define MPEG4_MULTI_AAC 0x00010D86
 #define US_POINT_EPOS_FORMAT 0x00012310
 #define US_RAW_FORMAT        0x0001127C
+#define MULTI_CHANNEL_PCM    0x00010C66
 
 #define ASM_ENCDEC_SBCRATE         0x00010C13
 #define ASM_ENCDEC_IMMDIATE_DECODE 0x00010C14
@@ -1059,6 +1218,7 @@
 		struct asm_aac_cfg         aac_cfg;
 		struct asm_flac_cfg        flac_cfg;
 		struct asm_vorbis_cfg      vorbis_cfg;
+		struct asm_multi_channel_pcm_fmt_blk multi_ch_pcm_cfg;
 	} __attribute__((packed)) write_cfg;
 } __attribute__((packed));
 
diff --git a/include/sound/q6adm.h b/include/sound/q6adm.h
index 80374c5..fe25d22 100644
--- a/include/sound/q6adm.h
+++ b/include/sound/q6adm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,9 @@
 
 int adm_open(int port, int path, int rate, int mode, int topology);
 
+int adm_multi_ch_copp_open(int port, int path, int rate, int mode,
+				int topology);
+
 int adm_memory_map_regions(uint32_t *buf_add, uint32_t mempool_id,
 				uint32_t *bufsz, uint32_t bufcnt);
 
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index 16439e8..d08f528 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,6 +39,7 @@
 #define FORMAT_WMA_V9	    0x000f
 #define FORMAT_AMR_WB_PLUS  0x0010
 #define FORMAT_MPEG4_MULTI_AAC 0x0011
+#define FORMAT_MULTI_CHANNEL_LINEAR_PCM 0x0012
 
 #define ENCDEC_SBCBITRATE   0x0001
 #define ENCDEC_IMMEDIATE_DECODE 0x0002
@@ -244,6 +245,9 @@
 int q6asm_media_format_block_pcm(struct audio_client *ac,
 			uint32_t rate, uint32_t channels);
 
+int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
+				uint32_t rate, uint32_t channels);
+
 int q6asm_media_format_block_aac(struct audio_client *ac,
 			struct asm_aac_cfg *cfg);
 
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index bda171e..f1ce01f 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -2,6 +2,7 @@
  * linux/sound/soc-dai.h -- ALSA SoC Layer
  *
  * Copyright:	2005-2008 Wolfson Microelectronics. PLC.
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -121,6 +122,10 @@
 	unsigned int tx_num, unsigned int *tx_slot,
 	unsigned int rx_num, unsigned int *rx_slot);
 
+int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai,
+	unsigned int *tx_num, unsigned int *tx_slot,
+	unsigned int *rx_num, unsigned int *rx_slot);
+
 int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
 
 /* Digital Audio Interface mute */
@@ -150,6 +155,9 @@
 		unsigned int rx_num, unsigned int *rx_slot);
 	int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
 
+	int (*get_channel_map)(struct snd_soc_dai *dai,
+		unsigned int *tx_num, unsigned int *tx_slot,
+		unsigned int *rx_num, unsigned int *rx_slot);
 	/*
 	 * DAI digital mute - optional.
 	 * Called by soc-core to minimise any pops.
diff --git a/kernel/printk.c b/kernel/printk.c
index dbaa948..3c31395 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -41,7 +41,7 @@
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 #include <linux/rculist.h>
-
+#include <mach/msm_rtb.h>
 #include <asm/uaccess.h>
 
 /*
@@ -784,6 +784,11 @@
 {
 	va_list args;
 	int r;
+#ifdef CONFIG_MSM_RTB
+	void *caller = __builtin_return_address(0);
+
+	uncached_logk_pc(LOGK_LOGBUF, caller, (void *)log_end);
+#endif
 
 #ifdef CONFIG_KGDB_KDB
 	if (unlikely(kdb_trap_printk)) {
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index e56fe35..b3b122f 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -686,6 +686,14 @@
 
 	bdi_unregister(bdi);
 
+	/*
+	 * If bdi_unregister() had already been called earlier, the
+	 * wakeup_timer could still be armed because bdi_prune_sb()
+	 * can race with the bdi_wakeup_thread_delayed() calls from
+	 * __mark_inode_dirty().
+	 */
+	del_timer_sync(&bdi->wb.wakeup_timer);
+
 	for (i = 0; i < NR_BDI_STAT_ITEMS; i++)
 		percpu_counter_destroy(&bdi->bdi_stat[i]);
 
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index f0f2ac1..899c538 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -65,7 +65,7 @@
 	cp.peer_addr_type = conn->dst_type;
 	cp.conn_interval_min = cpu_to_le16(0x0008);
 	cp.conn_interval_max = cpu_to_le16(0x0100);
-	cp.supervision_timeout = cpu_to_le16(0x0064);
+	cp.supervision_timeout = cpu_to_le16(1000);
 	cp.min_ce_len = cpu_to_le16(0x0001);
 	cp.max_ce_len = cpu_to_le16(0x0001);
 
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index ded74dc..b4dde4c 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -7440,11 +7440,12 @@
 		BT_DBG("sk->scid %d", l2cap_pi(sk)->scid);
 
 		if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
-			if (!status && encrypt)
+			if (!status && encrypt) {
 				l2cap_pi(sk)->sec_level = hcon->sec_level;
+				l2cap_chan_ready(sk);
+			}
 
 			del_timer(&hcon->smp_timer);
-			l2cap_chan_ready(sk);
 			smp_link_encrypt_cmplt(conn, status, encrypt);
 
 			bh_unlock_sock(sk);
diff --git a/scripts/gcc-wrapper.py b/scripts/gcc-wrapper.py
index 65744e1..0104f1a 100755
--- a/scripts/gcc-wrapper.py
+++ b/scripts/gcc-wrapper.py
@@ -57,8 +57,34 @@
     "inode.c:74",
     "msm_sdcc.c:126",
     "msm_sdcc.c:128",
+    "nf_conntrack_core.c:1579",
+    "nf_conntrack_core.c:1580",
     "nf_conntrack_netlink.c:790",
+    "nf_conntrack_proto.c:210",
+    "nf_conntrack_proto.c:345",
+    "nf_conntrack_proto.c:370",
+    "nf_nat_core.c:528",
+    "nf_nat_core.c:739",
+    "nf_nat_core.c:740",
+    "nf_nat_core.c:741",
+    "nf_nat_core.c:742",
+    "nf_nat_core.c:751",
+    "nf_nat_core.c:753",
+    "nf_nat_core.c:756",
+    "nf_nat_ftp.c:123",
+    "nf_nat_pptp.c:285",
+    "nf_nat_pptp.c:288",
+    "nf_nat_pptp.c:291",
+    "nf_nat_pptp.c:294",
+    "nf_nat_sip.c:550",
+    "nf_nat_sip.c:551",
+    "nf_nat_sip.c:552",
+    "nf_nat_sip.c:553",
+    "nf_nat_sip.c:555",
+    "nf_nat_sip.c:556",
+    "nf_nat_sip.c:554",
     "nf_nat_standalone.c:118",
+    "nf_nat_tftp.c:46",
     "return_address.c:62",
     "sch_generic.c:678",
     "soc-core.c:1719",
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index d4e9ecf..deb13dc 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -36,8 +36,6 @@
 #define NUM_DECIMATORS 10
 #define NUM_INTERPOLATORS 7
 #define BITS_PER_REG 8
-#define TABLA_RX_DAI_ID 1
-#define TABLA_TX_DAI_ID 2
 #define TABLA_CFILT_FAST_MODE 0x00
 #define TABLA_CFILT_SLOW_MODE 0x40
 #define MBHC_FW_READ_ATTEMPTS 15
@@ -49,6 +47,17 @@
 
 #define TABLA_OCP_ATTEMPT 1
 
+#define AIF1_PB 1
+#define AIF1_CAP 2
+#define NUM_CODEC_DAIS 2
+
+struct tabla_codec_dai_data {
+	u32 rate;
+	u32 *ch_num;
+	u32 ch_act;
+	u32 ch_tot;
+};
+
 #define TABLA_MCLK_RATE_12288KHZ 12288000
 #define TABLA_MCLK_RATE_9600KHZ 9600000
 
@@ -58,6 +67,7 @@
 static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
 static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
 static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
+static struct snd_soc_dai_driver tabla_dai[];
 
 enum tabla_bandgap_type {
 	TABLA_BANDGAP_OFF = 0,
@@ -185,11 +195,6 @@
 	struct work_struct hphlocp_work; /* reporting left hph ocp off */
 	struct work_struct hphrocp_work; /* reporting right hph ocp off */
 
-	/* pm_cnt holds number of sleep lock holders + 1
-	 * so if pm_cnt is 1 system is sleep-able. */
-	atomic_t pm_cnt;
-	wait_queue_head_t pm_wq;
-
 	u8 hphlocp_cnt; /* headphone left ocp retry */
 	u8 hphrocp_cnt; /* headphone right ocp retry */
 
@@ -199,6 +204,9 @@
 	/* Work to perform MBHC Firmware Read */
 	struct delayed_work mbhc_firmware_dwork;
 	const struct firmware *mbhc_fw;
+
+	/* num of slim ports required */
+	struct tabla_codec_dai_data dai[NUM_CODEC_DAIS];
 };
 
 #ifdef CONFIG_DEBUG_FS
@@ -1912,306 +1920,6 @@
 	return 0;
 }
 
-static const struct snd_soc_dapm_widget tabla_dapm_widgets[] = {
-	/*RX stuff */
-	SND_SOC_DAPM_OUTPUT("EAR"),
-
-	SND_SOC_DAPM_PGA("EAR PA", TABLA_A_RX_EAR_EN, 4, 0, NULL, 0),
-
-	SND_SOC_DAPM_MIXER("DAC1", TABLA_A_RX_EAR_EN, 6, 0, dac1_switch,
-		ARRAY_SIZE(dac1_switch)),
-
-	SND_SOC_DAPM_AIF_IN("SLIM RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
-	SND_SOC_DAPM_AIF_IN("SLIM RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
-	SND_SOC_DAPM_AIF_IN("SLIM RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
-	SND_SOC_DAPM_AIF_IN("SLIM RX4", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
-
-	/* Headphone */
-	SND_SOC_DAPM_OUTPUT("HEADPHONE"),
-	SND_SOC_DAPM_PGA_E("HPHL", TABLA_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
-		tabla_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
-			SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MIXER("HPHL DAC", TABLA_A_RX_HPH_L_DAC_CTL, 7, 0,
-		hphl_switch, ARRAY_SIZE(hphl_switch)),
-
-	SND_SOC_DAPM_PGA_E("HPHR", TABLA_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
-		tabla_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
-			SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TABLA_A_RX_HPH_R_DAC_CTL, 7, 0,
-		tabla_hphr_dac_event,
-		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-
-	/* Speaker */
-	SND_SOC_DAPM_OUTPUT("LINEOUT1"),
-	SND_SOC_DAPM_OUTPUT("LINEOUT2"),
-	SND_SOC_DAPM_OUTPUT("LINEOUT3"),
-	SND_SOC_DAPM_OUTPUT("LINEOUT4"),
-	SND_SOC_DAPM_OUTPUT("LINEOUT5"),
-
-	SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TABLA_A_RX_LINE_CNP_EN, 0, 0, NULL,
-			0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
-			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TABLA_A_RX_LINE_CNP_EN, 1, 0, NULL,
-			0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
-			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_PGA_E("LINEOUT3 PA", TABLA_A_RX_LINE_CNP_EN, 2, 0, NULL,
-			0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
-			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_PGA_E("LINEOUT4 PA", TABLA_A_RX_LINE_CNP_EN, 3, 0, NULL,
-			0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
-			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_PGA_E("LINEOUT5 PA", TABLA_A_RX_LINE_CNP_EN, 4, 0, NULL, 0,
-		tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TABLA_A_RX_LINE_1_DAC_CTL, 7, 0
-		, tabla_lineout_dac_event,
-		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TABLA_A_RX_LINE_2_DAC_CTL, 7, 0
-		, tabla_lineout_dac_event,
-		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_DAC_E("LINEOUT3 DAC", NULL, TABLA_A_RX_LINE_3_DAC_CTL, 7, 0
-		, tabla_lineout_dac_event,
-		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_SWITCH("LINEOUT3 DAC GROUND", SND_SOC_NOPM, 0, 0,
-				&lineout3_ground_switch),
-	SND_SOC_DAPM_DAC_E("LINEOUT4 DAC", NULL, TABLA_A_RX_LINE_4_DAC_CTL, 7, 0
-		, tabla_lineout_dac_event,
-		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_SWITCH("LINEOUT4 DAC GROUND", SND_SOC_NOPM, 0, 0,
-				&lineout4_ground_switch),
-	SND_SOC_DAPM_DAC_E("LINEOUT5 DAC", NULL, TABLA_A_RX_LINE_5_DAC_CTL, 7, 0
-		, tabla_lineout_dac_event,
-		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_MIXER_E("RX1 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
-		0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
-	SND_SOC_DAPM_MIXER_E("RX2 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
-		0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
-	SND_SOC_DAPM_MIXER_E("RX3 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
-		0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
-	SND_SOC_DAPM_MIXER_E("RX4 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
-		0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
-	SND_SOC_DAPM_MIXER_E("RX5 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
-		0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
-	SND_SOC_DAPM_MIXER_E("RX6 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL,
-		0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
-	SND_SOC_DAPM_MIXER_E("RX7 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
-		0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
-
-
-	SND_SOC_DAPM_MUX_E("RX4 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0,
-		&rx4_dsm_mux, tabla_codec_reset_interpolator,
-		SND_SOC_DAPM_PRE_PMU),
-
-	SND_SOC_DAPM_MUX_E("RX6 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0,
-		&rx6_dsm_mux, tabla_codec_reset_interpolator,
-		SND_SOC_DAPM_PRE_PMU),
-
-	SND_SOC_DAPM_MIXER("RX1 CHAIN", TABLA_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
-	SND_SOC_DAPM_MIXER("RX2 CHAIN", TABLA_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
-
-	SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
-		&rx_mix1_inp1_mux),
-	SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
-		&rx_mix1_inp2_mux),
-	SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
-		&rx2_mix1_inp1_mux),
-	SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
-		&rx2_mix1_inp2_mux),
-	SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
-		&rx3_mix1_inp1_mux),
-	SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
-		&rx3_mix1_inp2_mux),
-	SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
-		&rx4_mix1_inp1_mux),
-	SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
-		&rx4_mix1_inp2_mux),
-	SND_SOC_DAPM_MUX("RX5 MIX1 INP1", SND_SOC_NOPM, 0, 0,
-		&rx5_mix1_inp1_mux),
-	SND_SOC_DAPM_MUX("RX5 MIX1 INP2", SND_SOC_NOPM, 0, 0,
-		&rx5_mix1_inp2_mux),
-	SND_SOC_DAPM_MUX("RX6 MIX1 INP1", SND_SOC_NOPM, 0, 0,
-		&rx6_mix1_inp1_mux),
-	SND_SOC_DAPM_MUX("RX6 MIX1 INP2", SND_SOC_NOPM, 0, 0,
-		&rx6_mix1_inp2_mux),
-	SND_SOC_DAPM_MUX("RX7 MIX1 INP1", SND_SOC_NOPM, 0, 0,
-		&rx7_mix1_inp1_mux),
-	SND_SOC_DAPM_MUX("RX7 MIX1 INP2", SND_SOC_NOPM, 0, 0,
-		&rx7_mix1_inp2_mux),
-
-	SND_SOC_DAPM_SUPPLY("CP", TABLA_A_CP_EN, 0, 0,
-		tabla_codec_enable_charge_pump, SND_SOC_DAPM_POST_PMU |
-		SND_SOC_DAPM_PRE_PMD),
-
-	SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
-		tabla_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMD),
-
-	/* TX */
-
-	SND_SOC_DAPM_SUPPLY("CDC_CONN", TABLA_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
-		0),
-
-	SND_SOC_DAPM_SUPPLY("LDO_H", TABLA_A_LDO_H_MODE_1, 7, 0,
-		tabla_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
-
-	SND_SOC_DAPM_INPUT("AMIC1"),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TABLA_A_MICB_1_CTL, 7, 0,
-		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TABLA_A_MICB_1_CTL, 7, 0,
-		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TABLA_A_MICB_1_CTL, 7, 0,
-		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_ADC_E("ADC1", NULL, TABLA_A_TX_1_2_EN, 7, 0,
-		tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_INPUT("AMIC3"),
-	SND_SOC_DAPM_ADC_E("ADC3", NULL, TABLA_A_TX_3_4_EN, 7, 0,
-		tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_INPUT("AMIC4"),
-	SND_SOC_DAPM_ADC_E("ADC4", NULL, TABLA_A_TX_3_4_EN, 3, 0,
-		tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_INPUT("AMIC5"),
-	SND_SOC_DAPM_ADC_E("ADC5", NULL, TABLA_A_TX_5_6_EN, 7, 0,
-		tabla_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
-
-	SND_SOC_DAPM_INPUT("AMIC6"),
-	SND_SOC_DAPM_ADC_E("ADC6", NULL, TABLA_A_TX_5_6_EN, 3, 0,
-		tabla_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
-
-	SND_SOC_DAPM_MUX_E("DEC1 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
-		&dec1_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
-	SND_SOC_DAPM_MUX_E("DEC2 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
-		&dec2_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
-	SND_SOC_DAPM_MUX_E("DEC3 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
-		&dec3_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
-	SND_SOC_DAPM_MUX_E("DEC4 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
-		&dec4_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
-	SND_SOC_DAPM_MUX_E("DEC5 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 4, 0,
-		&dec5_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
-	SND_SOC_DAPM_MUX_E("DEC6 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 5, 0,
-		&dec6_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
-	SND_SOC_DAPM_MUX_E("DEC7 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 6, 0,
-		&dec7_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
-	SND_SOC_DAPM_MUX_E("DEC8 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 7, 0,
-		&dec8_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
-	SND_SOC_DAPM_MUX_E("DEC9 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0, 0,
-		&dec9_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
-	SND_SOC_DAPM_MUX_E("DEC10 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL, 1, 0,
-		&dec10_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
-	SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
-	SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
-
-	SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
-		tabla_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
-
-	SND_SOC_DAPM_INPUT("AMIC2"),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TABLA_A_MICB_2_CTL, 7, 0,
-		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU |	SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", TABLA_A_MICB_2_CTL, 7, 0,
-		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", TABLA_A_MICB_2_CTL, 7, 0,
-		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", TABLA_A_MICB_2_CTL, 7, 0,
-		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TABLA_A_MICB_3_CTL, 7, 0,
-		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TABLA_A_MICB_3_CTL, 7, 0,
-		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TABLA_A_MICB_3_CTL, 7, 0,
-		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_ADC_E("ADC2", NULL, TABLA_A_TX_1_2_EN, 3, 0,
-		tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, 0, 0, &sb_tx1_mux),
-	SND_SOC_DAPM_AIF_OUT("SLIM TX1", "AIF1 Capture", NULL, SND_SOC_NOPM,
-			0, 0),
-
-	SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, 0, 0, &sb_tx5_mux),
-	SND_SOC_DAPM_AIF_OUT("SLIM TX5", "AIF1 Capture", NULL, SND_SOC_NOPM,
-			4, 0),
-
-	SND_SOC_DAPM_MUX("SLIM TX6 MUX", SND_SOC_NOPM, 0, 0, &sb_tx6_mux),
-	SND_SOC_DAPM_AIF_OUT("SLIM TX6", "AIF1 Capture", NULL, SND_SOC_NOPM,
-			5, 0),
-
-	SND_SOC_DAPM_MUX("SLIM TX7 MUX", SND_SOC_NOPM, 0, 0, &sb_tx7_mux),
-	SND_SOC_DAPM_AIF_OUT("SLIM TX7", "AIF1 Capture", NULL, SND_SOC_NOPM,
-			0, 0),
-
-	SND_SOC_DAPM_MUX("SLIM TX8 MUX", SND_SOC_NOPM, 0, 0, &sb_tx8_mux),
-	SND_SOC_DAPM_AIF_OUT("SLIM TX8", "AIF1 Capture", NULL, SND_SOC_NOPM,
-			0, 0),
-
-	SND_SOC_DAPM_MUX("SLIM TX9 MUX", SND_SOC_NOPM, 0, 0, &sb_tx9_mux),
-	SND_SOC_DAPM_AIF_OUT("SLIM TX9", "AIF1 Capture", NULL, SND_SOC_NOPM,
-			0, 0),
-
-	SND_SOC_DAPM_MUX("SLIM TX10 MUX", SND_SOC_NOPM, 0, 0, &sb_tx10_mux),
-	SND_SOC_DAPM_AIF_OUT("SLIM TX10", "AIF1 Capture", NULL, SND_SOC_NOPM,
-			0, 0),
-
-	/* Digital Mic Inputs */
-	SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
-		tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
-		tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
-		tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
-		tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
-		tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 0, 0,
-		tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMD),
-
-	/* Sidetone */
-	SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
-	SND_SOC_DAPM_PGA("IIR1", TABLA_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
-};
-
 static const struct snd_soc_dapm_widget tabla_1_x_dapm_widgets[] = {
 	SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", TABLA_1_A_MICB_4_CTL, 7,
 			       0, tabla_codec_enable_micbias,
@@ -2680,7 +2388,6 @@
 {
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
 
-	pr_debug("%s: enable = %d\n", __func__, enable);
 	if (enable) {
 		snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x10, 0);
 		snd_soc_write(codec, TABLA_A_BIAS_CONFIG_MODE_BG_CTL, 0x17);
@@ -2885,11 +2592,11 @@
 	case SND_SOC_DAIFMT_CBS_CFS:
 		/* CPU is master */
 		if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
-			if (dai->id == TABLA_TX_DAI_ID)
+			if (dai->id == AIF1_CAP)
 				snd_soc_update_bits(dai->codec,
 					TABLA_A_CDC_CLK_TX_I2S_CTL,
 					TABLA_I2S_MASTER_MODE_MASK, 0);
-			else if (dai->id == TABLA_RX_DAI_ID)
+			else if (dai->id == AIF1_PB)
 				snd_soc_update_bits(dai->codec,
 					TABLA_A_CDC_CLK_RX_I2S_CTL,
 					TABLA_I2S_MASTER_MODE_MASK, 0);
@@ -2899,10 +2606,10 @@
 	/* CPU is slave */
 		if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
 			val = TABLA_I2S_MASTER_MODE_MASK;
-			if (dai->id == TABLA_TX_DAI_ID)
+			if (dai->id == AIF1_CAP)
 				snd_soc_update_bits(dai->codec,
 					TABLA_A_CDC_CLK_TX_I2S_CTL, val, val);
-			else if (dai->id == TABLA_RX_DAI_ID)
+			else if (dai->id == AIF1_PB)
 				snd_soc_update_bits(dai->codec,
 					TABLA_A_CDC_CLK_RX_I2S_CTL, val, val);
 		}
@@ -2913,6 +2620,71 @@
 	return 0;
 }
 
+static int tabla_set_channel_map(struct snd_soc_dai *dai,
+				unsigned int tx_num, unsigned int *tx_slot,
+				unsigned int rx_num, unsigned int *rx_slot)
+
+{
+	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(dai->codec);
+	u32 i = 0;
+	if (!tx_slot && !rx_slot) {
+		pr_err("%s: Invalid\n", __func__);
+		return -EINVAL;
+	}
+	pr_debug("%s: DAI-ID %x %d %d\n", __func__, dai->id, tx_num, rx_num);
+
+	if (dai->id == AIF1_PB) {
+		for (i = 0; i < rx_num; i++) {
+			tabla->dai[dai->id - 1].ch_num[i]  = rx_slot[i];
+			tabla->dai[dai->id - 1].ch_act = 0;
+			tabla->dai[dai->id - 1].ch_tot = rx_num;
+		}
+	} else if (dai->id == AIF1_CAP) {
+		for (i = 0; i < tx_num; i++) {
+			tabla->dai[dai->id - 1].ch_num[i]  = tx_slot[i];
+			tabla->dai[dai->id - 1].ch_act = 0;
+			tabla->dai[dai->id - 1].ch_tot = tx_num;
+		}
+	}
+	return 0;
+}
+
+static int tabla_get_channel_map(struct snd_soc_dai *dai,
+				unsigned int *tx_num, unsigned int *tx_slot,
+				unsigned int *rx_num, unsigned int *rx_slot)
+
+{
+	struct tabla *tabla = dev_get_drvdata(dai->codec->control_data);
+
+	u32 cnt = 0;
+	u32 tx_ch[SLIM_MAX_TX_PORTS];
+	u32 rx_ch[SLIM_MAX_RX_PORTS];
+
+	if (!rx_slot && !tx_slot) {
+		pr_err("%s: Invalid\n", __func__);
+		return -EINVAL;
+	}
+	pr_debug("%s: DAI-ID %x\n", __func__, dai->id);
+	/* for virtual port, codec driver needs to do
+	 * housekeeping, for now should be ok
+	 */
+	tabla_get_channel(tabla, rx_ch, tx_ch);
+	if (dai->id == AIF1_PB) {
+		*rx_num = tabla_dai[dai->id - 1].playback.channels_max;
+		while (cnt < *rx_num) {
+			rx_slot[cnt] = rx_ch[cnt];
+			cnt++;
+		}
+	} else if (dai->id == AIF1_CAP) {
+		*tx_num = tabla_dai[dai->id - 1].capture.channels_max;
+		while (cnt < *tx_num) {
+			tx_slot[cnt] = tx_ch[6 + cnt];
+			cnt++;
+		}
+	}
+	return 0;
+}
+
 static int tabla_hw_params(struct snd_pcm_substream *substream,
 			    struct snd_pcm_hw_params *params,
 			    struct snd_soc_dai *dai)
@@ -2923,7 +2695,8 @@
 	u16 tx_fs_reg, rx_fs_reg;
 	u8 tx_fs_rate, rx_fs_rate, rx_state, tx_state;
 
-	pr_debug("%s: DAI-ID %x\n", __func__, dai->id);
+	pr_debug("%s: DAI-ID %x rate %d\n", __func__, dai->id,
+						params_rate(params));
 
 	switch (params_rate(params)) {
 	case 8000:
@@ -2953,7 +2726,7 @@
 	 * If current dai is a tx dai, set sample rate to
 	 * all the txfe paths that are currently not active
 	 */
-	if (dai->id == TABLA_TX_DAI_ID) {
+	if (dai->id == AIF1_CAP) {
 
 		tx_state = snd_soc_read(codec,
 				TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL);
@@ -2992,9 +2765,10 @@
 			}
 			snd_soc_update_bits(codec, TABLA_A_CDC_CLK_TX_I2S_CTL,
 						0x03, tx_fs_rate);
+		} else {
+			tabla->dai[dai->id - 1].rate   = params_rate(params);
 		}
 	}
-
 	/**
 	 * TODO: Need to handle case where same RX chain takes 2 or more inputs
 	 * with varying sample rates
@@ -3004,7 +2778,7 @@
 	 * If current dai is a rx dai, set sample rate to
 	 * all the rx paths that are currently not active
 	 */
-	if (dai->id == TABLA_RX_DAI_ID) {
+	if (dai->id == AIF1_PB) {
 
 		rx_state = snd_soc_read(codec,
 			TABLA_A_CDC_CLK_RX_B1_CTL);
@@ -3037,6 +2811,8 @@
 			}
 			snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_I2S_CTL,
 						0x03, (rx_fs_rate >> 0x05));
+		} else {
+			tabla->dai[dai->id - 1].rate   = params_rate(params);
 		}
 	}
 
@@ -3049,12 +2825,14 @@
 	.hw_params = tabla_hw_params,
 	.set_sysclk = tabla_set_dai_sysclk,
 	.set_fmt = tabla_set_dai_fmt,
+	.set_channel_map = tabla_set_channel_map,
+	.get_channel_map = tabla_get_channel_map,
 };
 
 static struct snd_soc_dai_driver tabla_dai[] = {
 	{
 		.name = "tabla_rx1",
-		.id = 1,
+		.id = AIF1_PB,
 		.playback = {
 			.stream_name = "AIF1 Playback",
 			.rates = WCD9310_RATES,
@@ -3062,13 +2840,13 @@
 			.rate_max = 48000,
 			.rate_min = 8000,
 			.channels_min = 1,
-			.channels_max = 4,
+			.channels_max = 2,
 		},
 		.ops = &tabla_dai_ops,
 	},
 	{
 		.name = "tabla_tx1",
-		.id = 2,
+		.id = AIF1_CAP,
 		.capture = {
 			.stream_name = "AIF1 Capture",
 			.rates = WCD9310_RATES,
@@ -3076,7 +2854,7 @@
 			.rate_max = 48000,
 			.rate_min = 8000,
 			.channels_min = 1,
-			.channels_max = 2,
+			.channels_max = 4,
 		},
 		.ops = &tabla_dai_ops,
 	},
@@ -3112,6 +2890,426 @@
 		.ops = &tabla_dai_ops,
 	},
 };
+
+static int tabla_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct tabla *tabla;
+	struct snd_soc_codec *codec = w->codec;
+	struct tabla_priv *tabla_p = snd_soc_codec_get_drvdata(codec);
+	u32  j = 0;
+	u32  ret = 0;
+	codec->control_data = dev_get_drvdata(codec->dev->parent);
+	tabla = codec->control_data;
+	/* Execute the callback only if interface type is slimbus */
+	if (tabla_p->intf_type != TABLA_INTERFACE_TYPE_SLIMBUS)
+		return 0;
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
+			if (tabla_dai[j].id == AIF1_CAP)
+				continue;
+			if (!strncmp(w->sname,
+				tabla_dai[j].playback.stream_name, 13)) {
+				++tabla_p->dai[j].ch_act;
+				break;
+			}
+		}
+		if (tabla_p->dai[j].ch_act == tabla_p->dai[j].ch_tot)
+			ret = tabla_cfg_slim_sch_rx(tabla,
+						tabla_p->dai[j].ch_num,
+						tabla_p->dai[j].ch_tot,
+						tabla_p->dai[j].rate);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
+			if (tabla_dai[j].id == AIF1_CAP)
+				continue;
+			if (!strncmp(w->sname,
+				tabla_dai[j].playback.stream_name, 13)) {
+				--tabla_p->dai[j].ch_act;
+				break;
+			}
+		}
+		if (!tabla_p->dai[j].ch_act) {
+			ret = tabla_close_slim_sch_rx(tabla,
+						tabla_p->dai[j].ch_num,
+						tabla_p->dai[j].ch_tot);
+			tabla_p->dai[j].rate = 0;
+			memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
+						tabla_p->dai[j].ch_tot));
+			tabla_p->dai[j].ch_tot = 0;
+		}
+	}
+	return ret;
+}
+
+static int tabla_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct tabla *tabla;
+	struct snd_soc_codec *codec = w->codec;
+	struct tabla_priv *tabla_p = snd_soc_codec_get_drvdata(codec);
+	/* index to the DAI ID, for now hardcoding */
+	u32  j = 0;
+	u32  ret = 0;
+
+	codec->control_data = dev_get_drvdata(codec->dev->parent);
+	tabla = codec->control_data;
+
+	/* Execute the callback only if interface type is slimbus */
+	if (tabla_p->intf_type != TABLA_INTERFACE_TYPE_SLIMBUS)
+		return 0;
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
+			if (tabla_dai[j].id == AIF1_PB)
+				continue;
+			if (!strncmp(w->sname,
+				tabla_dai[j].capture.stream_name, 13)) {
+				++tabla_p->dai[j].ch_act;
+				break;
+			}
+		}
+		if (tabla_p->dai[j].ch_act == tabla_p->dai[j].ch_tot)
+			ret = tabla_cfg_slim_sch_tx(tabla,
+						tabla_p->dai[j].ch_num,
+						tabla_p->dai[j].ch_tot,
+						tabla_p->dai[j].rate);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
+			if (tabla_dai[j].id == AIF1_PB)
+				continue;
+			if (!strncmp(w->sname,
+				tabla_dai[j].capture.stream_name, 13)) {
+				--tabla_p->dai[j].ch_act;
+				break;
+			}
+		}
+		if (!tabla_p->dai[j].ch_act) {
+			ret = tabla_close_slim_sch_tx(tabla,
+						tabla_p->dai[j].ch_num,
+						tabla_p->dai[j].ch_tot);
+			tabla_p->dai[j].rate = 0;
+			memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
+						tabla_p->dai[j].ch_tot));
+			tabla_p->dai[j].ch_tot = 0;
+		}
+	}
+	return ret;
+}
+
+/* Todo: Have seperate dapm widgets for I2S and Slimbus.
+ * Might Need to have callbacks registered only for slimbus
+ */
+static const struct snd_soc_dapm_widget tabla_dapm_widgets[] = {
+	/*RX stuff */
+	SND_SOC_DAPM_OUTPUT("EAR"),
+
+	SND_SOC_DAPM_PGA("EAR PA", TABLA_A_RX_EAR_EN, 4, 0, NULL, 0),
+
+	SND_SOC_DAPM_MIXER("DAC1", TABLA_A_RX_EAR_EN, 6, 0, dac1_switch,
+		ARRAY_SIZE(dac1_switch)),
+
+	SND_SOC_DAPM_AIF_IN_E("SLIM RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0,
+				0, tabla_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_AIF_IN_E("SLIM RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 0,
+				0, tabla_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_AIF_IN("SLIM RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("SLIM RX4", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+
+	/* Headphone */
+	SND_SOC_DAPM_OUTPUT("HEADPHONE"),
+	SND_SOC_DAPM_PGA_E("HPHL", TABLA_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
+		tabla_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER("HPHL DAC", TABLA_A_RX_HPH_L_DAC_CTL, 7, 0,
+		hphl_switch, ARRAY_SIZE(hphl_switch)),
+
+	SND_SOC_DAPM_PGA_E("HPHR", TABLA_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
+		tabla_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TABLA_A_RX_HPH_R_DAC_CTL, 7, 0,
+		tabla_hphr_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* Speaker */
+	SND_SOC_DAPM_OUTPUT("LINEOUT1"),
+	SND_SOC_DAPM_OUTPUT("LINEOUT2"),
+	SND_SOC_DAPM_OUTPUT("LINEOUT3"),
+	SND_SOC_DAPM_OUTPUT("LINEOUT4"),
+	SND_SOC_DAPM_OUTPUT("LINEOUT5"),
+
+	SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TABLA_A_RX_LINE_CNP_EN, 0, 0, NULL,
+			0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TABLA_A_RX_LINE_CNP_EN, 1, 0, NULL,
+			0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("LINEOUT3 PA", TABLA_A_RX_LINE_CNP_EN, 2, 0, NULL,
+			0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("LINEOUT4 PA", TABLA_A_RX_LINE_CNP_EN, 3, 0, NULL,
+			0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("LINEOUT5 PA", TABLA_A_RX_LINE_CNP_EN, 4, 0, NULL, 0,
+		tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TABLA_A_RX_LINE_1_DAC_CTL, 7, 0
+		, tabla_lineout_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TABLA_A_RX_LINE_2_DAC_CTL, 7, 0
+		, tabla_lineout_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_DAC_E("LINEOUT3 DAC", NULL, TABLA_A_RX_LINE_3_DAC_CTL, 7, 0
+		, tabla_lineout_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SWITCH("LINEOUT3 DAC GROUND", SND_SOC_NOPM, 0, 0,
+				&lineout3_ground_switch),
+	SND_SOC_DAPM_DAC_E("LINEOUT4 DAC", NULL, TABLA_A_RX_LINE_4_DAC_CTL, 7, 0
+		, tabla_lineout_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SWITCH("LINEOUT4 DAC GROUND", SND_SOC_NOPM, 0, 0,
+				&lineout4_ground_switch),
+	SND_SOC_DAPM_DAC_E("LINEOUT5 DAC", NULL, TABLA_A_RX_LINE_5_DAC_CTL, 7, 0
+		, tabla_lineout_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER_E("RX1 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
+		0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_MIXER_E("RX2 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
+		0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_MIXER_E("RX3 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
+		0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_MIXER_E("RX4 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
+		0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_MIXER_E("RX5 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
+		0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_MIXER_E("RX6 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL,
+		0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_MIXER_E("RX7 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
+		0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MUX_E("RX4 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0,
+		&rx4_dsm_mux, tabla_codec_reset_interpolator,
+		SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MUX_E("RX6 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0,
+		&rx6_dsm_mux, tabla_codec_reset_interpolator,
+		SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MIXER("RX1 CHAIN", TABLA_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX2 CHAIN", TABLA_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx2_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx2_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx3_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx3_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx4_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx4_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX5 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx5_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX5 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx5_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX6 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx6_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX6 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx6_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX7 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx7_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX7 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx7_mix1_inp2_mux),
+
+	SND_SOC_DAPM_SUPPLY("CP", TABLA_A_CP_EN, 0, 0,
+		tabla_codec_enable_charge_pump, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
+		tabla_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	/* TX */
+
+	SND_SOC_DAPM_SUPPLY("CDC_CONN", TABLA_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
+		0),
+
+	SND_SOC_DAPM_SUPPLY("LDO_H", TABLA_A_LDO_H_MODE_1, 7, 0,
+		tabla_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_INPUT("AMIC1"),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TABLA_A_MICB_1_CTL, 7, 0,
+		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TABLA_A_MICB_1_CTL, 7, 0,
+		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TABLA_A_MICB_1_CTL, 7, 0,
+		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("ADC1", NULL, TABLA_A_TX_1_2_EN, 7, 0,
+		tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("AMIC3"),
+	SND_SOC_DAPM_ADC_E("ADC3", NULL, TABLA_A_TX_3_4_EN, 7, 0,
+		tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("AMIC4"),
+	SND_SOC_DAPM_ADC_E("ADC4", NULL, TABLA_A_TX_3_4_EN, 3, 0,
+		tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("AMIC5"),
+	SND_SOC_DAPM_ADC_E("ADC5", NULL, TABLA_A_TX_5_6_EN, 7, 0,
+		tabla_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_INPUT("AMIC6"),
+	SND_SOC_DAPM_ADC_E("ADC6", NULL, TABLA_A_TX_5_6_EN, 3, 0,
+		tabla_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_MUX_E("DEC1 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
+		&dec1_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MUX_E("DEC2 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
+		&dec2_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MUX_E("DEC3 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
+		&dec3_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MUX_E("DEC4 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
+		&dec4_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MUX_E("DEC5 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 4, 0,
+		&dec5_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MUX_E("DEC6 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 5, 0,
+		&dec6_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MUX_E("DEC7 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 6, 0,
+		&dec7_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MUX_E("DEC8 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 7, 0,
+		&dec8_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MUX_E("DEC9 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0, 0,
+		&dec9_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MUX_E("DEC10 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL, 1, 0,
+		&dec10_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
+	SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
+
+	SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
+		tabla_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
+
+	SND_SOC_DAPM_INPUT("AMIC2"),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TABLA_A_MICB_2_CTL, 7, 0,
+		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU |	SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", TABLA_A_MICB_2_CTL, 7, 0,
+		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", TABLA_A_MICB_2_CTL, 7, 0,
+		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", TABLA_A_MICB_2_CTL, 7, 0,
+		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TABLA_A_MICB_3_CTL, 7, 0,
+		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TABLA_A_MICB_3_CTL, 7, 0,
+		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TABLA_A_MICB_3_CTL, 7, 0,
+		tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("ADC2", NULL, TABLA_A_TX_1_2_EN, 3, 0,
+		tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, 0, 0, &sb_tx1_mux),
+	SND_SOC_DAPM_AIF_OUT("SLIM TX1", "AIF1 Capture", NULL, SND_SOC_NOPM,
+			0, 0),
+
+	SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, 0, 0, &sb_tx5_mux),
+	SND_SOC_DAPM_AIF_OUT("SLIM TX5", "AIF1 Capture", NULL, SND_SOC_NOPM,
+			4, 0),
+
+	SND_SOC_DAPM_MUX("SLIM TX6 MUX", SND_SOC_NOPM, 0, 0, &sb_tx6_mux),
+	SND_SOC_DAPM_AIF_OUT("SLIM TX6", "AIF1 Capture", NULL, SND_SOC_NOPM,
+			5, 0),
+
+	SND_SOC_DAPM_MUX("SLIM TX7 MUX", SND_SOC_NOPM, 0, 0, &sb_tx7_mux),
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX7", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+				0, tabla_codec_enable_slimtx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("SLIM TX8 MUX", SND_SOC_NOPM, 0, 0, &sb_tx8_mux),
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX8", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+				0, tabla_codec_enable_slimtx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("SLIM TX9 MUX", SND_SOC_NOPM, 0, 0, &sb_tx9_mux),
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX9", "AIF1 Capture", NULL, SND_SOC_NOPM,
+			0, 0, tabla_codec_enable_slimtx,
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("SLIM TX10 MUX", SND_SOC_NOPM, 0, 0, &sb_tx10_mux),
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX10", "AIF1 Capture", NULL, SND_SOC_NOPM,
+			0, 0, tabla_codec_enable_slimtx,
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* Digital Mic Inputs */
+	SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+		tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+		tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+		tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+		tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
+		tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 0, 0,
+		tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	/* Sidetone */
+	SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
+	SND_SOC_DAPM_PGA("IIR1", TABLA_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
+};
+
 static short tabla_codec_read_sta_result(struct snd_soc_codec *codec)
 {
 	u8 bias_msb, bias_lsb;
@@ -3331,24 +3529,6 @@
 	return 0;
 }
 
-static void tabla_lock_sleep(struct tabla_priv *tabla)
-{
-	int ret;
-	while (!(ret = wait_event_timeout(tabla->pm_wq,
-					  atomic_inc_not_zero(&tabla->pm_cnt),
-					  2 * HZ))) {
-		pr_err("%s: didn't wake up for 2000ms (%d), pm_cnt %d\n",
-		       __func__, ret, atomic_read(&tabla->pm_cnt));
-		WARN_ON_ONCE(1);
-	}
-}
-
-static void tabla_unlock_sleep(struct tabla_priv *tabla)
-{
-	atomic_dec(&tabla->pm_cnt);
-	wake_up(&tabla->pm_wq);
-}
-
 static u16 tabla_codec_v_sta_dce(struct snd_soc_codec *codec, bool dce,
 				 s16 vin_mv)
 {
@@ -3403,11 +3583,13 @@
 	struct tabla_priv *tabla;
 	short bias_value;
 	int dce_mv, sta_mv;
+	struct tabla *core;
 
 	pr_debug("%s:\n", __func__);
 
 	delayed_work = to_delayed_work(work);
 	tabla = container_of(delayed_work, struct tabla_priv, btn0_dwork);
+	core = dev_get_drvdata(tabla->codec->dev->parent);
 
 	if (tabla) {
 		if (tabla->button_jack) {
@@ -3428,7 +3610,7 @@
 		pr_err("%s: Bad tabla private data\n", __func__);
 	}
 
-	tabla_unlock_sleep(tabla);
+	tabla_unlock_sleep(core);
 }
 
 void tabla_mbhc_cal(struct snd_soc_codec *codec)
@@ -3877,10 +4059,10 @@
 	    TABLA_MBHC_CAL_BTN_DET_PTR(priv->calibration);
 	short btnmeas[d->n_btn_meas + 1];
 	struct snd_soc_codec *codec = priv->codec;
+	struct tabla *core = dev_get_drvdata(priv->codec->dev->parent);
 
 	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
 	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
-	tabla_lock_sleep(priv);
 
 	bias_value_dce = tabla_codec_read_dce_result(codec);
 	bias_mv_dce = tabla_codec_sta_dce_v(codec, 1, bias_value_dce);
@@ -3926,11 +4108,12 @@
 
 		/* XXX: assuming button 0 has the lowest micbias voltage */
 		if (btn == 0) {
+			tabla_lock_sleep(core);
 			if (schedule_delayed_work(&priv->btn0_dwork,
 						  msecs_to_jiffies(400)) == 0) {
 				WARN(1, "Button pressed twice without release"
 				     "event\n");
-				tabla_unlock_sleep(priv);
+				tabla_unlock_sleep(core);
 			}
 		} else {
 			pr_debug("%s: Reporting short button %d(0x%x) press\n",
@@ -3938,23 +4121,24 @@
 			tabla_snd_soc_jack_report(priv, priv->button_jack, mask,
 						  mask);
 		}
-	} else
+	} else {
 		pr_debug("%s: bogus button press, too short press?\n",
 			 __func__);
+	}
 
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t tabla_release_handler(int irq, void *data)
 {
-	struct tabla_priv *priv = data;
-	struct snd_soc_codec *codec = priv->codec;
 	int ret;
 	short mb_v;
+	struct tabla_priv *priv = data;
+	struct snd_soc_codec *codec = priv->codec;
+	struct tabla *core = dev_get_drvdata(priv->codec->dev->parent);
 
 	pr_debug("%s: enter\n", __func__);
 	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
-	tabla_lock_sleep(priv);
 
 	if (priv->buttons_pressed & SND_JACK_BTN_0) {
 		ret = cancel_delayed_work(&priv->btn0_dwork);
@@ -3968,7 +4152,7 @@
 		} else {
 			/* if scheduled btn0_dwork is canceled from here,
 			 * we have to unlock from here instead btn0_work */
-			tabla_unlock_sleep(priv);
+			tabla_unlock_sleep(core);
 			mb_v = tabla_codec_sta_dce(codec, 0);
 			pr_debug("%s: Mic Voltage on release STA: %d,%d\n",
 				 __func__, mb_v,
@@ -4006,7 +4190,6 @@
 	}
 
 	tabla_codec_start_hs_polling(codec);
-	tabla_unlock_sleep(priv);
 	return IRQ_HANDLED;
 }
 
@@ -4157,7 +4340,6 @@
 
 	pr_debug("%s: enter\n", __func__);
 	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
-	tabla_lock_sleep(priv);
 
 	is_removal = snd_soc_read(codec, TABLA_A_CDC_MBHC_INT_CTL) & 0x02;
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x03, 0x00);
@@ -4229,7 +4411,6 @@
 		}
 		tabla_codec_shutdown_hs_removal_detect(codec);
 		tabla_codec_enable_hs_detect(codec, 1);
-		tabla_unlock_sleep(priv);
 		return IRQ_HANDLED;
 	}
 
@@ -4308,7 +4489,6 @@
 		tabla_sync_hph_state(priv);
 	}
 
-	tabla_unlock_sleep(priv);
 	return IRQ_HANDLED;
 }
 
@@ -4326,7 +4506,6 @@
 	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
 	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
 	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
-	tabla_lock_sleep(priv);
 
 	usleep_range(generic->t_shutdown_plug_rem,
 		     generic->t_shutdown_plug_rem);
@@ -4364,7 +4543,6 @@
 		tabla_codec_enable_hs_detect(codec, 1);
 	}
 
-	tabla_unlock_sleep(priv);
 	return IRQ_HANDLED;
 }
 
@@ -4377,8 +4555,6 @@
 	int i, j;
 	u8 val;
 
-	tabla_lock_sleep(priv);
-
 	for (i = 0; i < TABLA_SLIM_NUM_PORT_REG; i++) {
 		slimbus_value = tabla_interface_reg_read(codec->control_data,
 			TABLA_SLIM_PGD_PORT_INT_STATUS0 + i);
@@ -4396,7 +4572,6 @@
 			TABLA_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
 	}
 
-	tabla_unlock_sleep(priv);
 	return IRQ_HANDLED;
 }
 
@@ -4708,6 +4883,7 @@
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int ret = 0;
 	int i;
+	int ch_cnt;
 
 	codec->control_data = dev_get_drvdata(codec->dev->parent);
 	control = codec->control_data;
@@ -4742,8 +4918,6 @@
 	tabla->codec = codec;
 	tabla->pdata = dev_get_platdata(codec->dev->parent);
 	tabla->intf_type = tabla_get_intf_type();
-	atomic_set(&tabla->pm_cnt, 1);
-	init_waitqueue_head(&tabla->pm_wq);
 
 	tabla_update_reg_address(tabla);
 	tabla_update_reg_defaults(codec);
@@ -4861,6 +5035,20 @@
 		goto err_hphr_ocp_irq;
 	}
 	tabla_disable_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPR_FAULT);
+	for (i = 0; i < ARRAY_SIZE(tabla_dai); i++) {
+		switch (tabla_dai[i].id) {
+		case AIF1_PB:
+			ch_cnt = tabla_dai[i].playback.channels_max;
+			break;
+		case AIF1_CAP:
+			ch_cnt = tabla_dai[i].capture.channels_max;
+			break;
+		default:
+			continue;
+		}
+		tabla->dai[i].ch_num = kzalloc((sizeof(unsigned int)*
+					ch_cnt), GFP_KERNEL);
+	}
 
 #ifdef CONFIG_DEBUG_FS
 	debug_tabla_priv = tabla;
@@ -4887,6 +5075,7 @@
 }
 static int tabla_codec_remove(struct snd_soc_codec *codec)
 {
+	int i;
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
 	tabla_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
 	tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
@@ -4897,6 +5086,8 @@
 	tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_OFF);
 	if (tabla->mbhc_fw)
 		release_firmware(tabla->mbhc_fw);
+	for (i = 0; i < ARRAY_SIZE(tabla_dai); i++)
+		kfree(tabla->dai[i].ch_num);
 	kfree(tabla);
 	return 0;
 }
@@ -4941,7 +5132,6 @@
 	buf = (char *)lbuf;
 	debug_tabla_priv->no_mic_headset_override = (*strsep(&buf, " ") == '0')
 		? false : true;
-
 	return rc;
 }
 
@@ -4954,53 +5144,14 @@
 #ifdef CONFIG_PM
 static int tabla_suspend(struct device *dev)
 {
-	int ret = 0, cnt;
-	struct platform_device *pdev = to_platform_device(dev);
-	struct tabla_priv *tabla = platform_get_drvdata(pdev);
-
-	cnt = atomic_read(&tabla->pm_cnt);
-	if (cnt > 0) {
-		if (wait_event_timeout(tabla->pm_wq,
-				       (atomic_cmpxchg(&tabla->pm_cnt, 1, 0)
-						== 1), 5 * HZ)) {
-			dev_dbg(dev, "system suspend pm_cnt %d\n",
-				atomic_read(&tabla->pm_cnt));
-		} else {
-			dev_err(dev, "%s timed out pm_cnt = %d\n",
-				__func__, atomic_read(&tabla->pm_cnt));
-			WARN_ON_ONCE(1);
-			ret = -EBUSY;
-		}
-	} else if (cnt == 0)
-		dev_warn(dev, "system is already in suspend, pm_cnt %d\n",
-			 atomic_read(&tabla->pm_cnt));
-	else {
-		WARN(1, "unexpected pm_cnt %d\n", cnt);
-		ret = -EFAULT;
-	}
-
-	return ret;
+	dev_dbg(dev, "%s: system suspend\n", __func__);
+	return 0;
 }
 
 static int tabla_resume(struct device *dev)
 {
-	int ret = 0, cnt;
-	struct platform_device *pdev = to_platform_device(dev);
-	struct tabla_priv *tabla = platform_get_drvdata(pdev);
-
-	cnt = atomic_cmpxchg(&tabla->pm_cnt, 0, 1);
-	if (cnt == 0) {
-		dev_dbg(dev, "system resume, pm_cnt %d\n",
-			atomic_read(&tabla->pm_cnt));
-		wake_up_all(&tabla->pm_wq);
-	} else if (cnt > 0)
-		dev_warn(dev, "system is already awake, pm_cnt %d\n", cnt);
-	else {
-		WARN(1, "unexpected pm_cnt %d\n", cnt);
-		ret = -EFAULT;
-	}
-
-	return ret;
+	dev_dbg(dev, "%s: system resume\n", __func__);
+	return 0;
 }
 
 static const struct dev_pm_ops tabla_pm_ops = {
diff --git a/sound/soc/codecs/wcd9310.h b/sound/soc/codecs/wcd9310.h
index 6ddc471..9c430b9 100644
--- a/sound/soc/codecs/wcd9310.h
+++ b/sound/soc/codecs/wcd9310.h
@@ -11,6 +11,7 @@
  */
 #include <sound/soc.h>
 #include <sound/jack.h>
+#include <linux/mfd/wcd9310/wcd9310-slimslave.h>
 
 #define TABLA_NUM_REGISTERS 0x400
 #define TABLA_MAX_REGISTER (TABLA_NUM_REGISTERS-1)
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 9e0549b..1ed5f74 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -80,6 +80,13 @@
 config SND_VOIP_PCM
 	tristate
 
+config SND_SOC_MSM_QDSP6_HDMI_AUDIO
+	tristate "Soc QDSP6 HDMI Audio DAI driver"
+	depends on FB_MSM_HDMI_MSM_PANEL
+	default n
+	help
+	 To support HDMI Audio on MSM8960 over QDSP6.
+
 config MSM_8x60_VOIP
 	tristate "SoC Machine driver for voip"
 	depends on SND_SOC_MSM8X60
@@ -120,6 +127,7 @@
 	select SND_SOC_MSM_STUB
 	select SND_SOC_WCD9310
 	select SND_SOC_MSM_HOSTLESS_PCM
+	select SND_SOC_MSM_QDSP6_HDMI_AUDIO
 	default n
 	help
 	 To add support for SoC audio on MSM8960 and APQ8064 boards
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index c583ce2..1b3014e 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -56,7 +56,8 @@
 
 obj-$(CONFIG_SND_SOC_MSM_QDSP6_INTF) += qdsp6/
 
-snd-soc-qdsp6-objs := msm-dai-q6.o msm-pcm-q6.o msm-pcm-routing.o msm-dai-fe.o msm-compr-q6.o
+snd-soc-qdsp6-objs := msm-dai-q6.o msm-pcm-q6.o msm-multi-ch-pcm-q6.o msm-pcm-routing.o msm-dai-fe.o msm-compr-q6.o
+obj-$(CONFIG_SND_SOC_MSM_QDSP6_HDMI_AUDIO) += msm-dai-q6-hdmi.o
 obj-$(CONFIG_SND_SOC_VOICE) += msm-pcm-voice.o msm-pcm-voip.o
 snd-soc-qdsp6-objs += msm-pcm-lpa.o msm-pcm-afe.o
 obj-$(CONFIG_SND_SOC_QDSP6) += snd-soc-qdsp6.o
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index bd41e0b..b5150903 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -671,6 +671,66 @@
 	return tabla_cal;
 }
 
+static int msm_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret = 0;
+	unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+	unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
+
+	pr_debug("%s: ch=%d\n", __func__,
+					msm_slim_0_rx_ch);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		ret = snd_soc_dai_get_channel_map(codec_dai,
+				&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to get codec chan map\n", __func__);
+			goto end;
+		}
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+				msm_slim_0_rx_ch, rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map\n", __func__);
+			goto end;
+		}
+		ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
+				msm_slim_0_rx_ch, rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to set codec channel map\n",
+								__func__);
+			goto end;
+		}
+	} else {
+		ret = snd_soc_dai_get_channel_map(codec_dai,
+				&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to get codec chan map\n", __func__);
+			goto end;
+		}
+		ret = snd_soc_dai_set_channel_map(cpu_dai,
+				msm_slim_0_tx_ch, tx_ch, 0 , 0);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map\n", __func__);
+			goto end;
+		}
+		ret = snd_soc_dai_set_channel_map(codec_dai,
+				msm_slim_0_tx_ch, tx_ch, 0, 0);
+		if (ret < 0) {
+			pr_err("%s: failed to set codec channel map\n",
+								__func__);
+			goto end;
+		}
+
+
+	}
+end:
+	return ret;
+}
+
 static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
 {
 	int err;
@@ -924,6 +984,7 @@
 
 static struct snd_soc_ops msm_be_ops = {
 	.startup = msm_startup,
+	.hw_params = msm_hw_params,
 	.shutdown = msm_shutdown,
 };
 
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 42e7935..8f71e83 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -75,7 +75,7 @@
 			.rates = SNDRV_PCM_RATE_8000_48000,
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
-			.channels_max = 2,
+			.channels_max = 6,
 			.rate_min =     8000,
 			.rate_max =	48000,
 		},
diff --git a/sound/soc/msm/msm-dai-q6-hdmi.c b/sound/soc/msm/msm-dai-q6-hdmi.c
new file mode 100644
index 0000000..6907ded
--- /dev/null
+++ b/sound/soc/msm/msm-dai-q6-hdmi.c
@@ -0,0 +1,283 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/wcd9310/core.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/apr_audio.h>
+#include <sound/q6afe.h>
+#include <sound/q6adm.h>
+#include <sound/msm-dai-q6.h>
+#include <mach/clk.h>
+#include <mach/msm_hdmi_audio.h>
+
+
+enum {
+	STATUS_PORT_STARTED, /* track if AFE port has started */
+	STATUS_MAX
+};
+
+struct msm_dai_q6_hdmi_dai_data {
+	DECLARE_BITMAP(status_mask, STATUS_MAX);
+	u32 rate;
+	u32 channels;
+	union afe_port_config port_config;
+};
+
+
+/* Current implementation assumes hw_param is called once
+ * This may not be the case but what to do when ADM and AFE
+ * port are already opened and parameter changes
+ */
+static int msm_dai_q6_hdmi_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params,
+				struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_hdmi_dai_data *dai_data = dev_get_drvdata(dai->dev);
+	u32 channel_allocation = 0;
+	u32 level_shift  = 0; /* 0dB */
+	bool down_mix = FALSE;
+
+	dai_data->channels = params_channels(params);
+	dai_data->rate = params_rate(params);
+	dai_data->port_config.hdmi_multi_ch.data_type = 0;
+	dai_data->port_config.hdmi_multi_ch.reserved = 0;
+
+	switch (dai_data->channels) {
+	case 2:
+		channel_allocation  = 0;
+		hdmi_msm_audio_info_setup(1, MSM_HDMI_AUDIO_CHANNEL_2,
+				channel_allocation, level_shift, down_mix);
+		dai_data->port_config.hdmi_multi_ch.channel_allocation =
+			channel_allocation;
+		break;
+	case 6:
+		channel_allocation  = 0x0B;
+		hdmi_msm_audio_info_setup(1, MSM_HDMI_AUDIO_CHANNEL_6,
+				channel_allocation, level_shift, down_mix);
+		dai_data->port_config.hdmi_multi_ch.channel_allocation =
+				channel_allocation;
+		break;
+	default:
+		dev_err(dai->dev, "invalid Channels = %u\n",
+				dai_data->channels);
+		return -EINVAL;
+	}
+	dev_dbg(dai->dev, "%s() num_ch = %u rate =%u"
+		" channel_allocation = %u\n", __func__, dai_data->channels,
+		dai_data->rate,
+		dai_data->port_config.hdmi_multi_ch.channel_allocation);
+
+	return 0;
+}
+
+
+static void msm_dai_q6_hdmi_shutdown(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_hdmi_dai_data *dai_data = dev_get_drvdata(dai->dev);
+	int rc = 0;
+
+	if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+		pr_info("%s:  afe port not started. dai_data->status_mask"
+			" = %ld\n", __func__, *dai_data->status_mask);
+		return;
+	}
+
+	rc = afe_close(dai->id); /* can block */
+
+	if (IS_ERR_VALUE(rc))
+		dev_err(dai->dev, "fail to close AFE port\n");
+
+	pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
+			*dai_data->status_mask);
+
+	clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
+}
+
+
+static int msm_dai_q6_hdmi_prepare(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_hdmi_dai_data *dai_data = dev_get_drvdata(dai->dev);
+	int rc = 0;
+
+	if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+		/* PORT START should be set if prepare called in active state */
+		rc = afe_q6_interface_prepare();
+		if (IS_ERR_VALUE(rc))
+			dev_err(dai->dev, "fail to open AFE APR\n");
+	}
+	return rc;
+}
+
+static int msm_dai_q6_hdmi_trigger(struct snd_pcm_substream *substream, int cmd,
+		struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_hdmi_dai_data *dai_data = dev_get_drvdata(dai->dev);
+
+	/* Start/stop port without waiting for Q6 AFE response. Need to have
+	 * native q6 AFE driver propagates AFE response in order to handle
+	 * port start/stop command error properly if error does arise.
+	 */
+	pr_debug("%s:port:%d  cmd:%d dai_data->status_mask = %ld",
+		__func__, dai->id, cmd, *dai_data->status_mask);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+			afe_port_start_nowait(dai->id, &dai_data->port_config,
+					dai_data->rate);
+
+			set_bit(STATUS_PORT_STARTED, dai_data->status_mask);
+		}
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+			afe_port_stop_nowait(dai->id);
+			clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
+		}
+		break;
+
+	default:
+		dev_err(dai->dev, "invalid Trigger command = %d\n", cmd);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int msm_dai_q6_hdmi_dai_probe(struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_hdmi_dai_data *dai_data;
+	int rc = 0;
+
+	dai_data = kzalloc(sizeof(struct msm_dai_q6_hdmi_dai_data),
+		GFP_KERNEL);
+
+	if (!dai_data) {
+		dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
+		dai->id);
+		rc = -ENOMEM;
+	} else
+		dev_set_drvdata(dai->dev, dai_data);
+
+	return rc;
+}
+
+static int msm_dai_q6_hdmi_dai_remove(struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_hdmi_dai_data *dai_data;
+	int rc;
+
+	dai_data = dev_get_drvdata(dai->dev);
+
+	/* If AFE port is still up, close it */
+	if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+		rc = afe_close(dai->id); /* can block */
+
+		if (IS_ERR_VALUE(rc))
+			dev_err(dai->dev, "fail to close AFE port\n");
+
+		clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
+	}
+	kfree(dai_data);
+	snd_soc_unregister_dai(dai->dev);
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops msm_dai_q6_hdmi_ops = {
+	.prepare	= msm_dai_q6_hdmi_prepare,
+	.trigger	= msm_dai_q6_hdmi_trigger,
+	.hw_params	= msm_dai_q6_hdmi_hw_params,
+	.shutdown	= msm_dai_q6_hdmi_shutdown,
+};
+
+static struct snd_soc_dai_driver msm_dai_q6_hdmi_hdmi_rx_dai = {
+	.playback = {
+		.rates = SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 2,
+		.channels_max = 6,
+		.rate_max =     48000,
+		.rate_min =	48000,
+	},
+	.ops = &msm_dai_q6_hdmi_ops,
+	.probe = msm_dai_q6_hdmi_dai_probe,
+	.remove = msm_dai_q6_hdmi_dai_remove,
+};
+
+
+/* To do: change to register DAIs as batch */
+static __devinit int msm_dai_q6_hdmi_dev_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+
+	dev_dbg(&pdev->dev, "dev name %s dev-id %d\n",
+			dev_name(&pdev->dev), pdev->id);
+
+	switch (pdev->id) {
+	case HDMI_RX:
+		rc = snd_soc_register_dai(&pdev->dev,
+				&msm_dai_q6_hdmi_hdmi_rx_dai);
+		break;
+	default:
+		dev_err(&pdev->dev, "invalid device ID %d\n", pdev->id);
+		rc = -ENODEV;
+		break;
+	}
+	return rc;
+}
+
+static __devexit int msm_dai_q6_hdmi_dev_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_dai(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver msm_dai_q6_hdmi_driver = {
+	.probe  = msm_dai_q6_hdmi_dev_probe,
+	.remove = msm_dai_q6_hdmi_dev_remove,
+	.driver = {
+		.name = "msm-dai-q6-hdmi",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_dai_q6_hdmi_init(void)
+{
+	return platform_driver_register(&msm_dai_q6_hdmi_driver);
+}
+module_init(msm_dai_q6_hdmi_init);
+
+static void __exit msm_dai_q6_hdmi_exit(void)
+{
+	platform_driver_unregister(&msm_dai_q6_hdmi_driver);
+}
+module_exit(msm_dai_q6_hdmi_exit);
+
+/* Module information */
+MODULE_DESCRIPTION("MSM DSP HDMI DAI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index c7d7004..aff87ae 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -206,110 +206,33 @@
 	return 0;
 }
 
-static int msm_dai_q6_hdmi_hw_params(struct snd_pcm_hw_params *params,
-	struct snd_soc_dai *dai)
-{
-	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
-
-	dev_dbg(dai->dev, "%s start HDMI port\n", __func__);
-
-	dai_data->channels = params_channels(params);
-	switch (dai_data->channels) {
-	case 2:
-		dai_data->port_config.hdmi.channel_mode = 0; /* Put in macro */
-		break;
-	default:
-		return -EINVAL;
-		break;
-	}
-
-	/* Q6 only supports 16 as now */
-	dai_data->port_config.hdmi.bitwidth = 16;
-	dai_data->port_config.hdmi.data_type = 0;
-	dai_data->rate = params_rate(params);
-
-	return 0;
-}
 
 static int msm_dai_q6_slim_bus_hw_params(struct snd_pcm_hw_params *params,
 				    struct snd_soc_dai *dai, int stream)
 {
 	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
-	u8 pgd_la, inf_la;
-	u16 *slave_port_mapping;
-
-	memset(dai_data->port_config.slimbus.slave_port_mapping, 0,
-		sizeof(dai_data->port_config.slimbus.slave_port_mapping));
 
 	dai_data->channels = params_channels(params);
-
-	slave_port_mapping = dai_data->port_config.slimbus.slave_port_mapping;
-
-	switch (dai_data->channels) {
-	case 4:
-		if (dai->id == SLIMBUS_0_TX) {
-			slave_port_mapping[0] = 7;
-			slave_port_mapping[1] = 8;
-			slave_port_mapping[2] = 9;
-			slave_port_mapping[3] = 10;
-		} else {
-			return -EINVAL;
-		}
-		break;
-	case 3:
-		if (dai->id == SLIMBUS_0_TX) {
-			slave_port_mapping[0] = 7;
-			slave_port_mapping[1] = 8;
-			slave_port_mapping[2] = 9;
-		} else {
-			return -EINVAL;
-		}
-		break;
-	case 2:
-		if (dai->id == SLIMBUS_0_RX) {
-			slave_port_mapping[0] = 1;
-			slave_port_mapping[1] = 2;
-		} else {
-			slave_port_mapping[0] = 7;
-			slave_port_mapping[1] = 8;
-		}
-		break;
-	case 1:
-		if (dai->id == SLIMBUS_0_RX)
-			slave_port_mapping[0] = 1;
-		else
-			slave_port_mapping[0] = 7;
-		break;
-	default:
-		return -EINVAL;
-		break;
-	}
 	dai_data->rate = params_rate(params);
-	tabla_get_logical_addresses(&pgd_la, &inf_la);
 
 	dai_data->port_config.slimbus.slimbus_dev_id =  AFE_SLIMBUS_DEVICE_1;
-	dai_data->port_config.slimbus.slave_dev_pgd_la = pgd_la;
-	dai_data->port_config.slimbus.slave_dev_intfdev_la = inf_la;
 	/* Q6 only supports 16 as now */
-	dai_data->port_config.slimbus.bit_width = 16;
-	dai_data->port_config.slimbus.data_format = 0;
-	dai_data->port_config.slimbus.num_channels = dai_data->channels;
-	dai_data->port_config.slimbus.reserved = 0;
+	dai_data->port_config.slim_sch.bit_width = 16;
+	dai_data->port_config.slim_sch.data_format = 0;
+	dai_data->port_config.slim_sch.num_channels = dai_data->channels;
+	dai_data->port_config.slim_sch.reserved = 0;
 
-	dev_dbg(dai->dev, "slimbus_dev_id  %hu  slave_dev_pgd_la 0x%hx\n"
-		"slave_dev_intfdev_la 0x%hx   bit_width %hu   data_format %hu\n"
-		"num_channel %hu  slave_port_mapping[0]  %hu\n"
+	dev_dbg(dai->dev, "%s:slimbus_dev_id[%hu] bit_wd[%hu] format[%hu]\n"
+		"num_channel %hu  slave_ch_mapping[0]  %hu\n"
 		"slave_port_mapping[1]  %hu slave_port_mapping[2]  %hu\n"
-		"sample_rate %d\n",
-		dai_data->port_config.slimbus.slimbus_dev_id,
-		dai_data->port_config.slimbus.slave_dev_pgd_la,
-		dai_data->port_config.slimbus.slave_dev_intfdev_la,
-		dai_data->port_config.slimbus.bit_width,
-		dai_data->port_config.slimbus.data_format,
-		dai_data->port_config.slimbus.num_channels,
-		dai_data->port_config.slimbus.slave_port_mapping[0],
-		dai_data->port_config.slimbus.slave_port_mapping[1],
-		dai_data->port_config.slimbus.slave_port_mapping[2],
+		"sample_rate %d\n", __func__,
+		dai_data->port_config.slim_sch.slimbus_dev_id,
+		dai_data->port_config.slim_sch.bit_width,
+		dai_data->port_config.slim_sch.data_format,
+		dai_data->port_config.slim_sch.num_channels,
+		dai_data->port_config.slim_sch.slave_ch_mapping[0],
+		dai_data->port_config.slim_sch.slave_ch_mapping[1],
+		dai_data->port_config.slim_sch.slave_ch_mapping[2],
 		dai_data->rate);
 
 	return 0;
@@ -425,9 +348,6 @@
 	case MI2S_RX:
 		rc = msm_dai_q6_mi2s_hw_params(params, dai, substream->stream);
 		break;
-	case HDMI_RX:
-		rc = msm_dai_q6_hdmi_hw_params(params, dai);
-		break;
 	case SLIMBUS_0_RX:
 	case SLIMBUS_0_TX:
 		rc = msm_dai_q6_slim_bus_hw_params(params, dai,
@@ -811,7 +731,8 @@
 {
 	int rc = 0;
 
-	dev_dbg(dai->dev, "enter %s, id = %d\n", __func__, dai->id);
+	dev_dbg(dai->dev, "enter %s, id = %d fmt[%d]\n", __func__,
+							dai->id, fmt);
 	switch (dai->id) {
 	case PRIMARY_I2S_TX:
 	case PRIMARY_I2S_RX:
@@ -828,12 +749,69 @@
 	return rc;
 }
 
+static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai,
+				unsigned int tx_num, unsigned int *tx_slot,
+				unsigned int rx_num, unsigned int *rx_slot)
+
+{
+	int rc = 0;
+	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
+	unsigned int i = 0;
+
+	dev_dbg(dai->dev, "enter %s, id = %d\n", __func__,
+							dai->id);
+	if (!tx_slot && !rx_slot)
+		return -EINVAL;
+	switch (dai->id) {
+	case SLIMBUS_0_RX:
+		/* channel number to be between 128 and 255. For RX port
+		 * use channel numbers from 138 to 144, for TX port
+		 * use channel numbers from 128 to 137
+		 */
+		for (i = 0; i < rx_num; i++) {
+			dai_data->port_config.slim_sch.slave_ch_mapping[i] =
+							rx_slot[i];
+			pr_debug("%s: find number of channels[%d] ch[%d]\n",
+							__func__, i,
+							rx_slot[i]);
+		}
+		dai_data->port_config.slim_sch.num_channels = rx_num;
+		pr_debug("%s:SLIMBUS_0_RX cnt[%d] ch[%d %d]\n", __func__,
+		rx_num, dai_data->port_config.slim_sch.slave_ch_mapping[0],
+		dai_data->port_config.slim_sch.slave_ch_mapping[1]);
+
+		break;
+	case SLIMBUS_0_TX:
+		/* channel number to be between 128 and 255. For RX port
+		 * use channel numbers from 138 to 144, for TX port
+		 * use channel numbers from 128 to 137
+		 */
+		for (i = 0; i < tx_num; i++) {
+			dai_data->port_config.slim_sch.slave_ch_mapping[i] =
+							tx_slot[i];
+			pr_debug("%s: find number of channels[%d] ch[%d]\n",
+						__func__, i, tx_slot[i]);
+		}
+		dai_data->port_config.slim_sch.num_channels = tx_num;
+		pr_debug("%s:SLIMBUS_0_TX cnt[%d] ch[%d %d]\n", __func__,
+		tx_num, dai_data->port_config.slim_sch.slave_ch_mapping[0],
+		dai_data->port_config.slim_sch.slave_ch_mapping[1]);
+		break;
+	default:
+		dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
+
 static struct snd_soc_dai_ops msm_dai_q6_ops = {
 	.prepare	= msm_dai_q6_prepare,
 	.trigger	= msm_dai_q6_trigger,
 	.hw_params	= msm_dai_q6_hw_params,
 	.shutdown	= msm_dai_q6_shutdown,
 	.set_fmt	= msm_dai_q6_set_fmt,
+	.set_channel_map = msm_dai_q6_set_channel_map,
 };
 
 static struct snd_soc_dai_ops msm_dai_q6_auxpcm_ops = {
@@ -903,20 +881,6 @@
 	.remove = msm_dai_q6_dai_remove,
 };
 
-static struct snd_soc_dai_driver msm_dai_q6_hdmi_rx_dai = {
-	.playback = {
-		.rates = SNDRV_PCM_RATE_48000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE,
-		.channels_min = 2,
-		.channels_max = 2,
-		.rate_max =     48000,
-		.rate_min =	48000,
-	},
-	.ops = &msm_dai_q6_ops,
-	.probe = msm_dai_q6_dai_probe,
-	.remove = msm_dai_q6_dai_remove,
-};
-
 static struct snd_soc_dai_driver msm_dai_q6_voice_playback_tx_dai = {
 	.playback = {
 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
@@ -1101,9 +1065,6 @@
 		rc = snd_soc_register_dai(&pdev->dev,
 					&msm_dai_q6_mi2s_rx_dai);
 		break;
-	case HDMI_RX:
-		rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_hdmi_rx_dai);
-		break;
 	case SLIMBUS_0_RX:
 		rc = snd_soc_register_dai(&pdev->dev,
 				&msm_dai_q6_slimbus_rx_dai);
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
new file mode 100644
index 0000000..1dac5d2
--- /dev/null
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -0,0 +1,723 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/android_pmem.h>
+#include <asm/dma.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+
+#include "msm-pcm-q6.h"
+#include "msm-pcm-routing.h"
+
+static struct audio_locks the_locks;
+
+struct snd_msm {
+	struct snd_card *card;
+	struct snd_pcm *pcm;
+};
+
+#define PLAYBACK_NUM_PERIODS	8
+#define PLAYBACK_PERIOD_SIZE	4032
+#define CAPTURE_NUM_PERIODS	16
+#define CAPTURE_PERIOD_SIZE	320
+
+static struct snd_pcm_hardware msm_pcm_hardware_capture = {
+	.info =                 (SNDRV_PCM_INFO_MMAP |
+				SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				SNDRV_PCM_INFO_MMAP_VALID |
+				SNDRV_PCM_INFO_INTERLEAVED |
+				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
+	.formats =              SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =                SNDRV_PCM_RATE_8000_48000,
+	.rate_min =             8000,
+	.rate_max =             48000,
+	.channels_min =         1,
+	.channels_max =         2,
+	.buffer_bytes_max =     CAPTURE_NUM_PERIODS * CAPTURE_PERIOD_SIZE,
+	.period_bytes_min =	CAPTURE_PERIOD_SIZE,
+	.period_bytes_max =     CAPTURE_PERIOD_SIZE,
+	.periods_min =          CAPTURE_NUM_PERIODS,
+	.periods_max =          CAPTURE_NUM_PERIODS,
+	.fifo_size =            0,
+};
+
+static struct snd_pcm_hardware msm_pcm_hardware_playback = {
+	.info =                 (SNDRV_PCM_INFO_MMAP |
+				SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				SNDRV_PCM_INFO_MMAP_VALID |
+				SNDRV_PCM_INFO_INTERLEAVED |
+				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
+	.formats =              SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =                SNDRV_PCM_RATE_8000_48000,
+	.rate_min =             8000,
+	.rate_max =             48000,
+	.channels_min =         1,
+	.channels_max =         6,
+	.buffer_bytes_max =     PLAYBACK_NUM_PERIODS * PLAYBACK_PERIOD_SIZE,
+	.period_bytes_min =	PLAYBACK_PERIOD_SIZE,
+	.period_bytes_max =     PLAYBACK_PERIOD_SIZE,
+	.periods_min =          PLAYBACK_NUM_PERIODS,
+	.periods_max =          PLAYBACK_NUM_PERIODS,
+	.fifo_size =            0,
+};
+
+/* Conventional and unconventional sample rate supported */
+static unsigned int supported_sample_rates[] = {
+	8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
+};
+
+static uint32_t in_frame_info[CAPTURE_NUM_PERIODS][2];
+
+static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
+	.count = ARRAY_SIZE(supported_sample_rates),
+	.list = supported_sample_rates,
+	.mask = 0,
+};
+
+static void event_handler(uint32_t opcode,
+		uint32_t token, uint32_t *payload, void *priv)
+{
+	struct msm_audio *prtd = priv;
+	struct snd_pcm_substream *substream = prtd->substream;
+	uint32_t *ptrmem = (uint32_t *)payload;
+	int i = 0;
+	uint32_t idx = 0;
+	uint32_t size = 0;
+
+	pr_debug("%s\n", __func__);
+	switch (opcode) {
+	case ASM_DATA_EVENT_WRITE_DONE: {
+		pr_debug("ASM_DATA_EVENT_WRITE_DONE\n");
+		pr_debug("Buffer Consumed = 0x%08x\n", *ptrmem);
+		prtd->pcm_irq_pos += prtd->pcm_count;
+		if (atomic_read(&prtd->start))
+			snd_pcm_period_elapsed(substream);
+		atomic_inc(&prtd->out_count);
+		wake_up(&the_locks.write_wait);
+		if (!atomic_read(&prtd->start))
+			break;
+		if (!prtd->mmap_flag)
+			break;
+		if (q6asm_is_cpu_buf_avail_nolock(IN,
+				prtd->audio_client,
+				&size, &idx)) {
+			pr_debug("%s:writing %d bytes of buffer to dsp 2\n",
+					__func__, prtd->pcm_count);
+			q6asm_write_nolock(prtd->audio_client,
+				prtd->pcm_count, 0, 0, NO_TIMESTAMP);
+		}
+		break;
+	}
+	case ASM_DATA_CMDRSP_EOS:
+		pr_debug("ASM_DATA_CMDRSP_EOS\n");
+		prtd->cmd_ack = 1;
+		wake_up(&the_locks.eos_wait);
+		break;
+	case ASM_DATA_EVENT_READ_DONE: {
+		pr_debug("ASM_DATA_EVENT_READ_DONE\n");
+		pr_debug("token = 0x%08x\n", token);
+		for (i = 0; i < 8; i++, ++ptrmem)
+			pr_debug("cmd[%d]=0x%08x\n", i, *ptrmem);
+		in_frame_info[token][0] = payload[2];
+		in_frame_info[token][1] = payload[3];
+		prtd->pcm_irq_pos += in_frame_info[token][0];
+		pr_debug("pcm_irq_pos=%d\n", prtd->pcm_irq_pos);
+		if (atomic_read(&prtd->start))
+			snd_pcm_period_elapsed(substream);
+		if (atomic_read(&prtd->in_count) <= prtd->periods)
+			atomic_inc(&prtd->in_count);
+		wake_up(&the_locks.read_wait);
+		if (prtd->mmap_flag
+			&& q6asm_is_cpu_buf_avail_nolock(OUT,
+				prtd->audio_client,
+				&size, &idx))
+			q6asm_read_nolock(prtd->audio_client);
+		break;
+	}
+	case APR_BASIC_RSP_RESULT: {
+		switch (payload[0]) {
+		case ASM_SESSION_CMD_RUN:
+			if (substream->stream
+				!= SNDRV_PCM_STREAM_PLAYBACK) {
+				atomic_set(&prtd->start, 1);
+				break;
+			}
+			if (prtd->mmap_flag) {
+				pr_debug("%s:writing %d bytes"
+					" of buffer to dsp\n",
+					__func__,
+					prtd->pcm_count);
+				q6asm_write_nolock(prtd->audio_client,
+					prtd->pcm_count,
+					0, 0, NO_TIMESTAMP);
+			} else {
+				while (atomic_read(&prtd->out_needed)) {
+					pr_debug("%s:writing %d bytes"
+						 " of buffer to dsp\n",
+						__func__,
+						prtd->pcm_count);
+					q6asm_write_nolock(prtd->audio_client,
+						prtd->pcm_count,
+						0, 0, NO_TIMESTAMP);
+					atomic_dec(&prtd->out_needed);
+					wake_up(&the_locks.write_wait);
+				};
+			}
+			atomic_set(&prtd->start, 1);
+			break;
+		default:
+			break;
+		}
+	}
+	break;
+	default:
+		pr_debug("Not Supported Event opcode[0x%x]\n", opcode);
+		break;
+	}
+}
+
+static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct msm_audio *prtd = runtime->private_data;
+	int ret;
+
+	pr_debug("%s\n", __func__);
+	prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
+	prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
+	prtd->pcm_irq_pos = 0;
+	/* rate and channels are sent to audio driver */
+	prtd->samp_rate = runtime->rate;
+	prtd->channel_mode = runtime->channels;
+	if (prtd->enabled)
+		return 0;
+
+	ret = q6asm_media_format_block_multi_ch_pcm(prtd->audio_client,
+			runtime->rate, runtime->channels);
+	if (ret < 0)
+		pr_info("%s: CMD Format block failed\n", __func__);
+
+	atomic_set(&prtd->out_count, runtime->periods);
+
+	prtd->enabled = 1;
+	prtd->cmd_ack = 0;
+
+	return 0;
+}
+
+static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct msm_audio *prtd = runtime->private_data;
+	int ret = 0;
+	int i = 0;
+	pr_debug("%s\n", __func__);
+	prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
+	prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
+	prtd->pcm_irq_pos = 0;
+
+	/* rate and channels are sent to audio driver */
+	prtd->samp_rate = runtime->rate;
+	prtd->channel_mode = runtime->channels;
+
+	if (prtd->enabled)
+		return 0;
+
+	pr_debug("Samp_rate = %d\n", prtd->samp_rate);
+	pr_debug("Channel = %d\n", prtd->channel_mode);
+	ret = q6asm_enc_cfg_blk_pcm(prtd->audio_client, prtd->samp_rate,
+					prtd->channel_mode);
+	if (ret < 0)
+		pr_debug("%s: cmd cfg pcm was block failed", __func__);
+
+	for (i = 0; i < runtime->periods; i++)
+		q6asm_read(prtd->audio_client);
+	prtd->periods = runtime->periods;
+
+	prtd->enabled = 1;
+
+	return ret;
+}
+
+static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	int ret = 0;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct msm_audio *prtd = runtime->private_data;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		pr_debug("%s: Trigger start\n", __func__);
+		q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
+		atomic_set(&prtd->start, 0);
+		if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
+			break;
+		prtd->cmd_ack = 0;
+		q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
+		break;
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		pr_debug("SNDRV_PCM_TRIGGER_PAUSE\n");
+		q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
+		atomic_set(&prtd->start, 0);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int msm_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+	struct msm_audio *prtd;
+	int ret = 0;
+
+	pr_debug("%s\n", __func__);
+	prtd = kzalloc(sizeof(struct msm_audio), GFP_KERNEL);
+	if (prtd == NULL) {
+		pr_err("Failed to allocate memory for msm_audio\n");
+		return -ENOMEM;
+	}
+	prtd->substream = substream;
+	prtd->audio_client = q6asm_audio_client_alloc(
+				(app_cb)event_handler, prtd);
+	if (!prtd->audio_client) {
+		pr_err("%s: Could not allocate memory\n", __func__);
+		kfree(prtd);
+		return -ENOMEM;
+	}
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		runtime->hw = msm_pcm_hardware_playback;
+		ret = q6asm_open_write(prtd->audio_client,
+				FORMAT_MULTI_CHANNEL_LINEAR_PCM);
+		if (ret < 0) {
+			pr_err("%s: pcm out open failed\n", __func__);
+			q6asm_audio_client_free(prtd->audio_client);
+			kfree(prtd);
+			return -ENOMEM;
+		}
+	}
+	/* Capture path */
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		runtime->hw = msm_pcm_hardware_capture;
+		ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM);
+		if (ret < 0) {
+			pr_err("%s: pcm in open failed\n", __func__);
+			q6asm_audio_client_free(prtd->audio_client);
+			kfree(prtd);
+			return -ENOMEM;
+		}
+	}
+
+	pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
+
+	prtd->session_id = prtd->audio_client->session;
+	msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
+			prtd->session_id, substream->stream);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		prtd->cmd_ack = 1;
+
+	ret = snd_pcm_hw_constraint_list(runtime, 0,
+				SNDRV_PCM_HW_PARAM_RATE,
+				&constraints_sample_rates);
+	if (ret < 0)
+		pr_err("snd_pcm_hw_constraint_list failed\n");
+	/* Ensure that buffer size is a multiple of period size */
+	ret = snd_pcm_hw_constraint_integer(runtime,
+					    SNDRV_PCM_HW_PARAM_PERIODS);
+	if (ret < 0)
+		pr_err("snd_pcm_hw_constraint_integer failed\n");
+
+	prtd->dsp_cnt = 0;
+	runtime->private_data = prtd;
+
+	return 0;
+}
+
+static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
+	snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
+{
+	int ret = 0;
+	int fbytes = 0;
+	int xfer = 0;
+	char *bufptr = NULL;
+	void *data = NULL;
+	uint32_t idx = 0;
+	uint32_t size = 0;
+
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct msm_audio *prtd = runtime->private_data;
+
+	fbytes = frames_to_bytes(runtime, frames);
+	pr_debug("%s: prtd->out_count = %d\n",
+				__func__, atomic_read(&prtd->out_count));
+	ret = wait_event_timeout(the_locks.write_wait,
+			(atomic_read(&prtd->out_count)), 5 * HZ);
+	if (ret < 0) {
+		pr_err("%s: wait_event_timeout failed\n", __func__);
+		goto fail;
+	}
+
+	if (!atomic_read(&prtd->out_count)) {
+		pr_err("%s: pcm stopped out_count 0\n", __func__);
+		return 0;
+	}
+
+	data = q6asm_is_cpu_buf_avail(IN, prtd->audio_client, &size, &idx);
+	bufptr = data;
+	if (bufptr) {
+		pr_debug("%s:fbytes =%d: xfer=%d size=%d\n",
+					__func__, fbytes, xfer, size);
+		xfer = fbytes;
+		if (copy_from_user(bufptr, buf, xfer)) {
+			ret = -EFAULT;
+			goto fail;
+		}
+		buf += xfer;
+		fbytes -= xfer;
+		pr_debug("%s:fbytes = %d: xfer=%d\n", __func__, fbytes, xfer);
+		if (atomic_read(&prtd->start)) {
+			pr_debug("%s:writing %d bytes of buffer to dsp\n",
+					__func__, xfer);
+			ret = q6asm_write(prtd->audio_client, xfer,
+						0, 0, NO_TIMESTAMP);
+			if (ret < 0) {
+				ret = -EFAULT;
+				goto fail;
+			}
+		} else
+			atomic_inc(&prtd->out_needed);
+		atomic_dec(&prtd->out_count);
+	}
+fail:
+	return  ret;
+}
+
+static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+	struct msm_audio *prtd = runtime->private_data;
+	int dir = 0;
+	int ret = 0;
+
+	pr_debug("%s\n", __func__);
+
+	dir = IN;
+	ret = wait_event_timeout(the_locks.eos_wait,
+				prtd->cmd_ack, 5 * HZ);
+	if (ret < 0)
+		pr_err("%s: CMD_EOS failed\n", __func__);
+	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+	q6asm_audio_client_buf_free_contiguous(dir,
+				prtd->audio_client);
+
+	msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
+	SNDRV_PCM_STREAM_PLAYBACK);
+	q6asm_audio_client_free(prtd->audio_client);
+	kfree(prtd);
+	return 0;
+}
+
+static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
+		 int channel, snd_pcm_uframes_t hwoff, void __user *buf,
+						 snd_pcm_uframes_t frames)
+{
+	int ret = 0;
+	int fbytes = 0;
+	int xfer;
+	char *bufptr;
+	void *data = NULL;
+	static uint32_t idx;
+	static uint32_t size;
+	uint32_t offset = 0;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct msm_audio *prtd = substream->runtime->private_data;
+
+
+	pr_debug("%s\n", __func__);
+	fbytes = frames_to_bytes(runtime, frames);
+
+	pr_debug("appl_ptr %d\n", (int)runtime->control->appl_ptr);
+	pr_debug("hw_ptr %d\n", (int)runtime->status->hw_ptr);
+	pr_debug("avail_min %d\n", (int)runtime->control->avail_min);
+
+	ret = wait_event_timeout(the_locks.read_wait,
+			(atomic_read(&prtd->in_count)), 5 * HZ);
+	if (ret < 0) {
+		pr_debug("%s: wait_event_timeout failed\n", __func__);
+		goto fail;
+	}
+	if (!atomic_read(&prtd->in_count)) {
+		pr_debug("%s: pcm stopped in_count 0\n", __func__);
+		return 0;
+	}
+	pr_debug("Checking if valid buffer is available...%08x\n",
+						(unsigned int) data);
+	data = q6asm_is_cpu_buf_avail(OUT, prtd->audio_client, &size, &idx);
+	bufptr = data;
+	pr_debug("Size = %d\n", size);
+	pr_debug("fbytes = %d\n", fbytes);
+	pr_debug("idx = %d\n", idx);
+	if (bufptr) {
+		xfer = fbytes;
+		if (xfer > size)
+			xfer = size;
+		offset = in_frame_info[idx][1];
+		pr_debug("Offset value = %d\n", offset);
+		if (copy_to_user(buf, bufptr+offset, xfer)) {
+			pr_err("Failed to copy buf to user\n");
+			ret = -EFAULT;
+			goto fail;
+		}
+		fbytes -= xfer;
+		size -= xfer;
+		in_frame_info[idx][1] += xfer;
+		pr_debug("%s:fbytes = %d: size=%d: xfer=%d\n",
+					__func__, fbytes, size, xfer);
+		pr_debug(" Sending next buffer to dsp\n");
+		memset(&in_frame_info[idx], 0,
+			sizeof(uint32_t) * 2);
+		atomic_dec(&prtd->in_count);
+		ret = q6asm_read(prtd->audio_client);
+		if (ret < 0) {
+			pr_err("q6asm read failed\n");
+			ret = -EFAULT;
+			goto fail;
+		}
+	} else
+		pr_err("No valid buffer\n");
+
+	pr_debug("Returning from capture_copy... %d\n", ret);
+fail:
+	return ret;
+}
+
+static int msm_pcm_capture_close(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+	struct msm_audio *prtd = runtime->private_data;
+	int dir = OUT;
+
+	pr_debug("%s\n", __func__);
+	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+	q6asm_audio_client_buf_free_contiguous(dir,
+				prtd->audio_client);
+	msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
+	SNDRV_PCM_STREAM_CAPTURE);
+	q6asm_audio_client_free(prtd->audio_client);
+	kfree(prtd);
+
+	return 0;
+}
+
+static int msm_pcm_copy(struct snd_pcm_substream *substream, int a,
+	 snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
+{
+	int ret = 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		ret = msm_pcm_playback_copy(substream, a, hwoff, buf, frames);
+	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+		ret = msm_pcm_capture_copy(substream, a, hwoff, buf, frames);
+	return ret;
+}
+
+static int msm_pcm_close(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		ret = msm_pcm_playback_close(substream);
+	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+		ret = msm_pcm_capture_close(substream);
+	return ret;
+}
+static int msm_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		ret = msm_pcm_playback_prepare(substream);
+	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+		ret = msm_pcm_capture_prepare(substream);
+	return ret;
+}
+
+static snd_pcm_uframes_t msm_pcm_pointer(struct snd_pcm_substream *substream)
+{
+
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct msm_audio *prtd = runtime->private_data;
+
+	if (prtd->pcm_irq_pos >= prtd->pcm_size)
+		prtd->pcm_irq_pos = 0;
+
+	pr_debug("pcm_irq_pos = %d\n", prtd->pcm_irq_pos);
+	return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
+}
+
+static int msm_pcm_mmap(struct snd_pcm_substream *substream,
+				struct vm_area_struct *vma)
+{
+	int result = 0;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct msm_audio *prtd = runtime->private_data;
+
+	pr_debug("%s\n", __func__);
+	prtd->mmap_flag = 1;
+
+	if (runtime->dma_addr && runtime->dma_bytes) {
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+		result = remap_pfn_range(vma, vma->vm_start,
+				runtime->dma_addr >> PAGE_SHIFT,
+				runtime->dma_bytes,
+				vma->vm_page_prot);
+	} else {
+		pr_err("Physical address or size of buf is NULL");
+		return -EINVAL;
+	}
+
+	return result;
+}
+
+static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct msm_audio *prtd = runtime->private_data;
+	struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
+	struct audio_buffer *buf;
+	int dir, ret;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dir = IN;
+	else
+		dir = OUT;
+
+	ret = q6asm_audio_client_buf_alloc_contiguous(dir,
+			prtd->audio_client,
+			runtime->hw.period_bytes_min,
+			runtime->hw.periods_max);
+	if (ret < 0) {
+		pr_err("Audio Start: Buffer Allocation failed rc = %d\n", ret);
+		return -ENOMEM;
+	}
+	buf = prtd->audio_client->port[dir].buf;
+
+	pr_debug("%s:buf = %p\n", __func__, buf);
+	dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
+	dma_buf->dev.dev = substream->pcm->card->dev;
+	dma_buf->private_data = NULL;
+	dma_buf->area = buf[0].data;
+	dma_buf->addr =  buf[0].phys;
+	dma_buf->bytes = runtime->hw.buffer_bytes_max;
+	if (!dma_buf->area)
+		return -ENOMEM;
+
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+	return 0;
+}
+
+static struct snd_pcm_ops msm_pcm_ops = {
+	.open           = msm_pcm_open,
+	.copy		= msm_pcm_copy,
+	.hw_params	= msm_pcm_hw_params,
+	.close          = msm_pcm_close,
+	.ioctl          = snd_pcm_lib_ioctl,
+	.prepare        = msm_pcm_prepare,
+	.trigger        = msm_pcm_trigger,
+	.pointer        = msm_pcm_pointer,
+	.mmap		= msm_pcm_mmap,
+};
+
+static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_card *card = rtd->card->snd_card;
+	int ret = 0;
+
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+	return ret;
+}
+
+static struct snd_soc_platform_driver msm_soc_platform = {
+	.ops		= &msm_pcm_ops,
+	.pcm_new	= msm_asoc_pcm_new,
+};
+
+static __devinit int msm_pcm_probe(struct platform_device *pdev)
+{
+	pr_info("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
+	return snd_soc_register_platform(&pdev->dev,
+				   &msm_soc_platform);
+}
+
+static int msm_pcm_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_platform(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver msm_pcm_driver = {
+	.driver = {
+		.name = "msm-multi-ch-pcm-dsp",
+		.owner = THIS_MODULE,
+	},
+	.probe = msm_pcm_probe,
+	.remove = __devexit_p(msm_pcm_remove),
+};
+
+static int __init msm_soc_platform_init(void)
+{
+	init_waitqueue_head(&the_locks.enable_wait);
+	init_waitqueue_head(&the_locks.eos_wait);
+	init_waitqueue_head(&the_locks.write_wait);
+	init_waitqueue_head(&the_locks.read_wait);
+
+	return platform_driver_register(&msm_pcm_driver);
+}
+module_init(msm_soc_platform_init);
+
+static void __exit msm_soc_platform_exit(void)
+{
+	platform_driver_unregister(&msm_pcm_driver);
+}
+module_exit(msm_soc_platform_exit);
+
+MODULE_DESCRIPTION("Multi channel PCM module platform driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 2b4999f..8b6b5f1 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -162,6 +162,7 @@
 {
 	int i, session_type, path_type, port_type;
 	struct route_payload payload;
+	u32 channels;
 
 	if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
 		/* bad ID assigned in machine driver */
@@ -191,11 +192,23 @@
 			port_type) && msm_bedais[i].active &&
 			(test_bit(fedai_id,
 			&msm_bedais[i].fe_sessions))) {
-			adm_open(msm_bedais[i].port_id,
+
+			channels = params_channels(msm_bedais[i].hw_params);
+
+			if ((stream_type == SNDRV_PCM_STREAM_PLAYBACK) &&
+				(channels > 2))
+				adm_multi_ch_copp_open(msm_bedais[i].port_id,
+				path_type,
+				params_rate(msm_bedais[i].hw_params),
+				channels,
+				DEFAULT_COPP_TOPOLOGY);
+			else
+				adm_open(msm_bedais[i].port_id,
 				path_type,
 				params_rate(msm_bedais[i].hw_params),
 				params_channels(msm_bedais[i].hw_params),
 				DEFAULT_COPP_TOPOLOGY);
+
 			payload.copp_ids[payload.num_copps++] =
 				msm_bedais[i].port_id;
 		}
@@ -243,6 +256,7 @@
 static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
 {
 	int session_type, path_type;
+	u32 channels;
 
 	pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
 
@@ -271,10 +285,22 @@
 		set_bit(val, &msm_bedais[reg].fe_sessions);
 		if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
 			INVALID_SESSION) {
-			adm_open(msm_bedais[reg].port_id, path_type,
+
+			channels = params_channels(msm_bedais[reg].hw_params);
+
+			if ((session_type == SESSION_TYPE_RX) && (channels > 2))
+				adm_multi_ch_copp_open(msm_bedais[reg].port_id,
+				path_type,
+				params_rate(msm_bedais[reg].hw_params),
+				channels,
+				DEFAULT_COPP_TOPOLOGY);
+			else
+				adm_open(msm_bedais[reg].port_id,
+				path_type,
 				params_rate(msm_bedais[reg].hw_params),
 				params_channels(msm_bedais[reg].hw_params),
 				DEFAULT_COPP_TOPOLOGY);
+
 			msm_pcm_routing_build_matrix(val,
 				fe_dai_map[val][session_type], path_type);
 		}
@@ -1463,6 +1489,7 @@
 	unsigned int be_id = rtd->dai_link->be_id;
 	int i, path_type, session_type;
 	struct msm_pcm_routing_bdai_data *bedai;
+	u32 channels;
 
 	if (be_id >= MSM_BACKEND_DAI_MAX) {
 		pr_err("%s: unexpected be_id %d\n", __func__, be_id);
@@ -1500,10 +1527,22 @@
 
 	for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
 		if (fe_dai_map[i][session_type] != INVALID_SESSION) {
-			adm_open(bedai->port_id, path_type,
+
+			channels = params_channels(bedai->hw_params);
+			if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
+				(channels > 2))
+				adm_multi_ch_copp_open(bedai->port_id,
+				path_type,
+				params_rate(bedai->hw_params),
+				channels,
+				DEFAULT_COPP_TOPOLOGY);
+			else
+				adm_open(bedai->port_id,
+				path_type,
 				params_rate(bedai->hw_params),
 				params_channels(bedai->hw_params),
 				DEFAULT_COPP_TOPOLOGY);
+
 			msm_pcm_routing_build_matrix(i,
 				fe_dai_map[i][session_type], path_type);
 		}
diff --git a/sound/soc/msm/msm7201.c b/sound/soc/msm/msm7201.c
index 9e041c7..6408cef 100644
--- a/sound/soc/msm/msm7201.c
+++ b/sound/soc/msm/msm7201.c
@@ -1,6 +1,6 @@
 /* linux/sound/soc/msm/msm7201.c
  *
- * Copyright (c) 2008-2009, 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2011, 2012 Code Aurora Forum. All rights reserved.
  *
  * All source code in this file is licensed under the following license except
  * where indicated.
@@ -40,6 +40,8 @@
 #include <mach/msm_rpcrouter.h>
 
 static struct msm_rpc_endpoint *snd_ep;
+static uint32_t snd_mute_ear_mute;
+static uint32_t snd_mute_mic_mute;
 
 struct msm_snd_rpc_ids {
 	unsigned long   prog;
@@ -99,7 +101,7 @@
 	 * The number of devices supported is 26 (0 to 25)
 	 */
 	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 25;
+	uinfo->value.integer.max = 36;
 	return 0;
 }
 
@@ -107,6 +109,8 @@
 				struct snd_ctl_elem_value *ucontrol)
 {
 	ucontrol->value.integer.value[0] = (uint32_t)snd_rpc_ids.device;
+	ucontrol->value.integer.value[1] = snd_mute_ear_mute;
+	ucontrol->value.integer.value[2] = snd_mute_mic_mute;
 	return 0;
 }
 
@@ -213,8 +217,11 @@
 	if (rc < 0) {
 		printk(KERN_ERR "%s: snd rpc call failed! rc = %d\n",
 			__func__, rc);
-	} else
-		printk(KERN_INFO "snd device connected \n");
+	} else {
+		printk(KERN_INFO "snd device connected\n");
+		snd_mute_ear_mute = ucontrol->value.integer.value[1];
+		snd_mute_mic_mute = ucontrol->value.integer.value[2];
+	}
 
 	return rc;
 }
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 578f819..bedfd68 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -643,6 +643,66 @@
 	return tabla_cal;
 }
 
+static int msm8960_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret = 0;
+	unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+	unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
+
+	pr_debug("%s: ch=%d\n", __func__,
+					msm8960_slim_0_rx_ch);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		ret = snd_soc_dai_get_channel_map(codec_dai,
+				&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to get codec chan map\n", __func__);
+			goto end;
+		}
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+				msm8960_slim_0_rx_ch, rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map\n", __func__);
+			goto end;
+		}
+		ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
+				msm8960_slim_0_rx_ch, rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to set codec channel map\n",
+								__func__);
+			goto end;
+		}
+	} else {
+		ret = snd_soc_dai_get_channel_map(codec_dai,
+				&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to get codec chan map\n", __func__);
+			goto end;
+		}
+		ret = snd_soc_dai_set_channel_map(cpu_dai,
+				msm8960_slim_0_tx_ch, tx_ch, 0 , 0);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map\n", __func__);
+			goto end;
+		}
+		ret = snd_soc_dai_set_channel_map(codec_dai,
+				msm8960_slim_0_tx_ch, tx_ch, 0, 0);
+		if (ret < 0) {
+			pr_err("%s: failed to set codec channel map\n",
+								__func__);
+			goto end;
+		}
+
+
+	}
+end:
+	return ret;
+}
+
 static int msm8960_audrx_init(struct snd_soc_pcm_runtime *rtd)
 {
 	int err;
@@ -787,8 +847,10 @@
 	struct snd_interval *channels = hw_param_interval(params,
 					SNDRV_PCM_HW_PARAM_CHANNELS);
 
+	pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
+			channels->min, channels->max);
+
 	rate->min = rate->max = 48000;
-	channels->min = channels->max = 2;
 
 	return 0;
 }
@@ -912,6 +974,7 @@
 
 static struct snd_soc_ops msm8960_be_ops = {
 	.startup = msm8960_startup,
+	.hw_params = msm8960_hw_params,
 	.shutdown = msm8960_shutdown,
 };
 
@@ -936,7 +999,7 @@
 		.name = "MSM8960 Media2",
 		.stream_name = "MultiMedia2",
 		.cpu_dai_name	= "MultiMedia2",
-		.platform_name  = "msm-pcm-dsp",
+		.platform_name  = "msm-multi-ch-pcm-dsp",
 		.dynamic = 1,
 		.dsp_link = &fe_media,
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
@@ -1118,7 +1181,7 @@
 	{
 		.name = LPASS_BE_HDMI,
 		.stream_name = "HDMI Playback",
-		.cpu_dai_name = "msm-dai-q6.8",
+		.cpu_dai_name = "msm-dai-q6-hdmi.8",
 		.platform_name = "msm-pcm-routing",
 		.codec_name     = "msm-stub-codec.1",
 		.codec_dai_name = "msm-stub-rx",
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index 177e1d8..2710fbb 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -103,7 +103,8 @@
 		}
 
 		switch (data->opcode) {
-		case ADM_CMDRSP_COPP_OPEN: {
+		case ADM_CMDRSP_COPP_OPEN:
+		case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN: {
 			struct adm_copp_open_respond *open = data->payload;
 			if (open->copp_id == INVALID_COPP_ID) {
 				pr_err("%s: invalid coppid rxed %d\n",
@@ -360,6 +361,133 @@
 	return ret;
 }
 
+
+int adm_multi_ch_copp_open(int port_id, int path, int rate, int channel_mode,
+				int topology)
+{
+	struct adm_multi_ch_copp_open_command open;
+	int ret = 0;
+	int index;
+
+	pr_debug("%s: port %d path:%d rate:%d channel :%d\n", __func__,
+				port_id, path, rate, channel_mode);
+
+	port_id = afe_convert_virtual_to_portid(port_id);
+
+	if (afe_validate_port(port_id) < 0) {
+		pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
+		return -ENODEV;
+	}
+
+	index = afe_get_port_index(port_id);
+	pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
+
+	if (this_adm.apr == NULL) {
+		this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
+						0xFFFFFFFF, &this_adm);
+		if (this_adm.apr == NULL) {
+			pr_err("%s: Unable to register ADM\n", __func__);
+			ret = -ENODEV;
+			return ret;
+		}
+		rtac_set_adm_handle(this_adm.apr);
+	}
+
+	/* Create a COPP if port id are not enabled */
+	if (atomic_read(&this_adm.copp_cnt[index]) == 0) {
+
+		open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+
+		open.hdr.pkt_size =
+			sizeof(struct adm_multi_ch_copp_open_command);
+		open.hdr.opcode = ADM_CMD_MULTI_CHANNEL_COPP_OPEN;
+		memset(open.dev_channel_mapping, 0, 8);
+
+		if (channel_mode == 1)	{
+			open.dev_channel_mapping[0] = PCM_CHANNEL_FC;
+		} else if (channel_mode == 2) {
+			open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+		} else if (channel_mode == 6) {
+			open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+			open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+			open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
+			open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
+			open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
+		} else {
+			pr_err("%s invalid num_chan %d\n", __func__,
+					channel_mode);
+			return -EINVAL;
+		}
+
+
+		open.hdr.src_svc = APR_SVC_ADM;
+		open.hdr.src_domain = APR_DOMAIN_APPS;
+		open.hdr.src_port = port_id;
+		open.hdr.dest_svc = APR_SVC_ADM;
+		open.hdr.dest_domain = APR_DOMAIN_ADSP;
+		open.hdr.dest_port = port_id;
+		open.hdr.token = port_id;
+
+		open.mode = path;
+		open.endpoint_id1 = port_id;
+		open.endpoint_id2 = 0xFFFF;
+
+		/* convert path to acdb path */
+		if (path == ADM_PATH_PLAYBACK)
+			open.topology_id = get_adm_rx_topology();
+		else {
+			open.topology_id = get_adm_tx_topology();
+			if ((open.topology_id ==
+				VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
+			    (open.topology_id ==
+				VPM_TX_DM_FLUENCE_COPP_TOPOLOGY) ||
+			    (open.topology_id ==
+				VPM_TX_QMIC_FLUENCE_COPP_TOPOLOGY))
+				rate = 16000;
+		}
+
+		if (open.topology_id  == 0)
+			open.topology_id = topology;
+
+		open.channel_config = channel_mode & 0x00FF;
+		open.rate  = rate;
+
+		pr_debug("%s: channel_config=%d port_id=%d rate=%d"
+			" topology_id=0x%X\n", __func__, open.channel_config,
+			open.endpoint_id1, open.rate,
+			open.topology_id);
+
+		atomic_set(&this_adm.copp_stat[index], 0);
+
+		ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
+		if (ret < 0) {
+			pr_err("%s:ADM enable for port %d failed\n",
+						__func__, port_id);
+			ret = -EINVAL;
+			goto fail_cmd;
+		}
+		/* Wait for the callback with copp id */
+		ret = wait_event_timeout(this_adm.wait,
+			atomic_read(&this_adm.copp_stat[index]),
+			msecs_to_jiffies(TIMEOUT_MS));
+		if (!ret) {
+			pr_err("%s ADM open failed for port %d\n", __func__,
+								port_id);
+			ret = -EINVAL;
+			goto fail_cmd;
+		}
+	}
+	atomic_inc(&this_adm.copp_cnt[index]);
+	return 0;
+
+fail_cmd:
+
+	return ret;
+}
+
 int adm_matrix_map(int session_id, int path, int num_copps,
 			unsigned int *port_id, int copp_id)
 {
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index 302ef57..59506f1 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -77,6 +77,8 @@
 		if (data->opcode == APR_BASIC_RSP_RESULT) {
 			switch (payload[0]) {
 			case AFE_PORT_AUDIO_IF_CONFIG:
+			case AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG:
+			case AFE_PORT_AUDIO_SLIM_SCH_CONFIG:
 			case AFE_PORT_CMD_STOP:
 			case AFE_PORT_CMD_START:
 			case AFE_PORT_CMD_LOOPBACK:
@@ -280,11 +282,11 @@
 		ret_size = SIZEOF_CFG_CMD(afe_port_mi2s_cfg);
 		break;
 	case HDMI_RX:
-		ret_size = SIZEOF_CFG_CMD(afe_port_hdmi_cfg);
+		ret_size = SIZEOF_CFG_CMD(afe_port_hdmi_multi_ch_cfg);
 		break;
 	case SLIMBUS_0_RX:
 	case SLIMBUS_0_TX:
-		ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_cfg);
+		ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_sch_cfg);
 		break;
 	case RT_PROXY_PORT_001_RX:
 	case RT_PROXY_PORT_001_TX:
@@ -400,13 +402,41 @@
 		ret = -ENODEV;
 		return ret;
 	}
-	config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+
+	if (port_id == HDMI_RX) {
+		config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
-	config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
-	config.hdr.src_port = 0;
-	config.hdr.dest_port = 0;
-	config.hdr.token = 0;
-	config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
+		config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
+		config.hdr.src_port = 0;
+		config.hdr.dest_port = 0;
+		config.hdr.token = 0;
+		config.hdr.opcode = AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG;
+	} else {
+
+		config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+		config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
+		config.hdr.src_port = 0;
+		config.hdr.dest_port = 0;
+		config.hdr.token = 0;
+		switch (port_id) {
+		case SLIMBUS_0_RX:
+		case SLIMBUS_0_TX:
+		case SLIMBUS_1_RX:
+		case SLIMBUS_1_TX:
+		case SLIMBUS_2_RX:
+		case SLIMBUS_2_TX:
+		case SLIMBUS_3_RX:
+		case SLIMBUS_3_TX:
+		case SLIMBUS_4_RX:
+		case SLIMBUS_4_TX:
+			config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
+		break;
+		default:
+			config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
+		break;
+		}
+	}
 
 	if (afe_validate_port(port_id) < 0) {
 
@@ -472,7 +502,7 @@
 		return ret;
 	}
 
-	pr_info("%s: %d %d\n", __func__, port_id, rate);
+	pr_debug("%s: %d %d\n", __func__, port_id, rate);
 
 	if ((port_id == RT_PROXY_DAI_001_RX) ||
 		(port_id == RT_PROXY_DAI_002_TX))
@@ -780,7 +810,7 @@
 	int ret = 0;
 	struct afe_pseudoport_start_command start;
 
-	pr_info("%s: port_id=%d\n", __func__, port_id);
+	pr_debug("%s: port_id=%d\n", __func__, port_id);
 
 	ret = afe_q6_interface_prepare();
 	if (ret != 0)
@@ -853,7 +883,7 @@
 	int ret = 0;
 	struct afe_pseudoport_stop_command stop;
 
-	pr_info("%s: port_id=%d\n", __func__, port_id);
+	pr_debug("%s: port_id=%d\n", __func__, port_id);
 
 	if (this_afe.apr == NULL) {
 		pr_err("%s: AFE is already closed\n", __func__);
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index 62168d2..dc49f12 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -1193,6 +1193,9 @@
 	case FORMAT_LINEAR_PCM:
 		open.format = LINEAR_PCM;
 		break;
+	case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
+		open.format = MULTI_CHANNEL_PCM;
+		break;
 	case FORMAT_MPEG4_AAC:
 		open.format = MPEG4_AAC;
 		break;
@@ -1761,6 +1764,66 @@
 	return -EINVAL;
 }
 
+int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
+				uint32_t rate, uint32_t channels)
+{
+	struct asm_stream_media_format_update fmt;
+	u8 *channel_mapping;
+	int rc = 0;
+
+	pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
+		channels);
+
+	q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
+
+	fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
+
+	fmt.format = MULTI_CHANNEL_PCM;
+	fmt.cfg_size = sizeof(struct asm_multi_channel_pcm_fmt_blk);
+	fmt.write_cfg.multi_ch_pcm_cfg.num_channels = channels;
+	fmt.write_cfg.multi_ch_pcm_cfg.bits_per_sample = 16;
+	fmt.write_cfg.multi_ch_pcm_cfg.sample_rate = rate;
+	fmt.write_cfg.multi_ch_pcm_cfg.is_signed = 1;
+	fmt.write_cfg.multi_ch_pcm_cfg.is_interleaved = 1;
+	channel_mapping =
+		fmt.write_cfg.multi_ch_pcm_cfg.channel_mapping;
+
+	memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
+
+	if (channels == 1)  {
+		channel_mapping[0] = PCM_CHANNEL_FL;
+	} else if (channels == 2) {
+		channel_mapping[0] = PCM_CHANNEL_FL;
+		channel_mapping[1] = PCM_CHANNEL_FR;
+	} else if (channels == 6) {
+		channel_mapping[0] = PCM_CHANNEL_FC;
+		channel_mapping[1] = PCM_CHANNEL_FL;
+		channel_mapping[2] = PCM_CHANNEL_FR;
+		channel_mapping[3] = PCM_CHANNEL_LB;
+		channel_mapping[4] = PCM_CHANNEL_RB;
+		channel_mapping[5] = PCM_CHANNEL_LFE;
+	} else {
+		pr_err("%s: ERROR.unsupported num_ch = %u\n", __func__,
+				channels);
+		return -EINVAL;
+	}
+
+	rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
+	if (rc < 0) {
+		pr_err("%s:Comamnd open failed\n", __func__);
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(ac->cmd_wait,
+			(atomic_read(&ac->cmd_state) == 0), 5*HZ);
+	if (!rc) {
+		pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
+		goto fail_cmd;
+	}
+	return 0;
+fail_cmd:
+	return -EINVAL;
+}
+
 int q6asm_media_format_block_aac(struct audio_client *ac,
 				struct asm_aac_cfg *cfg)
 {
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 219ae10..d528f4b 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3673,6 +3673,29 @@
 EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
 
 /**
+ * snd_soc_dai_get_channel_map - configure DAI audio channel map
+ * @dai: DAI
+ * @tx_num: how many TX channels
+ * @tx_slot: pointer to an array which imply the TX slot number channel
+ *           0~num-1 uses
+ * @rx_num: how many RX channels
+ * @rx_slot: pointer to an array which imply the RX slot number channel
+ *           0~num-1 uses
+ *
+ * configure the relationship between channel number and TDM slot number.
+ */
+int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai,
+	unsigned int *tx_num, unsigned int *tx_slot,
+	unsigned int *rx_num, unsigned int *rx_slot)
+{
+	if (dai->driver && dai->driver->ops->get_channel_map)
+		return dai->driver->ops->get_channel_map(dai, tx_num, tx_slot,
+			rx_num, rx_slot);
+	else
+		return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map);
+/**
  * snd_soc_dai_set_tristate - configure DAI system or master clock.
  * @dai: DAI
  * @tristate: tristate enable
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index b462639..c03f7ca7 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -2,6 +2,7 @@
  * soc-dapm.c  --  ALSA SoC Dynamic Audio Power Management
  *
  * Copyright 2005 Wolfson Microelectronics PLC.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *
@@ -59,8 +60,6 @@
 	[snd_soc_dapm_pre] = 0,
 	[snd_soc_dapm_supply] = 1,
 	[snd_soc_dapm_micbias] = 2,
-	[snd_soc_dapm_aif_in] = 3,
-	[snd_soc_dapm_aif_out] = 3,
 	[snd_soc_dapm_mic] = 4,
 	[snd_soc_dapm_mux] = 5,
 	[snd_soc_dapm_virt_mux] = 5,
@@ -69,6 +68,8 @@
 	[snd_soc_dapm_mixer] = 7,
 	[snd_soc_dapm_mixer_named_ctl] = 7,
 	[snd_soc_dapm_pga] = 8,
+	[snd_soc_dapm_aif_in] = 8,
+	[snd_soc_dapm_aif_out] = 8,
 	[snd_soc_dapm_adc] = 9,
 	[snd_soc_dapm_out_drv] = 10,
 	[snd_soc_dapm_hp] = 10,
@@ -78,6 +79,8 @@
 
 static int dapm_down_seq[] = {
 	[snd_soc_dapm_pre] = 0,
+	[snd_soc_dapm_aif_in] = 1,
+	[snd_soc_dapm_aif_out] = 1,
 	[snd_soc_dapm_adc] = 1,
 	[snd_soc_dapm_hp] = 2,
 	[snd_soc_dapm_spk] = 2,
@@ -91,8 +94,6 @@
 	[snd_soc_dapm_mux] = 9,
 	[snd_soc_dapm_virt_mux] = 9,
 	[snd_soc_dapm_value_mux] = 9,
-	[snd_soc_dapm_aif_in] = 10,
-	[snd_soc_dapm_aif_out] = 10,
 	[snd_soc_dapm_supply] = 11,
 	[snd_soc_dapm_post] = 12,
 };