Merge "vidc: 720p: Fix for H264 thumbnail generation" into msm-3.0
diff --git a/AndroidKernel.mk b/AndroidKernel.mk
index 97aa85d..50db52c 100644
--- a/AndroidKernel.mk
+++ b/AndroidKernel.mk
@@ -1,4 +1,5 @@
 #Android makefile to build kernel as a part of Android Build
+PERL		= perl
 
 ifeq ($(TARGET_PREBUILT_KERNEL),)
 
diff --git a/Documentation/DocBook/v4l/pixfmt.xml b/Documentation/DocBook/v4l/pixfmt.xml
index deb6602..8af0a42 100644
--- a/Documentation/DocBook/v4l/pixfmt.xml
+++ b/Documentation/DocBook/v4l/pixfmt.xml
@@ -741,10 +741,55 @@
 	  <row id="V4L2-PIX-FMT-MPEG">
 	    <entry><constant>V4L2_PIX_FMT_MPEG</constant></entry>
 	    <entry>'MPEG'</entry>
-	    <entry>MPEG stream. The actual format is determined by
+	    <entry>MPEG multiplexed stream. The actual format is determined by
 extended control <constant>V4L2_CID_MPEG_STREAM_TYPE</constant>, see
 <xref linkend="mpeg-control-id" />.</entry>
 	  </row>
+	  <row id="V4L2-PIX-FMT-H264">
+		<entry><constant>V4L2_PIX_FMT_H264</constant></entry>
+		<entry>'H264'</entry>
+		<entry>H264 video elementary stream with start codes.</entry>
+	  </row>
+	  <row id="V4L2-PIX-FMT-H264-NO-SC">
+		<entry><constant>V4L2_PIX_FMT_H264_NO_SC</constant></entry>
+		<entry>'AVC1'</entry>
+		<entry>H264 video elementary stream without start codes.</entry>
+	  </row>
+	  <row id="V4L2-PIX-FMT-H263">
+		<entry><constant>V4L2_PIX_FMT_H263</constant></entry>
+		<entry>'H263'</entry>
+		<entry>H263 video elementary stream.</entry>
+	  </row>
+	  <row id="V4L2-PIX-FMT-MPEG1">
+		<entry><constant>V4L2_PIX_FMT_MPEG1</constant></entry>
+		<entry>'MPG1'</entry>
+		<entry>MPEG1 video elementary stream.</entry>
+	  </row>
+	  <row id="V4L2-PIX-FMT-MPEG2">
+		<entry><constant>V4L2_PIX_FMT_MPEG2</constant></entry>
+		<entry>'MPG2'</entry>
+		<entry>MPEG2 video elementary stream.</entry>
+	  </row>
+	  <row id="V4L2-PIX-FMT-MPEG4">
+		<entry><constant>V4L2_PIX_FMT_MPEG4</constant></entry>
+		<entry>'MPG4'</entry>
+		<entry>MPEG4 video elementary stream.</entry>
+	  </row>
+	  <row id="V4L2-PIX-FMT-XVID">
+		<entry><constant>V4L2_PIX_FMT_XVID</constant></entry>
+		<entry>'XVID'</entry>
+		<entry>Xvid video elementary stream.</entry>
+	  </row>
+	  <row id="V4L2-PIX-FMT-VC1-ANNEX-G">
+		<entry><constant>V4L2_PIX_FMT_VC1_ANNEX_G</constant></entry>
+		<entry>'VC1G'</entry>
+		<entry>VC1, SMPTE 421M Annex G compliant stream.</entry>
+	  </row>
+	  <row id="V4L2-PIX-FMT-VC1-ANNEX-L">
+		<entry><constant>V4L2_PIX_FMT_VC1_ANNEX_L</constant></entry>
+		<entry>'VC1L'</entry>
+		<entry>VC1, SMPTE 421M Annex L compliant stream.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 81cbe40..8d3592e 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -129,4 +129,13 @@
 	  The uncompressor code port configuration is now handled
 	  by CONFIG_S3C_LOWLEVEL_UART_PORT.
 
+config PID_IN_CONTEXTIDR
+	bool "Write the current PID to the CONTEXTIDR register"
+	depends on CPU_COPY_V6
+	help
+	  Enabling this option causes the kernel to write the current PID to
+	  the PROCID field of the CONTEXTIDR register, at the expense of some
+	  additional instructions during context switch. Say Y here only if you
+	  are planning to use hardware trace tools with this kernel.
+
 endmenu
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index fc1d81a..76ff09c 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -201,6 +201,7 @@
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 3cf01a1..3ddb0c9 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -201,6 +201,7 @@
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 07aeb32..860e2bf 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -436,6 +436,7 @@
 CONFIG_ENABLE_DEFAULT_TRACERS=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
+CONFIG_PID_IN_CONTEXTIDR=y
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEV_QCRYPTO=m
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 47736ea..eb4244f 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -329,9 +329,9 @@
 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_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
@@ -451,6 +451,7 @@
 CONFIG_ENABLE_DEFAULT_TRACERS=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
+CONFIG_PID_IN_CONTEXTIDR=y
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEV_QCRYPTO=m
diff --git a/arch/arm/include/asm/fiq.h b/arch/arm/include/asm/fiq.h
index d493d0b..ec4b8b8 100644
--- a/arch/arm/include/asm/fiq.h
+++ b/arch/arm/include/asm/fiq.h
@@ -33,11 +33,22 @@
 	void *dev_id;
 };
 
+#ifdef CONFIG_FIQ
 extern int claim_fiq(struct fiq_handler *f);
 extern void release_fiq(struct fiq_handler *f);
 extern void set_fiq_handler(void *start, unsigned int length);
 extern void enable_fiq(int fiq);
 extern void disable_fiq(int fiq);
+#else
+static inline int claim_fiq(struct fiq_handler *f)
+{
+	return 0;
+}
+static inline void release_fiq(struct fiq_handler *f) { }
+static inline void set_fiq_handler(void *start, unsigned int length) { }
+static inline void enable_fiq(int fiq) { }
+static inline void disable_fiq(int fiq) { }
+#endif
 
 /* helpers defined in fiqasm.S: */
 extern void __set_fiq_regs(unsigned long const *regs);
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 6a7158b..0083033 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -73,10 +73,6 @@
 	enum arm_perf_pmu_ids id;
 	const char	*name;
 	irqreturn_t	(*handle_irq)(int irq_num, void *dev);
-#ifdef CONFIG_SMP
-	void            (*secondary_enable)(unsigned int irq);
-	void            (*secondary_disable)(unsigned int irq);
-#endif
 	void		(*enable)(struct hw_perf_event *evt, int idx);
 	void		(*disable)(struct hw_perf_event *evt, int idx);
 	int		(*get_event_idx)(struct cpu_hw_events *cpuc,
@@ -92,6 +88,8 @@
 				    [PERF_COUNT_HW_CACHE_OP_MAX]
 				    [PERF_COUNT_HW_CACHE_RESULT_MAX];
 	const unsigned	(*event_map)[PERF_COUNT_HW_MAX];
+	int	(*request_pmu_irq)(int irq, irq_handler_t *irq_h);
+	void	(*free_pmu_irq)(int irq);
 	u32		raw_event_mask;
 	int		num_events;
 	u64		max_period;
@@ -396,6 +394,21 @@
 }
 
 static int
+armpmu_generic_request_irq(int irq, irq_handler_t *handle_irq)
+{
+	return request_irq(irq, *handle_irq,
+			IRQF_DISABLED | IRQF_NOBALANCING,
+			"armpmu", NULL);
+}
+
+static void
+armpmu_generic_free_irq(int irq)
+{
+	if (irq >= 0)
+		free_irq(irq, NULL);
+}
+
+static int
 armpmu_reserve_hardware(void)
 {
 	struct arm_pmu_platdata *plat;
@@ -426,25 +439,20 @@
 		if (irq < 0)
 			continue;
 
-		err = request_irq(irq, handle_irq,
-				  IRQF_DISABLED | IRQF_NOBALANCING,
-				  "armpmu", NULL);
+		err = armpmu->request_pmu_irq(irq, &handle_irq);
+
 		if (err) {
 			pr_warning("unable to request IRQ%d for ARM perf "
 				"counters\n", irq);
 			break;
-#ifdef CONFIG_SMP
-		} else if (armpmu->secondary_enable) {
-			armpmu->secondary_enable(irq);
-#endif
 		}
 	}
 
 	if (err) {
 		for (i = i - 1; i >= 0; --i) {
 			irq = platform_get_irq(pmu_device, i);
-			if (irq >= 0)
-				free_irq(irq, NULL);
+
+			armpmu->free_pmu_irq(irq);
 		}
 		release_pmu(pmu_device);
 		pmu_device = NULL;
@@ -460,13 +468,7 @@
 
 	for (i = pmu_device->num_resources - 1; i >= 0; --i) {
 		irq = platform_get_irq(pmu_device, i);
-		if (irq >= 0) {
-			free_irq(irq, NULL);
-#ifdef CONFIG_SMP
-			if (armpmu->secondary_disable)
-				armpmu->secondary_disable(irq);
-#endif
-		}
+		armpmu->free_pmu_irq(irq);
 	}
 	armpmu->stop();
 
diff --git a/arch/arm/kernel/perf_event_msm.c b/arch/arm/kernel/perf_event_msm.c
index e37d2a7..a55ce3f 100644
--- a/arch/arm/kernel/perf_event_msm.c
+++ b/arch/arm/kernel/perf_event_msm.c
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -11,6 +11,8 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/cpumask.h>
+
 #include <asm/vfp.h>
 #include <asm/system.h>
 #include "../vfp/vfpinstr.h"
@@ -670,32 +672,52 @@
 	raw_spin_unlock_irqrestore(&pmu_lock, flags);
 }
 
-#ifdef CONFIG_SMP
-static void scorpion_secondary_enable_callback(void *info)
+static void enable_irq_callback(void *info)
 {
 	int irq = *(unsigned int *)info;
 
-	if (irq_get_chip(irq)->irq_unmask)
-		irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq));
+	enable_percpu_irq(irq, 0);
 }
-static void scorpion_secondary_disable_callback(void *info)
+
+static void disable_irq_callback(void *info)
 {
 	int irq = *(unsigned int *)info;
 
-	if (irq_get_chip(irq)->irq_mask)
-		irq_get_chip(irq)->irq_mask(irq_get_irq_data(irq));
+	disable_percpu_irq(irq);
 }
 
-static void scorpion_secondary_enable(unsigned int irq)
+static int
+msm_request_irq(int irq, irq_handler_t *handle_irq)
 {
-	smp_call_function(scorpion_secondary_enable_callback, &irq, 1);
+	int err = 0;
+	int cpu;
+
+	err = request_percpu_irq(irq, *handle_irq, "armpmu",
+			&cpu_hw_events);
+
+	if (!err) {
+		for_each_cpu(cpu, cpu_online_mask) {
+			smp_call_function_single(cpu,
+					enable_irq_callback, &irq, 1);
+		}
+	}
+
+	return err;
 }
 
-static void scorpion_secondary_disable(unsigned int irq)
+static void
+msm_free_irq(int irq)
 {
-	smp_call_function(scorpion_secondary_disable_callback, &irq, 1);
+	int cpu;
+
+	if (irq >= 0) {
+		for_each_cpu(cpu, cpu_online_mask) {
+			smp_call_function_single(cpu,
+					disable_irq_callback, &irq, 1);
+		}
+		free_percpu_irq(irq, &cpu_hw_events);
+	}
 }
-#endif
 
 static void scorpion_pmu_reset(void *info)
 {
@@ -719,10 +741,8 @@
 
 static struct arm_pmu scorpion_pmu = {
 	.handle_irq		= armv7pmu_handle_irq,
-#ifdef CONFIG_SMP
-	.secondary_enable       = scorpion_secondary_enable,
-	.secondary_disable      = scorpion_secondary_disable,
-#endif
+	.request_pmu_irq	= msm_request_irq,
+	.free_pmu_irq		= msm_free_irq,
 	.enable			= scorpion_pmu_enable_event,
 	.disable		= scorpion_pmu_disable_event,
 	.read_counter		= armv7pmu_read_counter,
diff --git a/arch/arm/kernel/perf_event_msm_krait.c b/arch/arm/kernel/perf_event_msm_krait.c
index 3c8fb84..1ce4dd6 100644
--- a/arch/arm/kernel/perf_event_msm_krait.c
+++ b/arch/arm/kernel/perf_event_msm_krait.c
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -498,10 +498,8 @@
 
 static struct arm_pmu krait_pmu = {
 	.handle_irq		= armv7pmu_handle_irq,
-#ifdef CONFIG_SMP
-	.secondary_enable       = scorpion_secondary_enable,
-	.secondary_disable      = scorpion_secondary_disable,
-#endif
+	.request_pmu_irq	= msm_request_irq,
+	.free_pmu_irq		= msm_free_irq,
 	.enable			= krait_pmu_enable_event,
 	.disable		= krait_pmu_disable_event,
 	.read_counter		= armv7pmu_read_counter,
diff --git a/arch/arm/kernel/perf_event_msm_krait_l2.c b/arch/arm/kernel/perf_event_msm_krait_l2.c
index 335ccaf..baa05ac 100644
--- a/arch/arm/kernel/perf_event_msm_krait_l2.c
+++ b/arch/arm/kernel/perf_event_msm_krait_l2.c
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -653,6 +653,8 @@
 	/* Avoid spurious interrupt if any */
 	get_reset_pmovsr();
 
+	raw_spin_lock_init(&hw_krait_l2_pmu.lock);
+
 	/* Don't return an arm_pmu here */
 	return NULL;
 }
diff --git a/arch/arm/kernel/perf_event_msm_l2.c b/arch/arm/kernel/perf_event_msm_l2.c
index c242754..26753d8 100644
--- a/arch/arm/kernel/perf_event_msm_l2.c
+++ b/arch/arm/kernel/perf_event_msm_l2.c
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -998,6 +998,8 @@
 	/* Avoid spurious interrupts at startup */
 	bb_l2_get_reset_pmovsr();
 
+	raw_spin_lock_init(&hw_bb_l2_pmu.lock);
+
 	/* Don't return an arm_pmu here */
 	return NULL;
 }
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index 0635b7e..8f9e4d0 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -611,6 +611,8 @@
 	.id			= ARM_PERF_PMU_ID_V6,
 	.name			= "v6",
 	.handle_irq		= armv6pmu_handle_irq,
+	.request_pmu_irq	= armpmu_generic_request_irq,
+	.free_pmu_irq		= armpmu_generic_free_irq,
 	.enable			= armv6pmu_enable_event,
 	.disable		= armv6pmu_disable_event,
 	.read_counter		= armv6pmu_read_counter,
@@ -641,6 +643,8 @@
 	.id			= ARM_PERF_PMU_ID_V6MP,
 	.name			= "v6mpcore",
 	.handle_irq		= armv6pmu_handle_irq,
+	.request_pmu_irq	= armpmu_generic_request_irq,
+	.free_pmu_irq		= armpmu_generic_free_irq,
 	.enable			= armv6pmu_enable_event,
 	.disable		= armv6mpcore_pmu_disable_event,
 	.read_counter		= armv6pmu_read_counter,
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 3689e07..beb25c2 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -1178,6 +1178,8 @@
 
 static struct arm_pmu armv7pmu = {
 	.handle_irq		= armv7pmu_handle_irq,
+	.request_pmu_irq	= armpmu_generic_request_irq,
+	.free_pmu_irq		= armpmu_generic_free_irq,
 	.enable			= armv7pmu_enable_event,
 	.disable		= armv7pmu_disable_event,
 	.read_counter		= armv7pmu_read_counter,
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c
index 21977cf..aeb9d95 100644
--- a/arch/arm/kernel/perf_event_xscale.c
+++ b/arch/arm/kernel/perf_event_xscale.c
@@ -776,6 +776,8 @@
 	.id		= ARM_PERF_PMU_ID_XSCALE2,
 	.name		= "xscale2",
 	.handle_irq	= xscale2pmu_handle_irq,
+	.request_pmu_irq = armpmu_generic_request_irq,
+	.free_pmu_irq	= armpmu_generic_free_irq,
 	.enable		= xscale2pmu_enable_event,
 	.disable	= xscale2pmu_disable_event,
 	.read_counter	= xscale2pmu_read_counter,
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 0cec5f2..3f04ce0 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -8,6 +8,7 @@
 	select MSM_VIC
 	select CPU_V6
 	select MSM_REMOTE_SPINLOCK_SWP
+	select MSM_PM if PM
 
 config ARCH_MSM7X25
 	bool "MSM7x25"
@@ -16,6 +17,7 @@
 	select CPU_V6
 	select MSM_REMOTE_SPINLOCK_SWP
 	select MULTI_IRQ_HANDLER
+	select MSM_PM if PM
 
 config ARCH_MSM7X27
 	bool "MSM7x27"
@@ -32,6 +34,7 @@
 	select MSM_PROC_COMM_REGULATOR
 	select CLEANCACHE
 	select QCACHE
+	select MSM_PM2 if PM
 
 config ARCH_MSM7X30
 	bool "MSM7x30"
@@ -55,6 +58,7 @@
 	select REGULATOR
 	select MSM_PROC_COMM_REGULATOR
 	select MULTI_IRQ_HANDLER
+	select MSM_PM2 if PM
 
 config ARCH_QSD8X50
 	bool "QSD8X50"
@@ -66,6 +70,7 @@
 	select EMULATE_DOMAIN_MANAGER_V7
 	select MSM_GPIOMUX
 	select MSM_DALRPC
+	select MSM_PM2 if PM
 
 config ARCH_MSM8X60
 	bool "MSM8X60"
@@ -121,6 +126,7 @@
 	select MSM_SPM_V1
 	select MSM_SCM if SMP
 	select MULTI_IRQ_HANDLER
+	select MSM_PM8X60 if PM
 
 config ARCH_MSM8960
 	bool "MSM8960"
@@ -159,6 +165,7 @@
 	select QCACHE
 	select MSM_MULTIMEDIA_USE_ION
 	select MULTI_IRQ_HANDLER
+	select MSM_PM8X60 if PM
 
 config ARCH_MSM8930
 	bool "MSM8930"
@@ -195,6 +202,7 @@
 	select FIX_MOVABLE_ZONE
 	select MSM_ULTRASOUND
 	select MULTI_IRQ_HANDLER
+	select MSM_PM8X60 if PM
 
 config ARCH_APQ8064
 	bool "APQ8064"
@@ -212,6 +220,7 @@
 	select MSM_RPM
 	select MSM_SPM_V2
 	select MSM_L2_SPM
+	select MSM_PM8X60 if PM
 
 config ARCH_MSMCOPPER
 	bool "MSM Copper"
@@ -247,6 +256,7 @@
 	select REGULATOR
 	select MSM_RPM_REGULATOR
 	select MULTI_IRQ_HANDLER
+	select MSM_PM8X60 if PM
 
 config ARCH_MSM8625
 	bool "MSM8625"
@@ -1840,6 +1850,22 @@
 config MSM_NATIVE_RESTART
 	bool
 
+config MSM_PM
+	depends on PM
+	bool
+
+config MSM_PM2
+	depends on PM
+	bool
+
+config MSM_PM8X60
+	depends on PM
+	bool
+
+config MSM_NOPM
+	default y if !PM
+	bool
+
 config MSM_BUS_SCALING
 	bool "Bus scaling driver"
 	default n
@@ -2017,4 +2043,21 @@
 	  instead of pmem. Selecting this may also involve userspace
 	  dependencies as well.
 
+config MSM_RTB
+	bool "Register tracing"
+	help
+	  Add support for logging different events to a small uncached
+	  region. This is designed to aid in debugging reset cases where the
+	  caches may not be flushed before the target resets.
+
+config MSM_RTB_SEPARATE_CPUS
+	bool "Separate entries for each cpu"
+	depends on MSM_RTB
+	help
+	  Under some circumstances, it may be beneficial to give dedicated space
+	  for each cpu to log accesses. Selecting this option will log each cpu
+	  separately. This will guarantee that the last acesses for each cpu
+	  will be logged but there will be fewer entries per cpu
+
+
 endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 6581619..939b036 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -140,21 +140,11 @@
 obj-$(CONFIG_MSM8X60_AUDIO) += qdsp6v2/
 obj-$(CONFIG_MSM_AUDIO_QDSP6) += qdsp6v2/
 obj-$(CONFIG_MSM_HW3D) += hw3d.o
-ifdef CONFIG_PM
-	obj-$(CONFIG_ARCH_APQ8064) += pm-8x60.o
-	obj-$(CONFIG_ARCH_MSM8960) += pm-8x60.o
-	obj-$(CONFIG_ARCH_MSM8X60) += pm-8x60.o
-	obj-$(CONFIG_ARCH_MSM9615) += pm-8x60.o
-	obj-$(CONFIG_ARCH_QSD8X50) += pm2.o
-	obj-$(CONFIG_ARCH_MSM7X30) += pm2.o
-	obj-$(CONFIG_ARCH_MSM7X27) += pm2.o
-	obj-$(CONFIG_ARCH_MSM7X27A) += pm2.o
-	obj-$(CONFIG_ARCH_MSM7X25) += pm.o
-	obj-$(CONFIG_ARCH_MSM7X01A) += pm.o
-	obj-y += pm-boot.o
-else
-	obj-y += no-pm.o
-endif
+obj-$(CONFIG_PM) += pm-boot.o
+obj-$(CONFIG_MSM_PM8X60) += pm-8x60.o
+obj-$(CONFIG_MSM_PM2) += pm2.o
+obj-$(CONFIG_MSM_PM) += pm.o
+obj-$(CONFIG_MSM_NOPM) += no-pm.o
 
 obj-$(CONFIG_MSM_SPM_V1) += spm.o
 obj-$(CONFIG_MSM_SPM_V2) += spm-v2.o spm_devices.o
@@ -242,7 +232,7 @@
 obj-$(CONFIG_ARCH_APQ8064) += devices-8960.o devices-8064.o
 board-8960-all-objs += board-8960.o board-8960-camera.o board-8960-display.o board-8960-pmic.o board-8960-storage.o board-8960-gpiomux.o
 board-8930-all-objs += board-8930.o board-8930-camera.o board-8930-display.o board-8930-pmic.o board-8930-storage.o board-8930-gpiomux.o devices-8930.o
-board-8064-all-objs += board-8064.o board-8064-pmic.o board-8064-storage.o board-8064-gpiomux.o board-8064-camera.o board-8064-display.o
+board-8064-all-objs += board-8064.o board-8064-pmic.o board-8064-storage.o board-8064-gpiomux.o board-8064-camera.o board-8064-display.o board-8064-gpu.o
 obj-$(CONFIG_MACH_MSM8960_SIM) += board-8960-all.o board-8960-regulator.o
 obj-$(CONFIG_MACH_MSM8960_RUMI3) += board-8960-all.o board-8960-regulator.o
 obj-$(CONFIG_MACH_MSM8960_CDP) += board-8960-all.o board-8960-regulator.o
@@ -324,3 +314,4 @@
 endif
 
 obj-$(CONFIG_ARCH_MSM8960) += mdm2.o mdm_common.o
+obj-$(CONFIG_MSM_RTB) += msm_rtb.o
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 408f77b..61c742d 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -734,25 +734,28 @@
 }
 
 /* Enable an already-configured HFPLL. */
-static void hfpll_enable(struct scalable *sc)
+static void hfpll_enable(struct scalable *sc, bool skip_regulators)
 {
 	int rc;
 
-	if (cpu_is_msm8960()) {
-		rc = rpm_vreg_set_voltage(sc->vreg[VREG_HFPLL_A].rpm_vreg_id,
-				sc->vreg[VREG_HFPLL_A].rpm_vreg_voter, 2100000,
-				sc->vreg[VREG_HFPLL_A].max_vdd, 0);
+	if (!skip_regulators) {
+		if (cpu_is_msm8960()) {
+			rc = rpm_vreg_set_voltage(
+					sc->vreg[VREG_HFPLL_A].rpm_vreg_id,
+					sc->vreg[VREG_HFPLL_A].rpm_vreg_voter,
+					2100000,
+					sc->vreg[VREG_HFPLL_A].max_vdd, 0);
+			if (rc)
+				pr_err("%s regulator enable failed (%d)\n",
+					sc->vreg[VREG_HFPLL_A].name, rc);
+		}
+		rc = rpm_vreg_set_voltage(sc->vreg[VREG_HFPLL_B].rpm_vreg_id,
+				sc->vreg[VREG_HFPLL_B].rpm_vreg_voter, 1800000,
+				sc->vreg[VREG_HFPLL_B].max_vdd, 0);
 		if (rc)
 			pr_err("%s regulator enable failed (%d)\n",
-				sc->vreg[VREG_HFPLL_A].name, rc);
+				sc->vreg[VREG_HFPLL_B].name, rc);
 	}
-	rc = rpm_vreg_set_voltage(sc->vreg[VREG_HFPLL_B].rpm_vreg_id,
-			sc->vreg[VREG_HFPLL_B].rpm_vreg_voter, 1800000,
-			sc->vreg[VREG_HFPLL_B].max_vdd, 0);
-	if (rc)
-		pr_err("%s regulator enable failed (%d)\n",
-			sc->vreg[VREG_HFPLL_B].name, rc);
-
 	/* Disable PLL bypass mode. */
 	writel_relaxed(0x2, sc->hfpll_base + HFPLL_MODE);
 
@@ -775,7 +778,7 @@
 }
 
 /* Disable a HFPLL for power-savings or while its being reprogrammed. */
-static void hfpll_disable(struct scalable *sc)
+static void hfpll_disable(struct scalable *sc, bool skip_regulators)
 {
 	int rc;
 
@@ -785,20 +788,23 @@
 	 */
 	writel_relaxed(0, sc->hfpll_base + HFPLL_MODE);
 
-	rc = rpm_vreg_set_voltage(sc->vreg[VREG_HFPLL_B].rpm_vreg_id,
-			sc->vreg[VREG_HFPLL_B].rpm_vreg_voter, 0,
-			0, 0);
-	if (rc)
-		pr_err("%s regulator enable failed (%d)\n",
-			sc->vreg[VREG_HFPLL_B].name, rc);
-
-	if (cpu_is_msm8960()) {
-		rc = rpm_vreg_set_voltage(sc->vreg[VREG_HFPLL_A].rpm_vreg_id,
-				sc->vreg[VREG_HFPLL_A].rpm_vreg_voter, 0,
+	if (!skip_regulators) {
+		rc = rpm_vreg_set_voltage(sc->vreg[VREG_HFPLL_B].rpm_vreg_id,
+				sc->vreg[VREG_HFPLL_B].rpm_vreg_voter, 0,
 				0, 0);
 		if (rc)
 			pr_err("%s regulator enable failed (%d)\n",
-				sc->vreg[VREG_HFPLL_A].name, rc);
+				sc->vreg[VREG_HFPLL_B].name, rc);
+
+		if (cpu_is_msm8960()) {
+			rc = rpm_vreg_set_voltage(
+					sc->vreg[VREG_HFPLL_A].rpm_vreg_id,
+					sc->vreg[VREG_HFPLL_A].rpm_vreg_voter,
+					0, 0, 0);
+			if (rc)
+				pr_err("%s regulator enable failed (%d)\n",
+					sc->vreg[VREG_HFPLL_A].name, rc);
+		}
 	}
 }
 
@@ -862,9 +868,9 @@
 		set_pri_clk_src(sc, PRI_SRC_SEL_SEC_SRC);
 
 		/* Program CPU HFPLL. */
-		hfpll_disable(sc);
+		hfpll_disable(sc, 1);
 		hfpll_set_rate(sc, tgt_s);
-		hfpll_enable(sc);
+		hfpll_enable(sc, 1);
 
 		/* Move CPU to HFPLL source. */
 		set_pri_clk_src(sc, tgt_s->pri_src_sel);
@@ -880,10 +886,10 @@
 			set_sec_clk_src(sc, tgt_s->sec_src_sel);
 			set_pri_clk_src(sc, tgt_s->pri_src_sel);
 		}
-		hfpll_disable(sc);
+		hfpll_disable(sc, 0);
 	} else if (strt_s->src != HFPLL && tgt_s->src == HFPLL) {
 		hfpll_set_rate(sc, tgt_s);
-		hfpll_enable(sc);
+		hfpll_enable(sc, 0);
 		/*
 		 * If responding to CPU_UP_PREPARE, we can't change CP15
 		 * registers for the CPU that's coming up since we're not
@@ -1141,7 +1147,7 @@
 	pr_debug("Initializing HFPLL%d\n", sc - scalable);
 
 	/* Disable the PLL for re-programming. */
-	hfpll_disable(sc);
+	hfpll_disable(sc, 0);
 
 	/* Configure PLL parameters for integer mode. */
 	writel_relaxed(0x7845C665, sc->hfpll_base + HFPLL_CONFIG_CTL);
@@ -1153,11 +1159,11 @@
 
 	/* Set an initial rate and enable the PLL. */
 	hfpll_set_rate(sc, tgt_s);
-	hfpll_enable(sc);
+	hfpll_enable(sc, 0);
 }
 
 /* Voltage regulator initialization. */
-static void __init regulator_init(void)
+static void __init regulator_init(int set_vdd)
 {
 	int cpu, ret;
 	struct scalable *sc;
@@ -1174,7 +1180,7 @@
 		}
 
 		ret = regulator_set_voltage(sc->vreg[VREG_CORE].reg,
-					    sc->vreg[VREG_CORE].max_vdd,
+					    set_vdd,
 					    sc->vreg[VREG_CORE].max_vdd);
 		if (ret)
 			pr_err("regulator_set_voltage(%s) failed"
@@ -1228,7 +1234,7 @@
 }
 
 /* Register with bus driver. */
-static void __init bus_init(void)
+static void __init bus_init(unsigned int init_bw)
 {
 	int ret;
 
@@ -1238,8 +1244,7 @@
 		BUG();
 	}
 
-	ret = msm_bus_scale_client_update_request(bus_perf_client,
-		(ARRAY_SIZE(bw_level_tbl)-1));
+	ret = msm_bus_scale_client_update_request(bus_perf_client, init_bw);
 	if (ret)
 		pr_err("initial bandwidth request failed (%d)\n", ret);
 }
@@ -1443,11 +1448,13 @@
 static int __init acpuclk_8960_init(struct acpuclk_soc_data *soc_data)
 {
 	struct acpu_level *max_acpu_level = select_freq_plan();
+
+	regulator_init(max_acpu_level->vdd_core);
+	bus_init(max_acpu_level->l2_level->bw_level);
+
 	init_clock_sources(&scalable[L2], &max_acpu_level->l2_level->speed);
 	on_each_cpu(per_cpu_init, max_acpu_level, true);
 
-	regulator_init();
-	bus_init();
 	cpufreq_table_init();
 
 	acpuclk_register(&acpuclk_8960_data);
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 05c5a2b..f1abde4 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -207,6 +207,7 @@
 static struct completion bam_connection_completion;
 static struct delayed_work ul_timeout_work;
 static int ul_packet_written;
+static atomic_t ul_ondemand_vote = ATOMIC_INIT(0);
 static struct clk *dfab_clk;
 static DEFINE_RWLOCK(ul_wakeup_lock);
 static DECLARE_WORK(kickoff_ul_wakeup, kickoff_ul_wakeup_func);
@@ -221,6 +222,7 @@
 static DEFINE_SPINLOCK(wakelock_reference_lock);
 static int wakelock_reference_count;
 static struct delayed_work msm9615_bam_init_work;
+static int a2_pc_disabled_wakelock_skipped;
 /* End A2 power collaspe */
 
 /* subsystem restart */
@@ -291,9 +293,10 @@
 	 * U: 1 = Uplink active
 	 * W: 1 = Uplink Wait-for-ack
 	 * A: 1 = Uplink ACK received
+	 * #: >=1 On-demand uplink vote
 	 */
 	len += scnprintf(buff, sizeof(buff),
-		"<DMUX> %u.%09lu %c%c%c%c %c%c%c%c ",
+		"<DMUX> %u.%09lu %c%c%c%c %c%c%c%c%d ",
 		(unsigned)t_now, nanosec_rem,
 		a2_pc_disabled ? 'D' : 'd',
 		in_global_reset ? 'R' : 'r',
@@ -302,7 +305,8 @@
 		bam_dmux_uplink_vote ? 'V' : 'v',
 		bam_is_connected ?  'U' : 'u',
 		wait_for_ack ? 'W' : 'w',
-		ul_wakeup_ack_completion.done ? 'A' : 'a'
+		ul_wakeup_ack_completion.done ? 'A' : 'a',
+		atomic_read(&ul_ondemand_vote)
 		);
 
 	va_start(arg_list, fmt);
@@ -1228,6 +1232,7 @@
 			"\tU: 1 = Uplink active\n"
 			"\tW: 1 = Uplink Wait-for-ack\n"
 			"\tA: 1 = Uplink ACK received\n"
+			"\t#: >=1 On-demand uplink vote\n"
 				);
 		buff += i;
 	}
@@ -1362,9 +1367,18 @@
 	read_unlock(&ul_wakeup_lock);
 }
 
-void msm_bam_dmux_kickoff_ul_wakeup(void)
+int msm_bam_dmux_kickoff_ul_wakeup(void)
 {
-	queue_work(bam_mux_tx_workqueue, &kickoff_ul_wakeup);
+	int is_connected;
+
+	read_lock(&ul_wakeup_lock);
+	ul_packet_written = 1;
+	is_connected = bam_is_connected;
+	if (!is_connected)
+		queue_work(bam_mux_tx_workqueue, &kickoff_ul_wakeup);
+	read_unlock(&ul_wakeup_lock);
+
+	return is_connected;
 }
 
 static void power_vote(int vote)
@@ -1412,6 +1426,43 @@
 	}
 }
 
+/*
+ * Votes for UL power and returns current power state.
+ *
+ * @returns true if currently connected
+ */
+int msm_bam_dmux_ul_power_vote(void)
+{
+	int is_connected;
+
+	read_lock(&ul_wakeup_lock);
+	atomic_inc(&ul_ondemand_vote);
+	is_connected = bam_is_connected;
+	if (!is_connected)
+		queue_work(bam_mux_tx_workqueue, &kickoff_ul_wakeup);
+	read_unlock(&ul_wakeup_lock);
+
+	return is_connected;
+}
+
+/*
+ * Unvotes for UL power.
+ *
+ * @returns true if vote count is 0 (UL shutdown possible)
+ */
+int msm_bam_dmux_ul_power_unvote(void)
+{
+	int vote;
+
+	read_lock(&ul_wakeup_lock);
+	vote = atomic_dec_return(&ul_ondemand_vote);
+	if (unlikely(vote) < 0)
+		DMUX_LOG_KERR("%s: invalid power vote %d\n", __func__, vote);
+	read_unlock(&ul_wakeup_lock);
+
+	return vote == 0;
+}
+
 static void ul_timeout(struct work_struct *work)
 {
 	unsigned long flags;
@@ -1441,8 +1492,9 @@
 			spin_unlock(&bam_tx_pool_spinlock);
 		}
 
-		if (ul_packet_written) {
-			bam_dmux_log("%s: packet written\n", __func__);
+		if (ul_packet_written || atomic_read(&ul_ondemand_vote)) {
+			bam_dmux_log("%s: pkt written %d\n",
+				__func__, ul_packet_written);
 			ul_packet_written = 0;
 			schedule_delayed_work(&ul_timeout_work,
 					msecs_to_jiffies(UL_TIMEOUT_DELAY));
@@ -1476,7 +1528,6 @@
 static void ul_wakeup(void)
 {
 	int ret;
-	static int called_before;
 
 	mutex_lock(&wakeup_lock);
 	if (bam_is_connected) { /* bam got connected before lock grabbed */
@@ -1490,10 +1541,10 @@
 		 * don't grab the wakelock the first time because it is
 		 * already grabbed when a2 powers on
 		 */
-		if (likely(called_before))
+		if (likely(a2_pc_disabled_wakelock_skipped))
 			grab_wakelock();
 		else
-			called_before = 1;
+			a2_pc_disabled_wakelock_skipped = 1;
 		if (wait_for_dfab) {
 			ret = wait_for_completion_timeout(
 					&dfab_unvote_completion, HZ);
@@ -1717,6 +1768,7 @@
 	write_unlock_irqrestore(&ul_wakeup_lock, flags);
 	ul_powerdown_finish();
 	a2_pc_disabled = 0;
+	a2_pc_disabled_wakelock_skipped = 0;
 
 	/* Cleanup Channel States */
 	for (i = 0; i < BAM_DMUX_NUM_CHANNELS; ++i) {
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index 3075e07..57f4a0a 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.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
@@ -83,7 +83,25 @@
 	.pull = GPIOMUX_PULL_KEEPER,
 };
 
+static struct gpiomux_setting gsbi1_uart_config = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_16MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
 static struct msm_gpiomux_config apq8064_gsbi_configs[] __initdata = {
+	{
+		.gpio      = 18,		/* GSBI1 UART TX */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi1_uart_config,
+		},
+	},
+	{
+		.gpio      = 19,		/* GSBI1 UART RX */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi1_uart_config,
+		},
+	},
 #if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
 	{
 		.gpio      = 51,		/* GSBI5 QUP SPI_DATA_MOSI */
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
new file mode 100644
index 0000000..a8c5d48
--- /dev/null
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -0,0 +1,173 @@
+/* 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/platform_device.h>
+#include <linux/msm_kgsl.h>
+#include <mach/msm_bus_board.h>
+#include <mach/board.h>
+
+#include "devices.h"
+#include "board-8064.h"
+
+#ifdef CONFIG_MSM_BUS_SCALING
+static struct msm_bus_vectors grp3d_init_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = 0,
+	},
+};
+
+static struct msm_bus_vectors grp3d_low_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = KGSL_CONVERT_TO_MBPS(2000),
+	},
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = KGSL_CONVERT_TO_MBPS(2000),
+	},
+};
+
+static struct msm_bus_vectors grp3d_nominal_high_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = KGSL_CONVERT_TO_MBPS(3200),
+	},
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = KGSL_CONVERT_TO_MBPS(3200),
+	},
+};
+
+static struct msm_bus_vectors grp3d_max_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = KGSL_CONVERT_TO_MBPS(4264),
+	},
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = KGSL_CONVERT_TO_MBPS(4264),
+	},
+};
+
+static struct msm_bus_paths grp3d_bus_scale_usecases[] = {
+	{
+		ARRAY_SIZE(grp3d_init_vectors),
+		grp3d_init_vectors,
+	},
+	{
+		ARRAY_SIZE(grp3d_low_vectors),
+		grp3d_low_vectors,
+	},
+	{
+		ARRAY_SIZE(grp3d_nominal_high_vectors),
+		grp3d_nominal_high_vectors,
+	},
+	{
+		ARRAY_SIZE(grp3d_max_vectors),
+		grp3d_max_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata grp3d_bus_scale_pdata = {
+	grp3d_bus_scale_usecases,
+	ARRAY_SIZE(grp3d_bus_scale_usecases),
+	.name = "grp3d",
+};
+#endif
+
+static struct resource kgsl_3d0_resources[] = {
+	{
+		.name = KGSL_3D0_REG_MEMORY,
+		.start = 0x04300000, /* GFX3D address */
+		.end = 0x0431ffff,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = KGSL_3D0_IRQ,
+		.start = GFX3D_IRQ,
+		.end = GFX3D_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct kgsl_device_platform_data kgsl_3d0_pdata = {
+	.pwrlevel = {
+		{
+			.gpu_freq = 400000000,
+			.bus_freq = 4,
+			.io_fraction = 0,
+		},
+		{
+			.gpu_freq = 320000000,
+			.bus_freq = 3,
+			.io_fraction = 33,
+		},
+		{
+			.gpu_freq = 1920000000,
+			.bus_freq = 2,
+			.io_fraction = 100,
+		},
+		{
+			.gpu_freq = 27000000,
+			.bus_freq = 0,
+		},
+	},
+	.init_level = 0,
+	.num_levels = 4,
+	.set_grp_async = NULL,
+	.idle_timeout = HZ/20,
+	.nap_allowed = true,
+	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE,
+#ifdef CONFIG_MSM_BUS_SCALING
+	.bus_scale_table = &grp3d_bus_scale_pdata,
+#endif
+	.iommu_user_ctx_name = "gfx3d_user",
+	.iommu_priv_ctx_name = NULL,
+};
+
+struct platform_device device_kgsl_3d0 = {
+	.name = "kgsl-3d0",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(kgsl_3d0_resources),
+	.resource = kgsl_3d0_resources,
+	.dev = {
+		.platform_data = &kgsl_3d0_pdata,
+	},
+};
+
+void __init apq8064_init_gpu(void)
+{
+	platform_device_register(&device_kgsl_3d0);
+}
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 032d8da..2182079 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -43,12 +43,19 @@
 	.dev_id			= 0,
 };
 
+static struct pm8xxx_rtc_platform_data
+apq8064_pm8921_rtc_pdata = {
+	.rtc_write_enable       = false,
+	.rtc_alarm_powerup      = false,
+};
+
 static struct pm8921_platform_data
 apq8064_pm8921_platform_data __devinitdata = {
 	.regulator_pdatas	= msm8064_pm8921_regulator_pdata,
 	.irq_pdata		= &apq8064_pm8921_irq_pdata,
 	.gpio_pdata		= &apq8064_pm8921_gpio_pdata,
 	.mpp_pdata		= &apq8064_pm8921_mpp_pdata,
+	.rtc_pdata		= &apq8064_pm8921_rtc_pdata,
 };
 
 static struct pm8xxx_irq_platform_data
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 6e3612a..7267f96 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -109,6 +109,7 @@
 };
 VREG_CONSUMERS(L26) = {
 	REGULATOR_SUPPLY("8921_l26",		NULL),
+	REGULATOR_SUPPLY("core_vdd",		"pil_qdsp6v4.0"),
 };
 VREG_CONSUMERS(L27) = {
 	REGULATOR_SUPPLY("8921_l27",		NULL),
@@ -174,6 +175,7 @@
 };
 VREG_CONSUMERS(LVS7) = {
 	REGULATOR_SUPPLY("8921_lvs7",		NULL),
+	REGULATOR_SUPPLY("pll_vdd",		"pil_riva"),
 };
 VREG_CONSUMERS(USB_OTG) = {
 	REGULATOR_SUPPLY("8921_usb_otg",	NULL),
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 29b8afb..3e99b2a 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1076,6 +1076,8 @@
 	&msm_bus_8064_sys_fpb,
 	&msm_bus_8064_cpss_fpb,
 	&msm_device_vidc,
+	&msm_8960_riva,
+	&msm_8960_q6_lpass,
 };
 
 static struct platform_device *sim_devices[] __initdata = {
@@ -1192,6 +1194,7 @@
 	msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
 				msm_pm_data);
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
+
 }
 
 static void __init apq8064_allocate_memory_regions(void)
@@ -1216,6 +1219,7 @@
 	platform_add_devices(rumi3_devices, ARRAY_SIZE(rumi3_devices));
 	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 	apq8064_init_fb();
+	apq8064_init_gpu();
 }
 
 static void __init apq8064_cdp_init(void)
@@ -1224,6 +1228,7 @@
 	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_gpu();
 }
 
 MACHINE_START(APQ8064_SIM, "QCT APQ8064 SIMULATOR")
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index 916e569..4735504 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -44,6 +44,7 @@
 void apq8064_init_mmc(void);
 void apq8064_init_gpiomux(void);
 void apq8064_init_pmic(void);
+
 extern struct msm_camera_board_info apq8064_camera_board_info;
 void apq8064_init_cam(void);
 #define APQ_8064_GSBI4_QUP_I2C_BUS_ID 4
@@ -51,4 +52,7 @@
 void apq8064_init_fb(void);
 void apq8064_allocate_fb_region(void);
 void apq8064_mdp_writeback(struct memtype_reserve *reserve_table);
+
+void apq8064_init_gpu(void);
+
 #endif
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index 6c01764..0208631 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -30,6 +30,9 @@
 	REGULATOR_SUPPLY("8038_l2",		NULL),
 	REGULATOR_SUPPLY("iris_vdddig",		"wcnss_wlan.0"),
 	REGULATOR_SUPPLY("dsi_vdda",		"mipi_dsi.1"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-001a"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-006c"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-0048"),
 };
 VREG_CONSUMERS(L3) = {
 	REGULATOR_SUPPLY("8038_l3",		NULL),
@@ -59,6 +62,12 @@
 	REGULATOR_SUPPLY("8038_l9",		NULL),
 	REGULATOR_SUPPLY("vdd_ana",		"3-004a"),
 	REGULATOR_SUPPLY("vdd",			"3-0024"),
+	REGULATOR_SUPPLY("cam_vana",		"4-001a"),
+	REGULATOR_SUPPLY("cam_vana",		"4-006c"),
+	REGULATOR_SUPPLY("cam_vana",		"4-0048"),
+	REGULATOR_SUPPLY("cam_vaf",		"4-001a"),
+	REGULATOR_SUPPLY("cam_vaf",		"4-006c"),
+	REGULATOR_SUPPLY("cam_vaf",		"4-0048"),
 };
 VREG_CONSUMERS(L10) = {
 	REGULATOR_SUPPLY("8038_l10",		NULL),
@@ -76,6 +85,9 @@
 };
 VREG_CONSUMERS(L12) = {
 	REGULATOR_SUPPLY("8038_l12",		NULL),
+	REGULATOR_SUPPLY("cam_vdig",		"4-001a"),
+	REGULATOR_SUPPLY("cam_vdig",		"4-006c"),
+	REGULATOR_SUPPLY("cam_vdig",		"4-0048"),
 };
 VREG_CONSUMERS(L14) = {
 	REGULATOR_SUPPLY("8038_l14",		NULL),
@@ -93,6 +105,9 @@
 };
 VREG_CONSUMERS(L18) = {
 	REGULATOR_SUPPLY("8038_l18",		NULL),
+	REGULATOR_SUPPLY("cam_vio",		"4-001a"),
+	REGULATOR_SUPPLY("cam_vio",		"4-006c"),
+	REGULATOR_SUPPLY("cam_vio",		"4-0048"),
 };
 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 fc91337..f080d50 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -30,7 +30,6 @@
 #ifdef CONFIG_ANDROID_PMEM
 #include <linux/android_pmem.h>
 #endif
-#include <linux/cyttsp.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_data/qcom_crypto_device.h>
 #include <linux/platform_data/qcom_wcnss_device.h>
@@ -1339,128 +1338,6 @@
 	},
 };
 
-#define CYTTSP_TS_GPIO_IRQ		11
-#define CYTTSP_TS_SLEEP_GPIO		50
-#define CYTTSP_TS_RESOUT_N_GPIO		52
-
-/*virtual key support */
-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 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_SLEEP_CURR_UA,
-	},
-	/* TODO: Remove after runtime PM is enabled in I2C driver */
-	{
-		.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_SLEEP_CURR_UA,
-	},
-};
-
-static struct cyttsp_platform_data cyttsp_pdata = {
-	.panel_maxx = 634,
-	.panel_maxy = 1166,
-	.disp_maxx = 616,
-	.disp_maxy = 1023,
-	.disp_minx = 0,
-	.disp_miny = 16,
-	.flags = 0x01,
-	.gen = CY_GEN3,	/* or */
-	.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 | CY_USE_LOW_POWER_SEL,
-	.use_gestures = CY_USE_GESTURES,
-	.fw_fname = "cyttsp_8960_cdp.hex",
-	/* activate up to 4 groups
-	 * and set active distance
-	 */
-	.gest_set = CY_GEST_GRP1 | CY_GEST_GRP2 |
-				CY_GEST_GRP3 | CY_GEST_GRP4 |
-				CY_ACT_DIST,
-	/* 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_SLEEP_GPIO,
-	.resout_gpio = CYTTSP_TS_RESOUT_N_GPIO,
-	.irq_gpio = CYTTSP_TS_GPIO_IRQ,
-	.regulator_info = regulator_data,
-	.num_regulators = ARRAY_SIZE(regulator_data),
-	.init = cyttsp_platform_init,
-	.correct_fw_ver = 9,
-};
-
-static struct i2c_board_info cyttsp_info[] __initdata = {
-	{
-		I2C_BOARD_INFO(CY_I2C_NAME, 0x24),
-		.platform_data = &cyttsp_pdata,
-#ifndef CY_USE_TIMER
-		.irq = MSM_GPIO_TO_INT(CYTTSP_TS_GPIO_IRQ),
-#endif /* CY_USE_TIMER */
-	},
-};
-
 #define MXT_TS_GPIO_IRQ			11
 #define MXT_TS_RESET_GPIO		52
 
@@ -1475,8 +1352,8 @@
 	 27, 0, 5, 1, 0, 0, 8, 8, 0, 0,
 	/* T9 Object */
 	 131, 0, 0, 19, 11, 0, 16, 35, 1, 3,
-	 10, 15, 1, 11, 4, 5, 40, 10, 54, 2,
-	 43, 4, 0, 0, 0, 0, 143, 40, 143, 80,
+	 10, 15, 1, 11, 4, 5, 40, 10, 43, 4,
+	 54, 2, 0, 0, 0, 0, 143, 40, 143, 80,
 	 18, 15, 50, 50, 2,
 	/* T15 Object */
 	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -1513,10 +1390,10 @@
 			struct kobj_attribute *attr, char *buf)
 {
 	return snprintf(buf, 200,
-	__stringify(EV_KEY) ":" __stringify(KEY_BACK) ":65:938:90:90"
-	":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":208:938:90:90"
-	":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":348:938:90:90"
-	":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":490:938:90:90"
+	__stringify(EV_KEY) ":" __stringify(KEY_BACK) ":57:1030:90:90"
+	":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":206:1030:90:90"
+	":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":366:1030:90:90"
+	":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":503:1030:90:90"
 	"\n");
 }
 
@@ -1568,8 +1445,10 @@
 static struct mxt_platform_data mxt_platform_data_8930 = {
 	.config_array		= mxt_config_array,
 	.config_array_size	= ARRAY_SIZE(mxt_config_array),
-	.x_size			= 1067,
-	.y_size			= 566,
+	.x_size			= 540,
+	.y_size			= 960,
+	.touch_x_size		= 566,
+	.touch_y_size		= 1067,
 	.irqflags		= IRQF_TRIGGER_FALLING,
 #ifdef MSM8930_PHASE_2
 	.digital_pwr_regulator	= true,
@@ -2140,12 +2019,6 @@
 		ARRAY_SIZE(isl_charger_i2c_info),
 	},
 #endif /* CONFIG_ISL9519_CHARGER */
-	{
-		I2C_SURF | I2C_FFA | I2C_FLUID,
-		MSM_8930_GSBI3_QUP_I2C_BUS_ID,
-		cyttsp_info,
-		ARRAY_SIZE(cyttsp_info),
-	},
 #ifndef MSM8930_PHASE_2
 	{
 		I2C_LIQUID,
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index bc45cdf..f9bc8fc 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -23,6 +23,7 @@
 #include <mach/gpio.h>
 #include <mach/gpiomux.h>
 #include <mach/ion.h>
+#include <mach/socinfo.h>
 
 #include "devices.h"
 #include "board-8960.h"
@@ -68,6 +69,7 @@
 #define MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME	"mipi_video_novatek_qhd"
 #define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME	"mipi_video_toshiba_wsvga"
 #define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME	"mipi_video_chimei_wxga"
+#define MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME	"mipi_video_chimei_wuxga"
 #define MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME	"mipi_video_simulator_vga"
 #define MIPI_CMD_RENESAS_FWVGA_PANEL_NAME	"mipi_cmd_renesas_fwvga"
 #define HDMI_PANEL_NAME	"hdmi_msm"
@@ -82,10 +84,18 @@
 static int msm_fb_detect_panel(const char *name)
 {
 	if (machine_is_msm8960_liquid()) {
-		if (!strncmp(name, MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
-				strnlen(MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
-					PANEL_NAME_MAX_LEN)))
-			return 0;
+		u32 ver = socinfo_get_platform_version();
+		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)))
+				return 0;
+		} else {
+			if (!strncmp(name, MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
+				     strnlen(MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
+						PANEL_NAME_MAX_LEN)))
+				return 0;
+		}
 	} else {
 		if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
 				strnlen(MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index c7e32c0..04376bc 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -449,14 +449,17 @@
 	{
 		.name		= "led:red",
 		.flags		= PM8XXX_ID_LED_0,
+		.default_trigger	= "battery-charging",
 	},
 	{
 		.name		= "led:green",
 		.flags		= PM8XXX_ID_LED_0,
+		.default_trigger	= "battery-full",
 	},
 	{
 		.name		= "led:blue",
 		.flags		= PM8XXX_ID_LED_2,
+		.default_trigger	= "dc-online",
 	},
 };
 
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 5520bf9..6819d5d 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -217,6 +217,7 @@
 };
 VREG_CONSUMERS(USB_OTG) = {
 	REGULATOR_SUPPLY("8921_usb_otg",	NULL),
+	REGULATOR_SUPPLY("vbus_otg",		"msm_otg"),
 };
 VREG_CONSUMERS(HDMI_MVS) = {
 	REGULATOR_SUPPLY("8921_hdmi_mvs",	NULL),
@@ -240,12 +241,12 @@
 };
 VREG_CONSUMERS(EXT_OTG_SW) = {
 	REGULATOR_SUPPLY("ext_otg_sw",		NULL),
-	REGULATOR_SUPPLY("vbus_otg",		"msm_otg"),
 };
 
 #define PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
 			 _apply_uV, _pull_down, _always_on, _supply_regulator, \
-			 _system_uA, _enable_time, _reg_id) \
+			 _system_uA, _enable_time, _reg_id, _ocp_enable, \
+			 _ocp_enable_time) \
 	{ \
 		.init_data = { \
 			.constraints = { \
@@ -267,6 +268,8 @@
 		.pull_down_enable	= _pull_down, \
 		.system_uA		= _system_uA, \
 		.enable_time		= _enable_time, \
+		.ocp_enable		= _ocp_enable, \
+		.ocp_enable_time	= _ocp_enable_time, \
 	}
 
 #define PM8XXX_LDO(_id, _name, _always_on, _pull_down, _min_uV, _max_uV, \
@@ -275,7 +278,7 @@
 		| REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE | \
 		REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
 		REGULATOR_CHANGE_DRMS, 0, _pull_down, _always_on, \
-		_supply_regulator, _system_uA, _enable_time, _reg_id)
+		_supply_regulator, _system_uA, _enable_time, _reg_id, 0, 0)
 
 #define PM8XXX_NLDO1200(_id, _name, _always_on, _pull_down, _min_uV, \
 		_max_uV, _enable_time, _supply_regulator, _system_uA, _reg_id) \
@@ -283,7 +286,7 @@
 		| REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE | \
 		REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
 		REGULATOR_CHANGE_DRMS, 0, _pull_down, _always_on, \
-		_supply_regulator, _system_uA, _enable_time, _reg_id)
+		_supply_regulator, _system_uA, _enable_time, _reg_id, 0, 0)
 
 #define PM8XXX_SMPS(_id, _name, _always_on, _pull_down, _min_uV, _max_uV, \
 		_enable_time, _supply_regulator, _system_uA, _reg_id) \
@@ -291,32 +294,32 @@
 		| REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE | \
 		REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
 		REGULATOR_CHANGE_DRMS, 0, _pull_down, _always_on, \
-		_supply_regulator, _system_uA, _enable_time, _reg_id)
+		_supply_regulator, _system_uA, _enable_time, _reg_id, 0, 0)
 
 #define PM8XXX_FTSMPS(_id, _name, _always_on, _pull_down, _min_uV, _max_uV, \
 		_enable_time, _supply_regulator, _system_uA, _reg_id) \
 	PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, REGULATOR_MODE_NORMAL, \
 		REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS \
 		| REGULATOR_CHANGE_MODE, 0, _pull_down, _always_on, \
-		_supply_regulator, _system_uA, _enable_time, _reg_id)
+		_supply_regulator, _system_uA, _enable_time, _reg_id, 0, 0)
 
 #define PM8XXX_VS(_id, _name, _always_on, _pull_down, _enable_time, \
-		_supply_regulator, _reg_id) \
+		_ocp_enable, _ocp_enable_time, _supply_regulator, _reg_id) \
 	PM8XXX_VREG_INIT(_id, _name, 0, 0, 0, REGULATOR_CHANGE_STATUS, 0, \
 		_pull_down, _always_on, _supply_regulator, 0, _enable_time, \
-		_reg_id)
+		_reg_id, _ocp_enable, _ocp_enable_time)
 
 #define PM8XXX_VS300(_id, _name, _always_on, _pull_down, _enable_time, \
-		_supply_regulator, _reg_id) \
+		_ocp_enable, _ocp_enable_time, _supply_regulator, _reg_id) \
 	PM8XXX_VREG_INIT(_id, _name, 0, 0, 0, REGULATOR_CHANGE_STATUS, 0, \
 		_pull_down, _always_on, _supply_regulator, 0, _enable_time, \
-		_reg_id)
+		_reg_id, _ocp_enable, _ocp_enable_time)
 
 #define PM8XXX_NCP(_id, _name, _always_on, _min_uV, _max_uV, _enable_time, \
 		_supply_regulator, _reg_id) \
 	PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, 0, \
 		REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, 0, 0, \
-		_always_on, _supply_regulator, 0, _enable_time, _reg_id)
+		_always_on, _supply_regulator, 0, _enable_time, _reg_id, 0, 0)
 
 /* Pin control initialization */
 #define PM8XXX_PC(_id, _name, _always_on, _pin_fn, _pin_ctrl, \
@@ -465,7 +468,7 @@
 	GPIO_VREG(EXT_3P3V, "ext_3p3v", "ext_3p3v_en",
 		PM8921_GPIO_PM_TO_SYS(17), NULL),
 	GPIO_VREG(EXT_OTG_SW, "ext_otg_sw", "ext_otg_sw_en",
-		PM8921_GPIO_PM_TO_SYS(42), "8921_usb_otg"),
+		PM8921_GPIO_PM_TO_SYS(42), "ext_5v"),
 };
 
 /* SAW regulator constraints */
@@ -491,9 +494,13 @@
 	PM8XXX_LDO(L29,      "8921_l29", 0, 1, 2050000, 2100000, 200, "8921_s8",
 		0, 4),
 
-	/*	     ID        name      always_on pd en_t supply    reg_ID */
-	PM8XXX_VS300(USB_OTG,  "8921_usb_otg",  0, 1, 0,   "ext_5v", 5),
-	PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1, 0,   "ext_5v", 6),
+	/*
+	 *	     ID       name      always_on pd en_t ocp ocp_t supply
+	 *	reg_ID
+	 */
+	PM8XXX_VS300(USB_OTG,  "8921_usb_otg",  0, 0,   0, 1, 500, "ext_otg_sw",
+		5),
+	PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1,   0, 0,   0, "ext_5v", 6),
 };
 
 static struct rpm_regulator_init_data
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index d628eeb..075f358 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1767,8 +1767,8 @@
 	&msm_device_saw_core0,
 	&msm_device_saw_core1,
 	&msm8960_device_ext_5v_vreg,
-	&msm8960_device_ssbi_pmic,
 	&msm8960_device_ext_otg_sw_vreg,
+	&msm8960_device_ssbi_pmic,
 	&msm8960_device_qup_spi_gsbi1,
 	&msm8960_device_qup_i2c_gsbi3,
 	&msm8960_device_qup_i2c_gsbi4,
@@ -2205,8 +2205,8 @@
 	.chg_detection_config	= NULL,	/* Not required when notify-by-pmic */
 	.max_system_voltage	= 4200,
 	.min_system_voltage	= 3200,
-	.chgcurrent		= 1000, /* 1900, */
-	.term_current		= 400,	/* Need fine tuning */
+	.chgcurrent		= 1900,
+	.term_current		= 0,
 	.input_current		= 2048,
 };
 
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 1e51a8a..9c0a80e 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -300,6 +300,46 @@
 		.desc_fifo_base_offset = 0x1000,
 		.desc_fifo_size = 0x100,
 	},
+	[1][USB_TO_PEER_PERIPHERAL] = {
+		.src_phy_addr = USB_BAM_PHY_BASE,
+		.src_pipe_index = 13,
+		.dst_phy_addr = A2_BAM_PHY_BASE,
+		.dst_pipe_index = 2,
+		.data_fifo_base_offset = 0x2100,
+		.data_fifo_size = 0x600,
+		.desc_fifo_base_offset = 0x2700,
+		.desc_fifo_size = 0x300,
+	},
+	[1][PEER_PERIPHERAL_TO_USB] = {
+		.src_phy_addr = A2_BAM_PHY_BASE,
+		.src_pipe_index = 3,
+		.dst_phy_addr = USB_BAM_PHY_BASE,
+		.dst_pipe_index = 12,
+		.data_fifo_base_offset = 0x1a00,
+		.data_fifo_size = 0x600,
+		.desc_fifo_base_offset = 0x2000,
+		.desc_fifo_size = 0x100,
+	},
+	[2][USB_TO_PEER_PERIPHERAL] = {
+		.src_phy_addr = USB_BAM_PHY_BASE,
+		.src_pipe_index = 15,
+		.dst_phy_addr = A2_BAM_PHY_BASE,
+		.dst_pipe_index = 4,
+		.data_fifo_base_offset = 0x3100,
+		.data_fifo_size = 0x600,
+		.desc_fifo_base_offset = 0x3700,
+		.desc_fifo_size = 0x300,
+	},
+	[2][PEER_PERIPHERAL_TO_USB] = {
+		.src_phy_addr = A2_BAM_PHY_BASE,
+		.src_pipe_index = 5,
+		.dst_phy_addr = USB_BAM_PHY_BASE,
+		.dst_pipe_index = 14,
+		.data_fifo_base_offset = 0x2a00,
+		.data_fifo_size = 0x600,
+		.desc_fifo_base_offset = 0x3000,
+		.desc_fifo_size = 0x100,
+	}
 #else
 	[0][USB_TO_PEER_PERIPHERAL] = {
 		.src_phy_addr = HSIC_BAM_PHY_BASE,
@@ -321,6 +361,46 @@
 		.desc_fifo_base_offset = 0x1000,
 		.desc_fifo_size = 0x100,
 	},
+	[1][USB_TO_PEER_PERIPHERAL] = {
+		.src_phy_addr = HSIC_BAM_PHY_BASE,
+		.src_pipe_index = 3,
+		.dst_phy_addr = A2_BAM_PHY_BASE,
+		.dst_pipe_index = 2,
+		.data_fifo_base_offset = 0x2100,
+		.data_fifo_size = 0x600,
+		.desc_fifo_base_offset = 0x2700,
+		.desc_fifo_size = 0x300,
+	},
+	[1][PEER_PERIPHERAL_TO_USB] = {
+		.src_phy_addr = A2_BAM_PHY_BASE,
+		.src_pipe_index = 3,
+		.dst_phy_addr = HSIC_BAM_PHY_BASE,
+		.dst_pipe_index = 2,
+		.data_fifo_base_offset = 0x1a00,
+		.data_fifo_size = 0x600,
+		.desc_fifo_base_offset = 0x2000,
+		.desc_fifo_size = 0x100,
+	},
+	[2][USB_TO_PEER_PERIPHERAL] = {
+		.src_phy_addr = HSIC_BAM_PHY_BASE,
+		.src_pipe_index = 5,
+		.dst_phy_addr = A2_BAM_PHY_BASE,
+		.dst_pipe_index = 4,
+		.data_fifo_base_offset = 0x3100,
+		.data_fifo_size = 0x600,
+		.desc_fifo_base_offset = 0x3700,
+		.desc_fifo_size = 0x300,
+	},
+	[2][PEER_PERIPHERAL_TO_USB] = {
+		.src_phy_addr = A2_BAM_PHY_BASE,
+		.src_pipe_index = 5,
+		.dst_phy_addr = HSIC_BAM_PHY_BASE,
+		.dst_pipe_index = 4,
+		.data_fifo_base_offset = 0x2a00,
+		.data_fifo_size = 0x600,
+		.desc_fifo_base_offset = 0x3000,
+		.desc_fifo_size = 0x100,
+	}
 #endif
 };
 
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index bde38c3..e3f668f 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -479,8 +479,8 @@
 	.ioext.csiirq		= INT_CSI_IRQ_1,
 	.ioclk.mclk_clk_rate	= 24000000,
 	.ioclk.vfe_clk_rate	= 192000000,
-	.ioext.appphy		= MSM_CLK_CTL_PHYS,
-	.ioext.appsz		= MSM_CLK_CTL_SIZE,
+	.ioext.appphy		= MSM7XXX_CLK_CTL_PHYS,
+	.ioext.appsz		= MSM7XXX_CLK_CTL_SIZE,
 };
 
 struct msm_camera_device_platform_data msm_camera_device_data_front = {
@@ -491,8 +491,8 @@
 	.ioext.csiirq		= INT_CSI_IRQ_0,
 	.ioclk.mclk_clk_rate	= 24000000,
 	.ioclk.vfe_clk_rate	= 192000000,
-	.ioext.appphy		= MSM_CLK_CTL_PHYS,
-	.ioext.appsz		= MSM_CLK_CTL_SIZE,
+	.ioext.appphy		= MSM7XXX_CLK_CTL_PHYS,
+	.ioext.appsz		= MSM7XXX_CLK_CTL_SIZE,
 };
 
 #ifdef CONFIG_S5K4E1
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index 9385a58..5c189fe 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -1063,10 +1063,10 @@
 static struct msm_camera_device_platform_data msm_camera_device_data = {
 	.camera_gpio_on  = config_camera_on_gpios,
 	.camera_gpio_off = config_camera_off_gpios,
-	.ioext.mdcphy = MSM_MDC_PHYS,
-	.ioext.mdcsz  = MSM_MDC_SIZE,
-	.ioext.appphy = MSM_CLK_CTL_PHYS,
-	.ioext.appsz  = MSM_CLK_CTL_SIZE,
+	.ioext.mdcphy = MSM7XXX_MDC_PHYS,
+	.ioext.mdcsz  = MSM7XXX_MDC_SIZE,
+	.ioext.appphy = MSM7XXX_CLK_CTL_PHYS,
+	.ioext.appsz  = MSM7XXX_CLK_CTL_SIZE,
 };
 
 int pmic_set_flash_led_current(enum pmic8058_leds id, unsigned mA)
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 118798b..0437134 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -151,6 +151,10 @@
 	.msm_i2c_config_gpio	= gsbi_qup_i2c_gpio_config,
 };
 
+static struct msm_i2c_platform_data msm8625_gsbi0_qup_i2c_pdata = {
+	.clk_freq		= 100000,
+};
+
 #ifdef CONFIG_ARCH_MSM7X27A
 #define MSM_PMEM_MDP_SIZE       0x2300000
 #define MSM7x25A_MSM_PMEM_MDP_SIZE       0x1500000
@@ -681,6 +685,7 @@
 static struct platform_device *msm8625_rumi3_devices[] __initdata = {
 	&msm8625_device_dmov,
 	&msm8625_device_uart1,
+	&msm8625_device_qup_i2c_gsbi0,
 };
 
 static struct platform_device *surf_ffa_devices[] __initdata = {
@@ -796,6 +801,12 @@
 
 static void __init msm_device_i2c_init(void)
 {
+	if (machine_is_msm8625_rumi3()) {
+		msm8625_device_qup_i2c_gsbi0.dev.platform_data =
+			&msm8625_gsbi0_qup_i2c_pdata;
+		return;
+	}
+
 	msm_gsbi0_qup_i2c_device.dev.platform_data = &msm_gsbi0_qup_i2c_pdata;
 	msm_gsbi1_qup_i2c_device.dev.platform_data = &msm_gsbi1_qup_i2c_pdata;
 }
@@ -1061,6 +1072,7 @@
 static void __init msm8625_rumi3_init(void)
 {
 	msm7x2x_misc_init();
+	msm_device_i2c_init();
 	platform_add_devices(msm8625_rumi3_devices,
 			ARRAY_SIZE(msm8625_rumi3_devices));
 }
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index d54ebc5..3e7b7f4 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -138,6 +138,13 @@
 
 #define	PM_FLIP_MPP 5 /* PMIC MPP 06 */
 
+#define DDR1_BANK_BASE 0X20000000
+#define DDR2_BANK_BASE 0X40000000
+
+static unsigned int phys_add = DDR2_BANK_BASE;
+unsigned long ebi1_phys_offset = DDR2_BANK_BASE;
+EXPORT_SYMBOL(ebi1_phys_offset);
+
 struct pm8xxx_gpio_init_info {
 	unsigned			gpio;
 	struct pm_gpio			config;
@@ -6898,9 +6905,9 @@
 
 static int msm7x30_paddr_to_memtype(unsigned int paddr)
 {
-	if (paddr < 0x40000000)
+	if (paddr < phys_add)
 		return MEMTYPE_EBI0;
-	if (paddr >= 0x40000000 && paddr < 0x80000000)
+	if (paddr >= phys_add && paddr < 0x80000000)
 		return MEMTYPE_EBI1;
 	return MEMTYPE_NONE;
 }
@@ -6944,6 +6951,19 @@
 	msm7x30_allocate_memory_regions();
 }
 
+static void __init msm7x30_fixup(struct machine_desc *desc, struct tag *tags,
+				 char **cmdline, struct meminfo *mi)
+{
+	for (; tags->hdr.size; tags = tag_next(tags)) {
+		if (tags->hdr.tag == ATAG_MEM && tags->u.mem.start ==
+							DDR1_BANK_BASE) {
+				ebi1_phys_offset = DDR1_BANK_BASE;
+				phys_add = DDR1_BANK_BASE;
+				break;
+		}
+	}
+}
+
 MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
 	.boot_params = PLAT_PHYS_OFFSET + 0x100,
 	.map_io = msm7x30_map_io,
@@ -6953,6 +6973,7 @@
 	.timer = &msm_timer,
 	.init_early = msm7x30_init_early,
 	.handle_irq = vic_handle_irq,
+	.fixup = msm7x30_fixup,
 MACHINE_END
 
 MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
@@ -6964,6 +6985,7 @@
 	.timer = &msm_timer,
 	.init_early = msm7x30_init_early,
 	.handle_irq = vic_handle_irq,
+	.fixup = msm7x30_fixup,
 MACHINE_END
 
 MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID")
@@ -6975,6 +6997,7 @@
 	.timer = &msm_timer,
 	.init_early = msm7x30_init_early,
 	.handle_irq = vic_handle_irq,
+	.fixup = msm7x30_fixup,
 MACHINE_END
 
 MACHINE_START(MSM8X55_SURF, "QCT MSM8X55 SURF")
@@ -6986,6 +7009,7 @@
 	.timer = &msm_timer,
 	.init_early = msm7x30_init_early,
 	.handle_irq = vic_handle_irq,
+	.fixup = msm7x30_fixup,
 MACHINE_END
 
 MACHINE_START(MSM8X55_FFA, "QCT MSM8X55 FFA")
@@ -6997,6 +7021,7 @@
 	.timer = &msm_timer,
 	.init_early = msm7x30_init_early,
 	.handle_irq = vic_handle_irq,
+	.fixup = msm7x30_fixup,
 MACHINE_END
 MACHINE_START(MSM8X55_SVLTE_SURF, "QCT MSM8X55 SVLTE SURF")
 	.boot_params = PHYS_OFFSET + 0x100,
@@ -7007,6 +7032,7 @@
 	.timer = &msm_timer,
 	.init_early = msm7x30_init_early,
 	.handle_irq = vic_handle_irq,
+	.fixup = msm7x30_fixup,
 MACHINE_END
 MACHINE_START(MSM8X55_SVLTE_FFA, "QCT MSM8X55 SVLTE FFA")
 	.boot_params = PHYS_OFFSET + 0x100,
@@ -7017,4 +7043,5 @@
 	.timer = &msm_timer,
 	.init_early = msm7x30_init_early,
 	.handle_irq = vic_handle_irq,
+	.fixup = msm7x30_fixup,
 MACHINE_END
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index 508a496..8374636 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -2749,7 +2749,7 @@
 	{ CLK_LOOKUP("ebi1_clk",	ebi1_clk.c,	NULL) },
 	{ CLK_LOOKUP("ebi1_fixed_clk",	ebi1_fixed_clk.c,	NULL) },
 	{ CLK_LOOKUP("ecodec_clk",	ecodec_clk.c,	NULL) },
-	{ CLK_LOOKUP("core_clk",	gp_clk.c,	NULL) },
+	{ CLK_LOOKUP("core_clk",	gp_clk.c,	"") },
 	{ CLK_LOOKUP("core_clk",	uart3_clk.c,	"msm_serial.2") },
 	{ CLK_LOOKUP("phy_clk",		usb_phy_clk.c,	"msm_otg") },
 
@@ -2836,9 +2836,9 @@
 	OWN(ROW1,  2, "alt_core_clk",	usb_hs2_clk,	"msm_hsusb_host.0"),
 	OWN(ROW1,  2, "core_clk",	usb_hs2_core_clk, "msm_hsusb_host.0"),
 	OWN(ROW1,  2, "iface_clk",	usb_hs2_p_clk,	"msm_hsusb_host.0"),
-	OWN(ROW1,  4, "alt_core_clk",	usb_hs3_clk,	NULL),
-	OWN(ROW1,  4, "core_clk",	usb_hs3_core_clk, NULL),
-	OWN(ROW1,  4, "iface_clk",	usb_hs3_p_clk,	NULL),
+	OWN(ROW1,  4, "alt_core_clk",	usb_hs3_clk,	""),
+	OWN(ROW1,  4, "core_clk",	usb_hs3_core_clk, ""),
+	OWN(ROW1,  4, "iface_clk",	usb_hs3_p_clk,	""),
 
 	OWN(ROW2,  3, "core_clk",	qup_i2c_clk,	"qup_i2c.4"),
 	OWN(ROW2,  1, "core_clk",	spi_clk,	"spi_qsd.0"),
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index a2abb25..eb3cb13 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -596,6 +596,7 @@
 	.reset = rcg_clk_reset,
 	.is_local = local_clk_is_local,
 	.get_parent = rcg_clk_get_parent,
+	.set_flags = rcg_clk_set_flags,
 };
 
 static struct clk_ops clk_ops_branch = {
@@ -611,6 +612,7 @@
 	.get_parent = branch_clk_get_parent,
 	.set_parent = branch_clk_set_parent,
 	.handoff = branch_clk_handoff,
+	.set_flags = branch_clk_set_flags,
 };
 
 static struct clk_ops clk_ops_reset = {
@@ -625,6 +627,8 @@
 		.en_mask = BIT(24),
 		.halt_reg = DBG_BUS_VEC_E_REG,
 		.halt_bit = 6,
+		.retain_reg = MAXI_EN2_REG,
+		.retain_mask = BIT(21),
 	},
 	.c = {
 		.dbg_name = "gmem_axi_clk",
@@ -661,6 +665,8 @@
 		.reset_mask = BIT(10),
 		.halt_reg = DBG_BUS_VEC_E_REG,
 		.halt_bit = 7,
+		.retain_reg = MAXI_EN2_REG,
+		.retain_mask = BIT(10),
 	},
 	.c = {
 		.dbg_name = "imem_axi_clk",
@@ -691,6 +697,8 @@
 		.hwcg_mask = BIT(22),
 		.halt_reg = DBG_BUS_VEC_I_REG,
 		.halt_bit = 25,
+		.retain_reg = MAXI_EN4_REG,
+		.retain_mask = BIT(21),
 	},
 	.c = {
 		.dbg_name = "vcodec_axi_b_clk",
@@ -707,6 +715,8 @@
 		.hwcg_mask = BIT(24),
 		.halt_reg = DBG_BUS_VEC_I_REG,
 		.halt_bit = 26,
+		.retain_reg = MAXI_EN4_REG,
+		.retain_mask = BIT(10),
 	},
 	.c = {
 		.dbg_name = "vcodec_axi_a_clk",
@@ -726,6 +736,8 @@
 		.reset_mask = BIT(4)|BIT(5)|BIT(7),
 		.halt_reg = DBG_BUS_VEC_E_REG,
 		.halt_bit = 3,
+		.retain_reg = MAXI_EN2_REG,
+		.retain_mask = BIT(28),
 	},
 	.c = {
 		.dbg_name = "vcodec_axi_clk",
@@ -761,6 +773,8 @@
 		.reset_mask = BIT(13),
 		.halt_reg = DBG_BUS_VEC_E_REG,
 		.halt_bit = 8,
+		.retain_reg = MAXI_EN_REG,
+		.retain_mask = BIT(0),
 	},
 	.c = {
 		.dbg_name = "mdp_axi_clk",
@@ -779,6 +793,8 @@
 		.reset_mask = BIT(6),
 		.halt_reg = DBG_BUS_VEC_E_REG,
 		.halt_bit = 2,
+		.retain_reg = MAXI_EN3_REG,
+		.retain_mask = BIT(10),
 	},
 	.c = {
 		.dbg_name = "rot_axi_clk",
@@ -797,6 +813,9 @@
 		.reset_mask = BIT(15),
 		.halt_reg = DBG_BUS_VEC_E_REG,
 		.halt_bit = 1,
+		.retain_reg = MAXI_EN3_REG,
+		.retain_mask = BIT(21),
+
 	},
 	.c = {
 		.dbg_name = "vpe_axi_clk",
@@ -1167,6 +1186,8 @@
 		.reset_mask = BIT(0),
 		.halt_reg = DBG_BUS_VEC_F_REG,
 		.halt_bit = 14,
+		.retain_reg = AHB_EN2_REG,
+		.retain_mask = BIT(0),
 	},
 	.c = {
 		.dbg_name = "vfe_p_clk",
@@ -3082,6 +3103,8 @@
 		.reset_mask = BIT(7),
 		.halt_reg = DBG_BUS_VEC_B_REG,
 		.halt_bit = 21,
+		.retain_reg = DSI1_BYTE_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = DSI1_BYTE_NS_REG,
 	.root_en_mask = BIT(2),
@@ -3104,6 +3127,8 @@
 		.reset_mask = BIT(25),
 		.halt_reg = DBG_BUS_VEC_B_REG,
 		.halt_bit = 20,
+		.retain_reg = DSI2_BYTE_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = DSI2_BYTE_NS_REG,
 	.root_en_mask = BIT(2),
@@ -3211,6 +3236,8 @@
 		.reset_mask = BIT(14),
 		.halt_reg = DBG_BUS_VEC_A_REG,
 		.halt_bit = 9,
+		.retain_reg = GFX2D0_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = GFX2D0_NS_REG,
 	.root_en_mask = BIT(2),
@@ -3253,6 +3280,8 @@
 		.reset_mask = BIT(13),
 		.halt_reg = DBG_BUS_VEC_A_REG,
 		.halt_bit = 14,
+		.retain_reg = GFX2D1_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = GFX2D1_NS_REG,
 	.root_en_mask = BIT(2),
@@ -3377,6 +3406,8 @@
 		.reset_mask = BIT(12),
 		.halt_reg = DBG_BUS_VEC_A_REG,
 		.halt_bit = 4,
+		.retain_reg = GFX3D_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = GFX3D_NS_REG,
 	.root_en_mask = BIT(2),
@@ -3517,6 +3548,8 @@
 		.reset_mask = BIT(9),
 		.halt_reg = DBG_BUS_VEC_A_REG,
 		.halt_bit = 24,
+		.retain_reg = IJPEG_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = IJPEG_NS_REG,
 	.md_reg = IJPEG_MD_REG,
@@ -3559,6 +3592,8 @@
 		.reset_mask = BIT(19),
 		.halt_reg = DBG_BUS_VEC_A_REG,
 		.halt_bit = 19,
+		.retain_reg = JPEGD_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = JPEGD_NS_REG,
 	.root_en_mask = BIT(2),
@@ -3635,6 +3670,8 @@
 		.reset_mask = BIT(21),
 		.halt_reg = DBG_BUS_VEC_C_REG,
 		.halt_bit = 10,
+		.retain_reg = MDP_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = MDP_NS_REG,
 	.root_en_mask = BIT(2),
@@ -3657,6 +3694,8 @@
 		.en_mask = BIT(0),
 		.halt_reg = DBG_BUS_VEC_I_REG,
 		.halt_bit = 13,
+		.retain_reg = MDP_LUT_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.parent = &mdp_clk.c,
 	.c = {
@@ -3743,6 +3782,8 @@
 		.reset_mask = BIT(2),
 		.halt_reg = DBG_BUS_VEC_C_REG,
 		.halt_bit = 15,
+		.retain_reg = ROT_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = ROT_NS_REG,
 	.root_en_mask = BIT(2),
@@ -3853,6 +3894,8 @@
 	.b = {
 		.ctl_reg = TV_CC_REG,
 		.halt_check = NOCHECK,
+		.retain_reg = TV_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.md_reg = TV_MD_REG,
 	.root_en_mask = BIT(2),
@@ -3909,6 +3952,8 @@
 		.reset_mask = BIT(4),
 		.halt_reg = DBG_BUS_VEC_D_REG,
 		.halt_bit = 12,
+		.retain_reg = TV_CC2_REG,
+		.retain_mask = BIT(10),
 	},
 	.parent = &tv_src_clk.c,
 	.c = {
@@ -3998,6 +4043,8 @@
 		.reset_mask = BIT(6),
 		.halt_reg = DBG_BUS_VEC_C_REG,
 		.halt_bit = 29,
+		.retain_reg = VCODEC_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = VCODEC_NS_REG,
 	.root_en_mask = BIT(2),
@@ -4042,6 +4089,8 @@
 		.reset_mask = BIT(17),
 		.halt_reg = DBG_BUS_VEC_A_REG,
 		.halt_bit = 28,
+		.retain_reg = VPE_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = VPE_NS_REG,
 	.root_en_mask = BIT(2),
@@ -4110,6 +4159,8 @@
 		.halt_reg = DBG_BUS_VEC_B_REG,
 		.halt_bit = 6,
 		.en_mask = BIT(0),
+		.retain_reg = VFE_CC2_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = VFE_NS_REG,
 	.md_reg = VFE_MD_REG,
@@ -4248,7 +4299,7 @@
 			.ctl_reg = ns, \
 			.en_mask = BIT(19), \
 			.halt_reg = h_r, \
-			.halt_check = ENABLE, \
+			.halt_check = DELAY, \
 		}, \
 		.ns_reg = ns, \
 		.ext_mask = BIT(18), \
@@ -4812,7 +4863,7 @@
 };
 
 static struct clk_lookup msm_clocks_8064[] = {
-	CLK_LOOKUP("cxo",		cxo_clk.c,	NULL),
+	CLK_LOOKUP("xo",		cxo_clk.c,	"msm_otg"),
 	CLK_LOOKUP("cxo",		cxo_clk.c,	"wcnss_wlan.0"),
 	CLK_LOOKUP("cxo",		cxo_clk.c,	"pil_riva"),
 	CLK_LOOKUP("xo",		pxo_clk.c,	"pil_qdsp6v4.0"),
@@ -4842,42 +4893,42 @@
 	CLK_DUMMY("bus_clk",		MMFPB_CLK,	NULL, 0),
 	CLK_DUMMY("bus_a_clk",		MMFPB_A_CLK,	NULL, 0),
 
-	CLK_LOOKUP("core_clk",		gp0_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		gp1_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		gp2_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		gsbi1_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi2_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi3_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi4_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi5_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi6_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi7_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi1_qup_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi2_qup_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi3_qup_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi4_qup_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi5_qup_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi6_qup_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi7_qup_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		pdm_clk.c,		NULL),
+	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,	""),
+	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",		gsbi1_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi2_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi3_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi4_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi5_qup_clk.c,	""),
+	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("pmem_clk",		pmem_clk.c,		NULL),
 	CLK_DUMMY("core_clk",           PRNG_CLK,	"msm_rng.0", OFF),
 	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"),
 	CLK_LOOKUP("core_clk",		sdc4_clk.c,		"msm_sdcc.4"),
-	CLK_LOOKUP("ref_clk",		tsif_ref_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		tssc_clk.c,		NULL),
+	CLK_LOOKUP("ref_clk",		tsif_ref_clk.c,		""),
+	CLK_LOOKUP("core_clk",		tssc_clk.c,		""),
 	CLK_LOOKUP("alt_core_clk",	usb_hs1_xcvr_clk.c,	"msm_otg"),
 	CLK_LOOKUP("alt_core_clk",      usb_hs3_xcvr_clk.c,  "msm_ehci_host.0"),
 	CLK_LOOKUP("alt_core_clk",      usb_hs4_xcvr_clk.c,  "msm_ehci_host.1"),
-	CLK_LOOKUP("src_clk",		usb_fs1_src_clk.c,	NULL),
-	CLK_LOOKUP("alt_core_clk",	usb_fs1_xcvr_clk.c,	NULL),
-	CLK_LOOKUP("sys_clk",		usb_fs1_sys_clk.c,	NULL),
-	CLK_LOOKUP("iface_clk",		ce1_p_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		ce1_core_clk.c,		NULL),
-	CLK_LOOKUP("ref_clk",		sata_phy_ref_clk.c,	NULL),
-	CLK_LOOKUP("cfg_clk",		sata_phy_cfg_clk.c,	NULL),
+	CLK_LOOKUP("src_clk",		usb_fs1_src_clk.c,	""),
+	CLK_LOOKUP("alt_core_clk",	usb_fs1_xcvr_clk.c,	""),
+	CLK_LOOKUP("sys_clk",		usb_fs1_sys_clk.c,	""),
+	CLK_LOOKUP("iface_clk",		ce1_p_clk.c,		""),
+	CLK_LOOKUP("core_clk",		ce1_core_clk.c,		""),
+	CLK_LOOKUP("ref_clk",		sata_phy_ref_clk.c,	""),
+	CLK_LOOKUP("cfg_clk",		sata_phy_cfg_clk.c,	""),
 	CLK_LOOKUP("iface_clk",		ce3_p_clk.c,		"qce.0"),
 	CLK_LOOKUP("iface_clk",		ce3_p_clk.c,		"qcrypto.0"),
 	CLK_LOOKUP("core_clk",		ce3_core_clk.c,		"qce.0"),
@@ -4885,15 +4936,15 @@
 	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,		NULL),
-	CLK_LOOKUP("iface_clk",		gsbi2_p_clk.c,		NULL),
-	CLK_LOOKUP("iface_clk",		gsbi3_p_clk.c,		NULL),
-	CLK_LOOKUP("iface_clk",		gsbi4_p_clk.c,		NULL),
-	CLK_LOOKUP("iface_clk",		gsbi5_p_clk.c,		NULL),
-	CLK_LOOKUP("iface_clk",		gsbi6_p_clk.c,		NULL),
-	CLK_LOOKUP("iface_clk",		gsbi7_p_clk.c,		NULL),
-	CLK_LOOKUP("iface_clk",		tsif_p_clk.c,		NULL),
-	CLK_LOOKUP("iface_clk",		usb_fs1_p_clk.c,	NULL),
+	CLK_LOOKUP("iface_clk",		gsbi1_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		gsbi2_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		gsbi3_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		gsbi4_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		gsbi5_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		gsbi6_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		gsbi7_p_clk.c,		""),
+	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"),
 	CLK_LOOKUP("iface_clk",         usb_hs3_p_clk.c,     "msm_ehci_host.0"),
 	CLK_LOOKUP("iface_clk",         usb_hs4_p_clk.c,     "msm_ehci_host.1"),
@@ -4901,80 +4952,80 @@
 	CLK_LOOKUP("iface_clk",		sdc2_p_clk.c,		"msm_sdcc.2"),
 	CLK_LOOKUP("iface_clk",		sdc3_p_clk.c,		"msm_sdcc.3"),
 	CLK_LOOKUP("iface_clk",		sdc4_p_clk.c,		"msm_sdcc.4"),
-	CLK_LOOKUP("iface_clk",		pcie_p_clk.c,		NULL),
+	CLK_LOOKUP("iface_clk",		pcie_p_clk.c,		""),
 	CLK_LOOKUP("core_clk",		adm0_clk.c,		"msm_dmov"),
 	CLK_LOOKUP("iface_clk",		adm0_p_clk.c,		"msm_dmov"),
-	CLK_LOOKUP("iface_clk",		pmic_arb0_p_clk.c,	NULL),
-	CLK_LOOKUP("iface_clk",		pmic_arb1_p_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		pmic_ssbi2_clk.c,	NULL),
-	CLK_LOOKUP("mem_clk",		rpm_msg_ram_p_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		amp_clk.c,		NULL),
-	CLK_LOOKUP("cam_clk",		cam0_clk.c,		NULL),
-	CLK_LOOKUP("cam_clk",		cam1_clk.c,		NULL),
-	CLK_LOOKUP("cam_clk",		cam0_clk.c,		NULL),
-	CLK_LOOKUP("cam_clk",		cam0_clk.c,		NULL),
-	CLK_LOOKUP("cam_clk",		cam0_clk.c,		NULL),
-	CLK_LOOKUP("csi_src_clk",	csi0_src_clk.c,		NULL),
-	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		NULL),
-	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		NULL),
-	CLK_LOOKUP("csi_src_clk",	csi2_src_clk.c,		NULL),
-	CLK_LOOKUP("csi_clk",		csi0_clk.c,		NULL),
-	CLK_LOOKUP("csi_clk",		csi1_clk.c,		NULL),
-	CLK_LOOKUP("csi_clk",		csi1_clk.c,		NULL),
-	CLK_LOOKUP("csi_clk",		csi2_clk.c,		NULL),
-	CLK_LOOKUP("csi_phy_clk",	csi0_phy_clk.c,		NULL),
-	CLK_LOOKUP("csi_phy_clk",	csi1_phy_clk.c,		NULL),
-	CLK_LOOKUP("csi_phy_clk",	csi1_phy_clk.c,		NULL),
-	CLK_LOOKUP("csi_phy_clk",	csi2_phy_clk.c,		NULL),
-	CLK_LOOKUP("csi_pix_clk",	csi_pix_clk.c,		NULL),
-	CLK_LOOKUP("csi_pix_clk",	csi_pix1_clk.c,		NULL),
-	CLK_LOOKUP("csi_rdi_clk",	csi_rdi_clk.c,		NULL),
-	CLK_LOOKUP("csi_rdi_clk",	csi_rdi1_clk.c,		NULL),
-	CLK_LOOKUP("csi_rdi_clk",	csi_rdi2_clk.c,		NULL),
-	CLK_LOOKUP("csiphy_timer_src_clk", csiphy_timer_src_clk.c, NULL),
-	CLK_LOOKUP("csiphy_timer_clk",	csi0phy_timer_clk.c,	NULL),
-	CLK_LOOKUP("csiphy_timer_clk",	csi1phy_timer_clk.c,	NULL),
-	CLK_LOOKUP("csiphy_timer_clk",	csi2phy_timer_clk.c,	NULL),
-	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,		NULL, OFF),
-	CLK_DUMMY("npl_tv_clk",		NPL_TV_CLK,		NULL, OFF),
+	CLK_LOOKUP("iface_clk",		pmic_arb0_p_clk.c,	""),
+	CLK_LOOKUP("iface_clk",		pmic_arb1_p_clk.c,	""),
+	CLK_LOOKUP("core_clk",		pmic_ssbi2_clk.c,	""),
+	CLK_LOOKUP("mem_clk",		rpm_msg_ram_p_clk.c,	""),
+	CLK_LOOKUP("core_clk",		amp_clk.c,		""),
+	CLK_LOOKUP("cam_clk",		cam0_clk.c,		""),
+	CLK_LOOKUP("cam_clk",		cam1_clk.c,		""),
+	CLK_LOOKUP("cam_clk",		cam0_clk.c,		""),
+	CLK_LOOKUP("cam_clk",		cam0_clk.c,		""),
+	CLK_LOOKUP("cam_clk",		cam0_clk.c,		""),
+	CLK_LOOKUP("csi_src_clk",	csi0_src_clk.c,		""),
+	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		""),
+	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		""),
+	CLK_LOOKUP("csi_src_clk",	csi2_src_clk.c,		""),
+	CLK_LOOKUP("csi_clk",		csi0_clk.c,		""),
+	CLK_LOOKUP("csi_clk",		csi1_clk.c,		""),
+	CLK_LOOKUP("csi_clk",		csi1_clk.c,		""),
+	CLK_LOOKUP("csi_clk",		csi2_clk.c,		""),
+	CLK_LOOKUP("csi_phy_clk",	csi0_phy_clk.c,		""),
+	CLK_LOOKUP("csi_phy_clk",	csi1_phy_clk.c,		""),
+	CLK_LOOKUP("csi_phy_clk",	csi1_phy_clk.c,		""),
+	CLK_LOOKUP("csi_phy_clk",	csi2_phy_clk.c,		""),
+	CLK_LOOKUP("csi_pix_clk",	csi_pix_clk.c,		""),
+	CLK_LOOKUP("csi_pix_clk",	csi_pix1_clk.c,		""),
+	CLK_LOOKUP("csi_rdi_clk",	csi_rdi_clk.c,		""),
+	CLK_LOOKUP("csi_rdi_clk",	csi_rdi1_clk.c,		""),
+	CLK_LOOKUP("csi_rdi_clk",	csi_rdi2_clk.c,		""),
+	CLK_LOOKUP("csiphy_timer_src_clk", csiphy_timer_src_clk.c, ""),
+	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_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"),
 	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	"footswitch-8x60.2"),
 	CLK_LOOKUP("bus_clk",		gfx3d_axi_clk.c, "footswitch-8x60.2"),
-	CLK_LOOKUP("iface_clk",         vcap_p_clk.c,           NULL),
+	CLK_LOOKUP("iface_clk",         vcap_p_clk.c,           ""),
 	CLK_LOOKUP("iface_clk",         vcap_p_clk.c,	"footswitch-8x60.10"),
 	CLK_LOOKUP("bus_clk",		vcap_axi_clk.c,	"footswitch-8x60.10"),
-	CLK_LOOKUP("core_clk",          vcap_clk.c,             NULL),
+	CLK_LOOKUP("core_clk",          vcap_clk.c,             ""),
 	CLK_LOOKUP("core_clk",          vcap_clk.c,	"footswitch-8x60.10"),
-	CLK_LOOKUP("vcap_npl_clk",      vcap_npl_clk.c,         NULL),
+	CLK_LOOKUP("vcap_npl_clk",      vcap_npl_clk.c,         ""),
 	CLK_LOOKUP("bus_clk",		ijpeg_axi_clk.c, "footswitch-8x60.3"),
-	CLK_LOOKUP("mem_clk",		imem_axi_clk.c,		NULL),
-	CLK_LOOKUP("ijpeg_clk",         ijpeg_clk.c,            NULL),
+	CLK_LOOKUP("mem_clk",		imem_axi_clk.c,		""),
+	CLK_LOOKUP("ijpeg_clk",         ijpeg_clk.c,            ""),
 	CLK_LOOKUP("core_clk",		ijpeg_clk.c,	"footswitch-8x60.3"),
-	CLK_LOOKUP("core_clk",		jpegd_clk.c,		NULL),
-	CLK_LOOKUP("mdp_clk",		mdp_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		jpegd_clk.c,		""),
+	CLK_LOOKUP("mdp_clk",		mdp_clk.c,		""),
 	CLK_LOOKUP("core_clk",		mdp_clk.c,	 "footswitch-8x60.4"),
-	CLK_LOOKUP("mdp_vsync_clk",	mdp_vsync_clk.c,	NULL),
+	CLK_LOOKUP("mdp_vsync_clk",	mdp_vsync_clk.c,	""),
 	CLK_LOOKUP("vsync_clk",		mdp_vsync_clk.c, "footswitch-8x60.4"),
-	CLK_LOOKUP("lut_mdp",		lut_mdp_clk.c,		NULL),
+	CLK_LOOKUP("lut_mdp",		lut_mdp_clk.c,		""),
 	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,		NULL, OFF),
+	CLK_DUMMY("tv_src_clk",		TV_SRC_CLK,		"", 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,		NULL, OFF),
+	CLK_DUMMY("mdp_tv_clk",		MDP_TV_CLK,		"", OFF),
 	CLK_DUMMY("tv_clk",		MDP_TV_CLK, "footswitch-8x60.4", OFF),
-	CLK_DUMMY("hdmi_clk",		HDMI_TV_CLK,		NULL, OFF),
-	CLK_LOOKUP("core_clk",		hdmi_app_clk.c,		NULL),
-	CLK_LOOKUP("vpe_clk",		vpe_clk.c,		NULL),
+	CLK_DUMMY("hdmi_clk",		HDMI_TV_CLK,		"", OFF),
+	CLK_LOOKUP("core_clk",		hdmi_app_clk.c,		""),
+	CLK_LOOKUP("vpe_clk",		vpe_clk.c,		""),
 	CLK_LOOKUP("core_clk",		vpe_clk.c,	"footswitch-8x60.9"),
-	CLK_LOOKUP("vfe_clk",		vfe_clk.c,		NULL),
+	CLK_LOOKUP("vfe_clk",		vfe_clk.c,		""),
 	CLK_LOOKUP("core_clk",		vfe_clk.c,	"footswitch-8x60.8"),
-	CLK_LOOKUP("csi_vfe_clk",	csi_vfe_clk.c,		NULL),
+	CLK_LOOKUP("csi_vfe_clk",	csi_vfe_clk.c,		""),
 	CLK_LOOKUP("bus_clk",		vfe_axi_clk.c,	"footswitch-8x60.8"),
 	CLK_LOOKUP("bus_clk",		mdp_axi_clk.c,	"footswitch-8x60.4"),
 	CLK_LOOKUP("bus_clk",		rot_axi_clk.c,	"footswitch-8x60.6"),
@@ -4982,63 +5033,63 @@
 	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,		NULL),
-	CLK_LOOKUP("csi_pclk",		csi_p_clk.c,		NULL),
-	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("amp_pclk",		amp_p_clk.c,		""),
+	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("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,		NULL),
-	CLK_LOOKUP("slave_iface_clk",	hdmi_s_p_clk.c,		NULL),
-	CLK_LOOKUP("ijpeg_pclk",	ijpeg_p_clk.c,		NULL),
+	CLK_LOOKUP("master_iface_clk",	hdmi_m_p_clk.c,		""),
+	CLK_LOOKUP("slave_iface_clk",	hdmi_s_p_clk.c,		""),
+	CLK_LOOKUP("ijpeg_pclk",	ijpeg_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		ijpeg_p_clk.c,	"footswitch-8x60.3"),
-	CLK_LOOKUP("iface_clk",		jpegd_p_clk.c,		NULL),
-	CLK_LOOKUP("mem_iface_clk",	imem_p_clk.c,		NULL),
-	CLK_LOOKUP("mdp_pclk",		mdp_p_clk.c,		NULL),
+	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("iface_clk",		mdp_p_clk.c,	"footswitch-8x60.4"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,		NULL),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		rot_p_clk.c,	"msm_rotator.0"),
 	CLK_LOOKUP("iface_clk",		rot_p_clk.c,	"footswitch-8x60.6"),
 	CLK_LOOKUP("iface_clk",		vcodec_p_clk.c,		"msm_vidc.0"),
 	CLK_LOOKUP("iface_clk",		vcodec_p_clk.c,	"footswitch-8x60.7"),
-	CLK_LOOKUP("vfe_pclk",		vfe_p_clk.c,		NULL),
+	CLK_LOOKUP("vfe_pclk",		vfe_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		vfe_p_clk.c,	"footswitch-8x60.8"),
-	CLK_LOOKUP("vpe_pclk",		vpe_p_clk.c,		NULL),
+	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,		NULL),
-	CLK_LOOKUP("mi2s_osr_clk",	mi2s_osr_clk.c,		NULL),
-	CLK_LOOKUP("i2s_mic_bit_clk",	codec_i2s_mic_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_mic_osr_clk",	codec_i2s_mic_osr_clk.c,	NULL),
-	CLK_LOOKUP("i2s_mic_bit_clk",	spare_i2s_mic_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_mic_osr_clk",	spare_i2s_mic_osr_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_bit_clk",	codec_i2s_spkr_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_osr_clk",	codec_i2s_spkr_osr_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_bit_clk",	spare_i2s_spkr_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_osr_clk",	spare_i2s_spkr_osr_clk.c,	NULL),
-	CLK_LOOKUP("pcm_clk",		pcm_clk.c,		NULL),
-	CLK_LOOKUP("sps_slimbus_clk",	sps_slimbus_clk.c,	NULL),
-	CLK_LOOKUP("audio_slimbus_clk",	audio_slimbus_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		jpegd_axi_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		vpe_axi_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		vcap_axi_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		rot_axi_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		ijpeg_axi_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		vfe_axi_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		vcodec_axi_a_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		vcodec_axi_b_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gfx3d_axi_clk.c,	NULL),
-	CLK_DUMMY("dfab_dsps_clk",	DFAB_DSPS_CLK,		NULL, 0),
+	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, ""),
+	CLK_LOOKUP("i2s_mic_osr_clk",	codec_i2s_mic_osr_clk.c, ""),
+	CLK_LOOKUP("i2s_mic_bit_clk",	spare_i2s_mic_bit_clk.c, ""),
+	CLK_LOOKUP("i2s_mic_osr_clk",	spare_i2s_mic_osr_clk.c, ""),
+	CLK_LOOKUP("i2s_spkr_bit_clk",	codec_i2s_spkr_bit_clk.c, ""),
+	CLK_LOOKUP("i2s_spkr_osr_clk",	codec_i2s_spkr_osr_clk.c, ""),
+	CLK_LOOKUP("i2s_spkr_bit_clk",	spare_i2s_spkr_bit_clk.c, ""),
+	CLK_LOOKUP("i2s_spkr_osr_clk",	spare_i2s_spkr_osr_clk.c, ""),
+	CLK_LOOKUP("pcm_clk",		pcm_clk.c,		""),
+	CLK_LOOKUP("sps_slimbus_clk",	sps_slimbus_clk.c,	""),
+	CLK_LOOKUP("audio_slimbus_clk",	audio_slimbus_clk.c,	""),
+	CLK_LOOKUP("core_clk",		jpegd_axi_clk.c,	""),
+	CLK_LOOKUP("core_clk",		vpe_axi_clk.c,		""),
+	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,		""),
+	CLK_LOOKUP("core_clk",		vcap_axi_clk.c,		""),
+	CLK_LOOKUP("core_clk",		rot_axi_clk.c,		""),
+	CLK_LOOKUP("core_clk",		ijpeg_axi_clk.c,	""),
+	CLK_LOOKUP("core_clk",		vfe_axi_clk.c,		""),
+	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,		NULL, 0),
-	CLK_DUMMY("bus_clk",		DFAB_SDC2_CLK,		NULL, 0),
-	CLK_DUMMY("bus_clk",		DFAB_SDC3_CLK,		NULL, 0),
-	CLK_DUMMY("bus_clk",		DFAB_SDC4_CLK,		NULL, 0),
-	CLK_DUMMY("dfab_clk",		DFAB_CLK,		NULL, 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("alt_core_clk",    usb_hsic_xcvr_fs_clk.c,  "msm_hsic_host"),
 	CLK_LOOKUP("phy_clk",	      usb_hsic_hsic_clk.c,     "msm_hsic_host"),
@@ -5048,13 +5099,13 @@
 
 	CLK_LOOKUP("mem_clk",		ebi1_adm_clk.c, "msm_dmov"),
 
-	CLK_LOOKUP("l2_mclk",		l2_m_clk,     NULL),
-	CLK_LOOKUP("krait0_mclk",	krait0_m_clk, NULL),
-	CLK_LOOKUP("krait1_mclk",	krait1_m_clk, NULL),
+	CLK_LOOKUP("l2_mclk",		l2_m_clk,     ""),
+	CLK_LOOKUP("krait0_mclk",	krait0_m_clk, ""),
+	CLK_LOOKUP("krait1_mclk",	krait1_m_clk, ""),
 };
 
 static struct clk_lookup msm_clocks_8960_v1[] __initdata = {
-	CLK_LOOKUP("cxo",		cxo_clk.c,	NULL),
+	CLK_LOOKUP("xo",		cxo_clk.c,	"msm_otg"),
 	CLK_LOOKUP("cxo",		cxo_clk.c,	"wcnss_wlan.0"),
 	CLK_LOOKUP("cxo",		cxo_clk.c,	"pil_riva"),
 	CLK_LOOKUP("xo",		pxo_clk.c,	"pil_qdsp6v4.0"),
@@ -5085,34 +5136,34 @@
 	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,		NULL),
-	CLK_LOOKUP("core_clk",		gp1_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		gp2_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		gsbi1_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi2_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi3_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi4_uart_clk.c,	NULL),
+	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,	""),
+	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, "msm_serial_hsl.0"),
 	CLK_LOOKUP("core_clk",		gsbi6_uart_clk.c, "msm_serial_hs.0"),
-	CLK_LOOKUP("core_clk",		gsbi7_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi8_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi9_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi10_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi11_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi12_uart_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		gsbi7_uart_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi8_uart_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi9_uart_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi10_uart_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi11_uart_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi12_uart_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi1_qup_clk.c,	"spi_qsd.0"),
-	CLK_LOOKUP("core_clk",		gsbi2_qup_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		gsbi2_qup_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi3_qup_clk.c,	"qup_i2c.3"),
 	CLK_LOOKUP("core_clk",		gsbi4_qup_clk.c,	"qup_i2c.4"),
-	CLK_LOOKUP("core_clk",		gsbi5_qup_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi6_qup_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi7_qup_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi8_qup_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi9_qup_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		gsbi5_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi6_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi7_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi8_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi9_qup_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi10_qup_clk.c,	"qup_i2c.10"),
-	CLK_LOOKUP("core_clk",		gsbi11_qup_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		gsbi11_qup_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi12_qup_clk.c,	"qup_i2c.12"),
-	CLK_LOOKUP("core_clk",		pdm_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		pdm_clk.c,		""),
 	CLK_LOOKUP("mem_clk",		pmem_clk.c,		"msm_sps"),
 	CLK_LOOKUP("core_clk",		prng_clk.c,		"msm_rng.0"),
 	CLK_LOOKUP("core_clk",		sdc1_clk.c,		"msm_sdcc.1"),
@@ -5121,36 +5172,36 @@
 	CLK_LOOKUP("core_clk",		sdc4_clk.c,		"msm_sdcc.4"),
 	CLK_LOOKUP("core_clk",		sdc5_clk.c,		"msm_sdcc.5"),
 	CLK_LOOKUP("slimbus_xo_src_clk", slimbus_xo_src_clk.c,	NULL),
-	CLK_LOOKUP("ref_clk",		tsif_ref_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		tssc_clk.c,		NULL),
+	CLK_LOOKUP("ref_clk",		tsif_ref_clk.c,		""),
+	CLK_LOOKUP("core_clk",		tssc_clk.c,		""),
 	CLK_LOOKUP("alt_core_clk",	usb_hs1_xcvr_clk.c,	"msm_otg"),
 	CLK_LOOKUP("phy_clk",		usb_phy0_clk.c,		"msm_otg"),
-	CLK_LOOKUP("alt_core_clk",	usb_fs1_xcvr_clk.c,	NULL),
-	CLK_LOOKUP("sys_clk",		usb_fs1_sys_clk.c,	NULL),
-	CLK_LOOKUP("src_clk",		usb_fs1_src_clk.c,	NULL),
-	CLK_LOOKUP("alt_core_clk",	usb_fs2_xcvr_clk.c,	NULL),
-	CLK_LOOKUP("sys_clk",		usb_fs2_sys_clk.c,	NULL),
-	CLK_LOOKUP("src_clk",		usb_fs2_src_clk.c,	NULL),
+	CLK_LOOKUP("alt_core_clk",	usb_fs1_xcvr_clk.c,	""),
+	CLK_LOOKUP("sys_clk",		usb_fs1_sys_clk.c,	""),
+	CLK_LOOKUP("src_clk",		usb_fs1_src_clk.c,	""),
+	CLK_LOOKUP("alt_core_clk",	usb_fs2_xcvr_clk.c,	""),
+	CLK_LOOKUP("sys_clk",		usb_fs2_sys_clk.c,	""),
+	CLK_LOOKUP("src_clk",		usb_fs2_src_clk.c,	""),
 	CLK_LOOKUP("iface_clk",		ce1_p_clk.c,		"qce.0"),
 	CLK_LOOKUP("iface_clk",		ce1_p_clk.c,		"qcrypto.0"),
 	CLK_LOOKUP("core_clk",		ce1_core_clk.c,		"qce.0"),
 	CLK_LOOKUP("core_clk",		ce1_core_clk.c,		"qcrypto.0"),
 	CLK_LOOKUP("dma_bam_pclk",	dma_bam_p_clk.c,	NULL),
 	CLK_LOOKUP("iface_clk",		gsbi1_p_clk.c,		"spi_qsd.0"),
-	CLK_LOOKUP("iface_clk",		gsbi2_p_clk.c,		NULL),
+	CLK_LOOKUP("iface_clk",		gsbi2_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		gsbi3_p_clk.c,		"qup_i2c.3"),
 	CLK_LOOKUP("iface_clk",		gsbi4_p_clk.c,		"qup_i2c.4"),
 	CLK_LOOKUP("iface_clk",		gsbi5_p_clk.c,	"msm_serial_hsl.0"),
 	CLK_LOOKUP("iface_clk",		gsbi6_p_clk.c,  "msm_serial_hs.0"),
-	CLK_LOOKUP("iface_clk",		gsbi7_p_clk.c,		NULL),
-	CLK_LOOKUP("iface_clk",		gsbi8_p_clk.c,		NULL),
-	CLK_LOOKUP("iface_clk",		gsbi9_p_clk.c,		NULL),
+	CLK_LOOKUP("iface_clk",		gsbi7_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		gsbi8_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		gsbi9_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		gsbi10_p_clk.c,		"qup_i2c.10"),
-	CLK_LOOKUP("iface_clk",		gsbi11_p_clk.c,		NULL),
+	CLK_LOOKUP("iface_clk",		gsbi11_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		gsbi12_p_clk.c,		"qup_i2c.12"),
-	CLK_LOOKUP("iface_clk",		tsif_p_clk.c,		NULL),
-	CLK_LOOKUP("iface_clk",		usb_fs1_p_clk.c,	NULL),
-	CLK_LOOKUP("iface_clk",		usb_fs2_p_clk.c,	NULL),
+	CLK_LOOKUP("iface_clk",		tsif_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		usb_fs1_p_clk.c,	""),
+	CLK_LOOKUP("iface_clk",		usb_fs2_p_clk.c,	""),
 	CLK_LOOKUP("iface_clk",		usb_hs1_p_clk.c,	"msm_otg"),
 	CLK_LOOKUP("iface_clk",		sdc1_p_clk.c,		"msm_sdcc.1"),
 	CLK_LOOKUP("iface_clk",		sdc2_p_clk.c,		"msm_sdcc.2"),
@@ -5159,11 +5210,11 @@
 	CLK_LOOKUP("iface_clk",		sdc5_p_clk.c,		"msm_sdcc.5"),
 	CLK_LOOKUP("core_clk",		adm0_clk.c,		"msm_dmov"),
 	CLK_LOOKUP("iface_clk",		adm0_p_clk.c,		"msm_dmov"),
-	CLK_LOOKUP("iface_clk",		pmic_arb0_p_clk.c,	NULL),
-	CLK_LOOKUP("iface_clk",		pmic_arb1_p_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		pmic_ssbi2_clk.c,	NULL),
-	CLK_LOOKUP("mem_clk",		rpm_msg_ram_p_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		amp_clk.c,		NULL),
+	CLK_LOOKUP("iface_clk",		pmic_arb0_p_clk.c,	""),
+	CLK_LOOKUP("iface_clk",		pmic_arb1_p_clk.c,	""),
+	CLK_LOOKUP("core_clk",		pmic_ssbi2_clk.c,	""),
+	CLK_LOOKUP("mem_clk",		rpm_msg_ram_p_clk.c,	""),
+	CLK_LOOKUP("core_clk",		amp_clk.c,		""),
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-001a"),
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-006c"),
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-0048"),
@@ -5192,10 +5243,10 @@
 	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,		NULL),
+	CLK_LOOKUP("mem_clk",		imem_axi_clk.c,		""),
 	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,		NULL),
+	CLK_LOOKUP("core_clk",		jpegd_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,	NULL),
@@ -5243,8 +5294,8 @@
 	CLK_LOOKUP("slave_iface_clk",	hdmi_s_p_clk.c,	"hdmi_msm.1"),
 	CLK_LOOKUP("ijpeg_pclk",	ijpeg_p_clk.c,		NULL),
 	CLK_LOOKUP("iface_clk",		ijpeg_p_clk.c,	"footswitch-8x60.3"),
-	CLK_LOOKUP("iface_clk",		jpegd_p_clk.c,		NULL),
-	CLK_LOOKUP("mem_iface_clk",	imem_p_clk.c,		NULL),
+	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,		NULL),
 	CLK_LOOKUP("iface_clk",		mdp_p_clk.c,	"footswitch-8x60.4"),
 	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu"),
@@ -5302,12 +5353,12 @@
 
 	CLK_LOOKUP("mem_clk",		ebi1_adm_clk.c, "msm_dmov"),
 
-	CLK_LOOKUP("l2_mclk",		l2_m_clk,     NULL),
-	CLK_LOOKUP("krait0_mclk",	krait0_m_clk, NULL),
-	CLK_LOOKUP("krait1_mclk",	krait1_m_clk, NULL),
-	CLK_LOOKUP("q6sw_clk",		q6sw_clk, NULL),
-	CLK_LOOKUP("q6fw_clk",		q6fw_clk, NULL),
-	CLK_LOOKUP("q6_func_clk",	q6_func_clk, NULL),
+	CLK_LOOKUP("l2_mclk",		l2_m_clk,     ""),
+	CLK_LOOKUP("krait0_mclk",	krait0_m_clk, ""),
+	CLK_LOOKUP("krait1_mclk",	krait1_m_clk, ""),
+	CLK_LOOKUP("q6sw_clk",		q6sw_clk,     ""),
+	CLK_LOOKUP("q6fw_clk",		q6fw_clk,     ""),
+	CLK_LOOKUP("q6_func_clk",	q6_func_clk,  ""),
 };
 
 static struct clk_lookup msm_clocks_8960_v2[] __initdata = {
@@ -5771,15 +5822,6 @@
 	} else
 		/* CSI2 hardware not present on 8960v1 devices */
 		pix_rdi_mux_map[2] = NULL;
-
-	if (machine_is_msm8960_sim()) {
-		clk_set_rate(&sdc1_clk.c, 48000000);
-		clk_enable(&sdc1_clk.c);
-		clk_enable(&sdc1_p_clk.c);
-		clk_set_rate(&sdc3_clk.c, 48000000);
-		clk_enable(&sdc3_clk.c);
-		clk_enable(&sdc3_p_clk.c);
-	}
 }
 
 static int __init msm8960_clock_late_init(void)
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 17f5d01..043cdbc 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -496,6 +496,7 @@
 	.reset = rcg_clk_reset,
 	.is_local = local_clk_is_local,
 	.get_parent = rcg_clk_get_parent,
+	.set_flags = rcg_clk_set_flags,
 };
 
 static struct clk_ops clk_ops_branch = {
@@ -507,6 +508,7 @@
 	.is_local = local_clk_is_local,
 	.get_parent = branch_clk_get_parent,
 	.set_parent = branch_clk_set_parent,
+	.set_flags = branch_clk_set_flags,
 };
 
 static struct clk_ops clk_ops_reset = {
@@ -557,6 +559,8 @@
 		.reset_mask = BIT(10),
 		.halt_reg = DBG_BUS_VEC_E_REG,
 		.halt_bit = 7,
+		.retain_reg = MAXI_EN2_REG,
+		.retain_mask = BIT(10),
 	},
 	.c = {
 		.dbg_name = "imem_axi_clk",
@@ -587,6 +591,8 @@
 		.reset_mask = BIT(13),
 		.halt_reg = DBG_BUS_VEC_E_REG,
 		.halt_bit = 8,
+		.retain_reg = MAXI_EN_REG,
+		.retain_mask = BIT(0),
 	},
 	.c = {
 		.dbg_name = "mdp_axi_clk",
@@ -967,6 +973,8 @@
 		.reset_mask = BIT(0),
 		.halt_reg = DBG_BUS_VEC_F_REG,
 		.halt_bit = 14,
+		.retain_reg = AHB_EN2_REG,
+		.retain_mask = BIT(0),
 	},
 	.c = {
 		.dbg_name = "vfe_p_clk",
@@ -2154,6 +2162,8 @@
 		.halt_check = DELAY,
 		.reset_reg = SW_RESET_CORE_REG,
 		.reset_mask = BIT(7),
+		.retain_reg = MISC_CC2_REG,
+		.retain_mask = BIT(10),
 	},
 	.ns_reg = MISC_CC2_REG,
 	.root_en_mask = BIT(2),
@@ -2234,6 +2244,8 @@
 		.reset_mask = BIT(14),
 		.halt_reg = DBG_BUS_VEC_A_REG,
 		.halt_bit = 9,
+		.retain_reg = GFX2D0_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = GFX2D0_NS_REG,
 	.root_en_mask = BIT(2),
@@ -2276,6 +2288,8 @@
 		.reset_mask = BIT(13),
 		.halt_reg = DBG_BUS_VEC_A_REG,
 		.halt_bit = 14,
+		.retain_reg = GFX2D1_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = GFX2D1_NS_REG,
 	.root_en_mask = BIT(2),
@@ -2346,6 +2360,8 @@
 		.reset_mask = BIT(12),
 		.halt_reg = DBG_BUS_VEC_A_REG,
 		.halt_bit = 4,
+		.retain_reg = GFX3D_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = GFX3D_NS_REG,
 	.root_en_mask = BIT(2),
@@ -2394,6 +2410,8 @@
 		.reset_mask = BIT(9),
 		.halt_reg = DBG_BUS_VEC_A_REG,
 		.halt_bit = 24,
+		.retain_reg = IJPEG_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = IJPEG_NS_REG,
 	.md_reg = IJPEG_MD_REG,
@@ -2436,6 +2454,8 @@
 		.reset_mask = BIT(19),
 		.halt_reg = DBG_BUS_VEC_A_REG,
 		.halt_bit = 19,
+		.retain_reg = JPEGD_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = JPEGD_NS_REG,
 	.root_en_mask = BIT(2),
@@ -2506,6 +2526,8 @@
 		.reset_mask = BIT(21),
 		.halt_reg = DBG_BUS_VEC_C_REG,
 		.halt_bit = 10,
+		.retain_reg = MDP_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = MDP_NS_REG,
 	.root_en_mask = BIT(2),
@@ -2591,6 +2613,8 @@
 		.reset_mask = BIT(5),
 		.halt_reg = DBG_BUS_VEC_C_REG,
 		.halt_bit = 23,
+		.retain_reg = PIXEL_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(31, 16) | BM(15, 14) | BM(2, 0)),
@@ -2664,6 +2688,8 @@
 		.reset_mask = BIT(2),
 		.halt_reg = DBG_BUS_VEC_C_REG,
 		.halt_bit = 15,
+		.retain_reg = ROT_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = ROT_NS_REG,
 	.root_en_mask = BIT(2),
@@ -2713,6 +2739,8 @@
 	.b = {
 		.ctl_reg = TV_CC_REG,
 		.halt_check = NOCHECK,
+		.retain_reg = TV_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.md_reg = TV_MD_REG,
 	.root_en_mask = BIT(2),
@@ -2841,6 +2869,8 @@
 		.reset_mask = BIT(6),
 		.halt_reg = DBG_BUS_VEC_C_REG,
 		.halt_bit = 29,
+		.retain_reg = VCODEC_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = VCODEC_NS_REG,
 	.md_reg = VCODEC_MD0_REG,
@@ -2888,6 +2918,8 @@
 		.reset_mask = BIT(17),
 		.halt_reg = DBG_BUS_VEC_A_REG,
 		.halt_bit = 28,
+		.retain_reg = VPE_CC_REG,
+		.retain_mask =  BIT(31),
 	},
 	.ns_reg = VPE_NS_REG,
 	.root_en_mask = BIT(2),
@@ -2943,6 +2975,8 @@
 		.halt_reg = DBG_BUS_VEC_B_REG,
 		.halt_bit = 6,
 		.en_mask = BIT(0),
+		.retain_reg = VFE_CC_REG,
+		.retain_mask = BIT(31),
 	},
 	.ns_reg = VFE_NS_REG,
 	.md_reg = VFE_MD_REG,
@@ -3545,35 +3579,35 @@
 	CLK_LOOKUP("mmfpb_clk",		mmfpb_clk.c,	NULL),
 	CLK_LOOKUP("mmfpb_a_clk",	mmfpb_a_clk.c,	NULL),
 
-	CLK_LOOKUP("core_clk",		gp0_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		gp1_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		gp2_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		gsbi1_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi2_uart_clk.c,	NULL),
+	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,	""),
+	CLK_LOOKUP("core_clk",		gsbi2_uart_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi3_uart_clk.c, "msm_serial_hsl.2"),
-	CLK_LOOKUP("core_clk",		gsbi4_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi5_uart_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		gsbi4_uart_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi5_uart_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi6_uart_clk.c, "msm_serial_hs.0"),
-	CLK_LOOKUP("core_clk",		gsbi7_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi8_uart_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		gsbi7_uart_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi8_uart_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi9_uart_clk.c, "msm_serial_hsl.1"),
-	CLK_LOOKUP("core_clk",		gsbi10_uart_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi11_uart_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		gsbi10_uart_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi11_uart_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi12_uart_clk.c, "msm_serial_hsl.0"),
 	CLK_LOOKUP("core_clk",		gsbi1_qup_clk.c,	"spi_qsd.0"),
-	CLK_LOOKUP("core_clk",		gsbi2_qup_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		gsbi2_qup_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi3_qup_clk.c,	"qup_i2c.0"),
 	CLK_LOOKUP("core_clk",		gsbi4_qup_clk.c,	"qup_i2c.1"),
-	CLK_LOOKUP("core_clk",		gsbi5_qup_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gsbi6_qup_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		gsbi5_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi6_qup_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi7_qup_clk.c,	"qup_i2c.4"),
 	CLK_LOOKUP("core_clk",		gsbi8_qup_clk.c,	"qup_i2c.3"),
 	CLK_LOOKUP("core_clk",		gsbi9_qup_clk.c,	"qup_i2c.2"),
 	CLK_LOOKUP("core_clk",		gsbi10_qup_clk.c,	"spi_qsd.1"),
-	CLK_LOOKUP("core_clk",		gsbi11_qup_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		gsbi11_qup_clk.c,	""),
 	CLK_LOOKUP("gsbi_qup_clk",	gsbi12_qup_clk.c,	"msm_dsps"),
 	CLK_LOOKUP("core_clk",		gsbi12_qup_clk.c,	"qup_i2c.5"),
-	CLK_LOOKUP("core_clk",		pdm_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		pdm_clk.c,		""),
 	CLK_LOOKUP("mem_clk",		pmem_clk.c,		"msm_dsps"),
 	CLK_LOOKUP("core_clk",		prng_clk.c,	"msm_rng.0"),
 	CLK_LOOKUP("core_clk",		sdc1_clk.c, "msm_sdcc.1"),
@@ -3583,57 +3617,57 @@
 	CLK_LOOKUP("core_clk",		sdc5_clk.c, "msm_sdcc.5"),
 	CLK_LOOKUP("ref_clk",		tsif_ref_clk.c,		"msm_tsif.0"),
 	CLK_LOOKUP("ref_clk",		tsif_ref_clk.c,		"msm_tsif.1"),
-	CLK_LOOKUP("core_clk",		tssc_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		tssc_clk.c,		""),
 	CLK_LOOKUP("alt_core_clk",	usb_hs1_xcvr_clk.c,	"msm_otg"),
 	CLK_LOOKUP("phy_clk",		usb_phy0_clk.c,		"msm_otg"),
-	CLK_LOOKUP("alt_core_clk",	usb_fs1_xcvr_clk.c,	NULL),
-	CLK_LOOKUP("sys_clk",		usb_fs1_sys_clk.c,	NULL),
-	CLK_LOOKUP("src_clk",		usb_fs1_src_clk.c,	NULL),
-	CLK_LOOKUP("alt_core_clk",	usb_fs2_xcvr_clk.c,	NULL),
-	CLK_LOOKUP("sys_clk",		usb_fs2_sys_clk.c,	NULL),
-	CLK_LOOKUP("src_clk",		usb_fs2_src_clk.c,	NULL),
+	CLK_LOOKUP("alt_core_clk",	usb_fs1_xcvr_clk.c,	""),
+	CLK_LOOKUP("sys_clk",		usb_fs1_sys_clk.c,	""),
+	CLK_LOOKUP("src_clk",		usb_fs1_src_clk.c,	""),
+	CLK_LOOKUP("alt_core_clk",	usb_fs2_xcvr_clk.c,	""),
+	CLK_LOOKUP("sys_clk",		usb_fs2_sys_clk.c,	""),
+	CLK_LOOKUP("src_clk",		usb_fs2_src_clk.c,	""),
 	CLK_LOOKUP("core_clk",		ce2_p_clk.c,		"qce.0"),
 	CLK_LOOKUP("core_clk",		ce2_p_clk.c,		"qcrypto.0"),
 	CLK_LOOKUP("iface_clk",		gsbi1_p_clk.c,		"spi_qsd.0"),
-	CLK_LOOKUP("iface_clk",		gsbi2_p_clk.c,		NULL),
+	CLK_LOOKUP("iface_clk",		gsbi2_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		gsbi3_p_clk.c, "msm_serial_hsl.2"),
 	CLK_LOOKUP("iface_clk",		gsbi3_p_clk.c,		"qup_i2c.0"),
 	CLK_LOOKUP("iface_clk",		gsbi4_p_clk.c,		"qup_i2c.1"),
-	CLK_LOOKUP("iface_clk",		gsbi5_p_clk.c,		NULL),
+	CLK_LOOKUP("iface_clk",		gsbi5_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		gsbi6_p_clk.c, "msm_serial_hs.0"),
 	CLK_LOOKUP("iface_clk",		gsbi7_p_clk.c,		"qup_i2c.4"),
 	CLK_LOOKUP("iface_clk",		gsbi8_p_clk.c,		"qup_i2c.3"),
 	CLK_LOOKUP("iface_clk",		gsbi9_p_clk.c, "msm_serial_hsl.1"),
 	CLK_LOOKUP("iface_clk",		gsbi9_p_clk.c,		"qup_i2c.2"),
 	CLK_LOOKUP("iface_clk",		gsbi10_p_clk.c,		"spi_qsd.1"),
-	CLK_LOOKUP("iface_clk",		gsbi11_p_clk.c,		NULL),
-	CLK_LOOKUP("iface_clk",		gsbi12_p_clk.c,		NULL),
+	CLK_LOOKUP("iface_clk",		gsbi11_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		gsbi12_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		gsbi12_p_clk.c, "msm_serial_hsl.0"),
 	CLK_LOOKUP("iface_clk",		gsbi12_p_clk.c,		"qup_i2c.5"),
-	CLK_LOOKUP("ppss_pclk",		ppss_p_clk.c,		NULL),
+	CLK_LOOKUP("ppss_pclk",		ppss_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		tsif_p_clk.c,		"msm_tsif.0"),
 	CLK_LOOKUP("iface_clk",		tsif_p_clk.c,		"msm_tsif.1"),
-	CLK_LOOKUP("iface_clk",		usb_fs1_p_clk.c,		NULL),
-	CLK_LOOKUP("iface_clk",		usb_fs2_p_clk.c,		NULL),
+	CLK_LOOKUP("iface_clk",		usb_fs1_p_clk.c,	""),
+	CLK_LOOKUP("iface_clk",		usb_fs2_p_clk.c,	""),
 	CLK_LOOKUP("iface_clk",		usb_hs1_p_clk.c,	"msm_otg"),
 	CLK_LOOKUP("iface_clk",		sdc1_p_clk.c, "msm_sdcc.1"),
 	CLK_LOOKUP("iface_clk",		sdc2_p_clk.c, "msm_sdcc.2"),
 	CLK_LOOKUP("iface_clk",		sdc3_p_clk.c, "msm_sdcc.3"),
 	CLK_LOOKUP("iface_clk",		sdc4_p_clk.c, "msm_sdcc.4"),
 	CLK_LOOKUP("iface_clk",		sdc5_p_clk.c, "msm_sdcc.5"),
-	CLK_LOOKUP("mem_clk",		ebi2_2x_clk.c,		NULL),
+	CLK_LOOKUP("mem_clk",		ebi2_2x_clk.c,		""),
 	CLK_LOOKUP("mem_clk",		ebi2_clk.c,		"msm_ebi2"),
 	CLK_LOOKUP("core_clk",		adm0_clk.c, "msm_dmov.0"),
 	CLK_LOOKUP("iface_clk",		adm0_p_clk.c, "msm_dmov.0"),
 	CLK_LOOKUP("core_clk",		adm1_clk.c, "msm_dmov.1"),
 	CLK_LOOKUP("iface_clk",		adm1_p_clk.c, "msm_dmov.1"),
-	CLK_LOOKUP("modem_ahb1_pclk",	modem_ahb1_p_clk.c,	NULL),
-	CLK_LOOKUP("modem_ahb2_pclk",	modem_ahb2_p_clk.c,	NULL),
-	CLK_LOOKUP("iface_clk",		pmic_arb0_p_clk.c,	NULL),
-	CLK_LOOKUP("iface_clk",		pmic_arb1_p_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		pmic_ssbi2_clk.c,		NULL),
-	CLK_LOOKUP("mem_clk",		rpm_msg_ram_p_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		amp_clk.c,		NULL),
+	CLK_LOOKUP("iface_clk",		modem_ahb1_p_clk.c,	""),
+	CLK_LOOKUP("iface_clk",		modem_ahb2_p_clk.c,	""),
+	CLK_LOOKUP("iface_clk",		pmic_arb0_p_clk.c,	""),
+	CLK_LOOKUP("iface_clk",		pmic_arb1_p_clk.c,	""),
+	CLK_LOOKUP("core_clk",		pmic_ssbi2_clk.c,	""),
+	CLK_LOOKUP("mem_clk",		rpm_msg_ram_p_clk.c,	""),
+	CLK_LOOKUP("core_clk",		amp_clk.c,		""),
 	CLK_LOOKUP("cam_clk",		cam_clk.c,		NULL),
 	CLK_LOOKUP("csi_clk",		csi0_clk.c,		NULL),
 	CLK_LOOKUP("csi_clk",		csi1_clk.c, "msm_camera_ov7692.0"),
@@ -3748,9 +3782,9 @@
 	CLK_LOOKUP("mem_clk",		ebi1_adm0_clk.c, "msm_dmov.0"),
 	CLK_LOOKUP("mem_clk",		ebi1_adm1_clk.c, "msm_dmov.1"),
 
-	CLK_LOOKUP("sc0_mclk",		sc0_m_clk, NULL),
-	CLK_LOOKUP("sc1_mclk",		sc1_m_clk, NULL),
-	CLK_LOOKUP("l2_mclk",		l2_m_clk,  NULL),
+	CLK_LOOKUP("sc0_mclk",		sc0_m_clk, ""),
+	CLK_LOOKUP("sc1_mclk",		sc1_m_clk, ""),
+	CLK_LOOKUP("l2_mclk",		l2_m_clk,  ""),
 };
 
 /*
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 3592c43..98d9cb2 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -1201,7 +1201,7 @@
 			.ctl_reg = ns, \
 			.en_mask = BIT(19), \
 			.halt_reg = h_r, \
-			.halt_check = ENABLE, \
+			.halt_check = DELAY, \
 		}, \
 		.ns_reg = ns, \
 		.ext_mask = BIT(18), \
@@ -1598,7 +1598,7 @@
 };
 
 static struct clk_lookup msm_clocks_9615[] = {
-	CLK_LOOKUP("cxo",	cxo_clk.c,	NULL),
+	CLK_LOOKUP("xo",	cxo_clk.c,	"msm_otg"),
 	CLK_LOOKUP("pll0",	pll0_clk.c,	NULL),
 	CLK_LOOKUP("pll8",	pll8_clk.c,	NULL),
 	CLK_LOOKUP("pll14",	pll14_clk.c,	NULL),
@@ -1622,25 +1622,25 @@
 	CLK_LOOKUP("dfab_clk",		dfab_clk.c,	NULL),
 	CLK_LOOKUP("dfab_a_clk",	dfab_a_clk.c,	NULL),
 
-	CLK_LOOKUP("core_clk",		gp0_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gp1_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gp2_clk.c,	NULL),
+	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", gsbi3_uart_clk.c, NULL),
+	CLK_LOOKUP("core_clk", gsbi3_uart_clk.c, ""),
 	CLK_LOOKUP("core_clk", gsbi4_uart_clk.c, "msm_serial_hsl.0"),
-	CLK_LOOKUP("core_clk", gsbi5_uart_clk.c, NULL),
+	CLK_LOOKUP("core_clk", gsbi5_uart_clk.c, ""),
 
 	CLK_LOOKUP("core_clk",	gsbi3_qup_clk.c, "spi_qsd.0"),
-	CLK_LOOKUP("core_clk",	gsbi4_qup_clk.c, NULL),
+	CLK_LOOKUP("core_clk",	gsbi4_qup_clk.c, ""),
 	CLK_LOOKUP("core_clk",	gsbi5_qup_clk.c, "qup_i2c.0"),
 
-	CLK_LOOKUP("core_clk",		pdm_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		pdm_clk.c,		""),
 	CLK_LOOKUP("mem_clk",		pmem_clk.c,		"msm_sps"),
 	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("iface_clk",		ce1_p_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		ce1_core_clk.c,		NULL),
+	CLK_LOOKUP("iface_clk",		ce1_p_clk.c,		""),
+	CLK_LOOKUP("core_clk",		ce1_core_clk.c,		""),
 	CLK_LOOKUP("dma_bam_pclk",	dma_bam_p_clk.c,	NULL),
 
 	CLK_LOOKUP("iface_clk",	gsbi3_p_clk.c, "spi_qsd.0"),
@@ -1665,10 +1665,10 @@
 	CLK_LOOKUP("iface_clk",		sdc2_p_clk.c,		"msm_sdcc.2"),
 	CLK_LOOKUP("core_clk",		adm0_clk.c,		"msm_dmov"),
 	CLK_LOOKUP("iface_clk",		adm0_p_clk.c,		"msm_dmov"),
-	CLK_LOOKUP("iface_clk",		pmic_arb0_p_clk.c,	NULL),
-	CLK_LOOKUP("iface_clk",		pmic_arb1_p_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		pmic_ssbi2_clk.c,	NULL),
-	CLK_LOOKUP("mem_clk",		rpm_msg_ram_p_clk.c,	NULL),
+	CLK_LOOKUP("iface_clk",		pmic_arb0_p_clk.c,	""),
+	CLK_LOOKUP("iface_clk",		pmic_arb1_p_clk.c,	""),
+	CLK_LOOKUP("core_clk",		pmic_ssbi2_clk.c,	""),
+	CLK_LOOKUP("mem_clk",		rpm_msg_ram_p_clk.c,	""),
 	CLK_LOOKUP("mi2s_bit_clk",	mi2s_bit_clk.c,		NULL),
 	CLK_LOOKUP("mi2s_osr_clk",	mi2s_osr_clk.c,		NULL),
 
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 1bb9c86..c02c6f3 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -924,6 +924,38 @@
 	branch_disable_hwcg(&branch->b);
 }
 
+static int branch_set_flags(struct branch *b, unsigned flags)
+{
+	unsigned long irq_flags;
+	u32 reg_val;
+	int ret = 0;
+
+	if (!b->retain_reg)
+		return -EPERM;
+
+	spin_lock_irqsave(&local_clock_reg_lock, irq_flags);
+	reg_val = readl_relaxed(b->retain_reg);
+	switch (flags) {
+	case CLKFLAG_RETAIN:
+		reg_val |= b->retain_mask;
+		break;
+	case CLKFLAG_NORETAIN:
+		reg_val &= ~b->retain_mask;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	writel_relaxed(reg_val, b->retain_reg);
+	spin_unlock_irqrestore(&local_clock_reg_lock, irq_flags);
+
+	return ret;
+}
+
+int branch_clk_set_flags(struct clk *clk, unsigned flags)
+{
+	return branch_set_flags(&to_branch_clk(clk)->b, flags);
+}
+
 int branch_clk_in_hwcg_mode(struct clk *c)
 {
 	struct branch_clk *clk = to_branch_clk(c);
@@ -948,6 +980,11 @@
 	return branch_in_hwcg_mode(&clk->b);
 }
 
+int rcg_clk_set_flags(struct clk *clk, unsigned flags)
+{
+	return branch_set_flags(&to_rcg_clk(clk)->b, flags);
+}
+
 int branch_reset(struct branch *b, enum clk_reset_action action)
 {
 	int ret = 0;
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 9292e5d..8ea344b 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -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
@@ -164,12 +164,16 @@
 
 	void __iomem *const reset_reg;
 	const u32 reset_mask;
+
+	void __iomem *const retain_reg;
+	const u32 retain_mask;
 };
 
 int branch_reset(struct branch *b, enum clk_reset_action action);
 void __branch_clk_enable_reg(const struct branch *clk, const char *name);
 u32 __branch_clk_disable_reg(const struct branch *clk, const char *name);
 int branch_clk_handoff(struct clk *c);
+int branch_clk_set_flags(struct clk *clk, unsigned flags);
 
 /*
  * Generic clock-definition struct and macros
@@ -213,6 +217,7 @@
 void rcg_clk_enable_hwcg(struct clk *clk);
 void rcg_clk_disable_hwcg(struct clk *clk);
 int rcg_clk_in_hwcg_mode(struct clk *c);
+int rcg_clk_set_flags(struct clk *clk, unsigned flags);
 
 /**
  * struct cdiv_clk - integer divider clock with external source selection
diff --git a/arch/arm/mach-msm/clock-pcom-lookup.c b/arch/arm/mach-msm/clock-pcom-lookup.c
index a98e7f1..200cbfe 100644
--- a/arch/arm/mach-msm/clock-pcom-lookup.c
+++ b/arch/arm/mach-msm/clock-pcom-lookup.c
@@ -149,7 +149,7 @@
 	CLK_LOOKUP("ebi2_clk",		ebi2_clk.c,	NULL),
 	CLK_LOOKUP("ecodec_clk",	ecodec_clk.c,	NULL),
 	CLK_LOOKUP("emdh_clk",		emdh_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gp_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		gp_clk.c,	""),
 	CLK_LOOKUP("core_clk",		grp_3d_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("core_clk",		i2c_clk.c,	"msm_i2c.0"),
 	CLK_LOOKUP("icodec_rx_clk",	icodec_rx_clk.c,	NULL),
@@ -201,7 +201,7 @@
 	CLK_LOOKUP("ebi1_clk",		ebi1_clk.c,	NULL),
 	CLK_LOOKUP("ebi2_clk",		ebi2_clk.c,	NULL),
 	CLK_LOOKUP("ecodec_clk",	ecodec_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gp_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		gp_clk.c,	""),
 	CLK_LOOKUP("core_clk",		grp_3d_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("core_clk",		grp_3d_clk.c,	"footswitch-pcom.2"),
 	CLK_LOOKUP("iface_clk",		grp_3d_p_clk.c,	"kgsl-3d0.0"),
@@ -287,7 +287,7 @@
 	CLK_LOOKUP("ebi1_clk",		ebi1_clk.c,	NULL),
 	CLK_LOOKUP("ebi2_clk",		ebi2_clk.c,	NULL),
 	CLK_LOOKUP("ecodec_clk",	ecodec_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gp_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		gp_clk.c,	""),
 	CLK_LOOKUP("core_clk",		grp_3d_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("core_clk",		grp_3d_clk.c,	"footswitch-pcom.2"),
 	CLK_LOOKUP("iface_clk",		grp_3d_p_clk.c,	"kgsl-3d0.0"),
@@ -354,7 +354,7 @@
 	CLK_LOOKUP("ebi2_clk",		ebi2_clk.c,	NULL),
 	CLK_LOOKUP("ecodec_clk",	ecodec_clk.c,	NULL),
 	CLK_LOOKUP("emdh_clk",		emdh_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",		gp_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		gp_clk.c,	""),
 	CLK_LOOKUP("core_clk",		grp_3d_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("core_clk",		i2c_clk.c,	"msm_i2c.0"),
 	CLK_LOOKUP("icodec_rx_clk",	icodec_rx_clk.c,	NULL),
@@ -397,8 +397,8 @@
 	CLK_LOOKUP("vfe_axi_clk",	vfe_axi_clk.c,	NULL),
 	CLK_LOOKUP("alt_core_clk",	usb_hs2_clk.c,	 "msm_hsusb_host.0"),
 	CLK_LOOKUP("iface_clk",		usb_hs2_p_clk.c, "msm_hsusb_host.0"),
-	CLK_LOOKUP("alt_core_clk",	usb_hs3_clk.c,	 NULL),
-	CLK_LOOKUP("iface_clk",		usb_hs3_p_clk.c, NULL),
+	CLK_LOOKUP("alt_core_clk",	usb_hs3_clk.c,	 ""),
+	CLK_LOOKUP("iface_clk",		usb_hs3_p_clk.c, ""),
 	CLK_LOOKUP("phy_clk",		usb_phy_clk.c,	 "msm_otg"),
 
 	CLK_LOOKUP("ebi1_acpu_clk",	ebi_acpu_clk.c,	NULL),
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 5a9b199..4210bd9 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -30,6 +30,8 @@
 #define CLKFLAG_NORESET			0x00000008
 #define CLKFLAG_HANDOFF_RATE		0x00000010
 #define CLKFLAG_HWCG			0x00000020
+#define CLKFLAG_RETAIN			0x00000040
+#define CLKFLAG_NORETAIN		0x00000080
 #define CLKFLAG_SKIP_AUTO_OFF		0x00000200
 #define CLKFLAG_MIN			0x00000400
 #define CLKFLAG_MAX			0x00000800
diff --git a/arch/arm/mach-msm/devices-msm7x27.c b/arch/arm/mach-msm/devices-msm7x27.c
index cdb43ad..b895870 100644
--- a/arch/arm/mach-msm/devices-msm7x27.c
+++ b/arch/arm/mach-msm/devices-msm7x27.c
@@ -43,8 +43,8 @@
 		.flags	= IORESOURCE_IRQ,
 	},
 	{
-		.start	= MSM_UART1_PHYS,
-		.end	= MSM_UART1_PHYS + MSM_UART1_SIZE - 1,
+		.start	= MSM7XXX_UART1_PHYS,
+		.end	= MSM7XXX_UART1_PHYS + MSM7XXX_UART1_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 };
@@ -56,8 +56,8 @@
 		.flags	= IORESOURCE_IRQ,
 	},
 	{
-		.start	= MSM_UART2_PHYS,
-		.end	= MSM_UART2_PHYS + MSM_UART2_SIZE - 1,
+		.start	= MSM7XXX_UART2_PHYS,
+		.end	= MSM7XXX_UART2_PHYS + MSM7XXX_UART2_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 };
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 6a59b08..f3a95a6 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -228,8 +228,8 @@
 		.flags	= IORESOURCE_IRQ,
 	},
 	{
-		.start	= MSM_UART1_PHYS,
-		.end	= MSM_UART1_PHYS + MSM_UART1_SIZE - 1,
+		.start	= MSM7XXX_UART1_PHYS,
+		.end	= MSM7XXX_UART1_PHYS + MSM7XXX_UART1_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 };
@@ -573,8 +573,8 @@
 static struct resource msm_clkctl_resources[] = {
 	{
 		.name   = "clk_ctl",
-		.start  = MSM_CLK_CTL_PHYS,
-		.end    = MSM_CLK_CTL_PHYS + MSM_CLK_CTL_SIZE - 1,
+		.start  = MSM7XXX_CLK_CTL_PHYS,
+		.end    = MSM7XXX_CLK_CTL_PHYS + MSM7XXX_CLK_CTL_SIZE - 1,
 		.flags  = IORESOURCE_MEM,
 	},
 };
@@ -802,8 +802,8 @@
 		.flags  = IORESOURCE_IRQ,
 	},
 	{
-		.start	= MSM_UART1_PHYS,
-		.end    = MSM_UART1_PHYS + MSM_UART1_SIZE - 1,
+		.start	= MSM7XXX_UART1_PHYS,
+		.end    = MSM7XXX_UART1_PHYS + MSM7XXX_UART1_SIZE - 1,
 		.flags  = IORESOURCE_MEM,
 	},
 };
@@ -837,6 +837,35 @@
 	},
 };
 
+static struct resource gsbi0_msm8625_qup_resources[] = {
+	{
+		.name	= "qup_phys_addr",
+		.start	= MSM_GSBI0_QUP_PHYS,
+		.end	= MSM_GSBI0_QUP_PHYS + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "gsbi_qup_i2c_addr",
+		.start	= MSM_GSBI0_PHYS,
+		.end	= MSM_GSBI0_PHYS + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "qup_err_intr",
+		.start	= MSM8625_INT_PWB_I2C,
+		.end	= MSM8625_INT_PWB_I2C,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+/* Use GSBI0 QUP for /dev/i2c-0 */
+struct platform_device msm8625_device_qup_i2c_gsbi0 = {
+	.name		= "qup_i2c",
+	.id		= MSM_GSBI0_QUP_I2C_BUS_ID,
+	.num_resources	= ARRAY_SIZE(gsbi0_msm8625_qup_resources),
+	.resource	= gsbi0_msm8625_qup_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),
@@ -931,6 +960,13 @@
 		   (0x2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) | \
 		   (0x1 << L2X0_AUX_CTRL_EVNT_MON_BUS_EN_SHIFT);
 
+	if (cpu_is_msm8625()) {
+		/* Way Size 011(0x3) 64KB */
+		aux_ctrl |= (0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) | \
+			    (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) | \
+			    (0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT);
+	}
+
 	l2x0_init(MSM_L2CC_BASE, aux_ctrl, L2X0_AUX_CTRL_MASK);
 
 	return 0;
@@ -966,7 +1002,7 @@
 
 	if (socinfo_init() < 0)
 		pr_err("%s: socinfo_init() failed!\n", __func__);
-
+	msm7x27x_cache_init();
 }
 
 static int msm7627a_init_gpio(void)
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 176d14a..5d42f99 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -118,6 +118,8 @@
 extern struct platform_device msm_gsbi9_qup_i2c_device;
 extern struct platform_device msm_gsbi12_qup_i2c_device;
 
+extern struct platform_device msm8625_device_qup_i2c_gsbi0;
+
 extern struct platform_device msm_slim_ctrl;
 extern struct platform_device msm_device_sps;
 extern struct platform_device msm_device_usb_bam;
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index cd6e582..296c111 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.c
@@ -213,6 +213,9 @@
 		udelay(RESET_DELAY_US);
 	}
 
+	/* Prevent core memory from collapsing when its clock is gated. */
+	clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);
+
 	/* Return clocks to their state before this function. */
 	restore_clocks(fs);
 
@@ -242,6 +245,9 @@
 	if (rc)
 		return rc;
 
+	/* Allow core memory to collapse when its clock is gated. */
+	clk_set_flags(fs->core_clk, CLKFLAG_NORETAIN);
+
 	/* Halt all bus ports in the power domain. */
 	if (fs->bus_port0) {
 		rc = msm_bus_axi_porthalt(fs->bus_port0);
@@ -294,6 +300,7 @@
 err_port2_halt:
 	msm_bus_axi_portunhalt(fs->bus_port0);
 err:
+	clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);
 	restore_clocks(fs);
 	return rc;
 }
@@ -360,6 +367,9 @@
 	/* Re-enable core clock. */
 	clk_prepare_enable(fs->core_clk);
 
+	/* Prevent core memory from collapsing when its clock is gated. */
+	clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);
+
 	/* Return clocks to their state before this function. */
 	restore_clocks(fs);
 
@@ -387,6 +397,9 @@
 	if (rc)
 		return rc;
 
+	/* Allow core memory to collapse when its clock is gated. */
+	clk_set_flags(fs->core_clk, CLKFLAG_NORETAIN);
+
 	/* Halt all bus ports in the power domain. */
 	if (fs->bus_port0) {
 		rc = msm_bus_axi_porthalt(fs->bus_port0);
@@ -431,6 +444,7 @@
 	return 0;
 
 err:
+	clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);
 	restore_clocks(fs);
 	return rc;
 }
diff --git a/arch/arm/mach-msm/footswitch-pcom.c b/arch/arm/mach-msm/footswitch-pcom.c
index c48c141..340f19b 100644
--- a/arch/arm/mach-msm/footswitch-pcom.c
+++ b/arch/arm/mach-msm/footswitch-pcom.c
@@ -18,6 +18,7 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/clk.h>
+#include <mach/socinfo.h>
 #include "footswitch.h"
 #include "proc_comm.h"
 
@@ -305,6 +306,8 @@
 	struct footswitch *fs;
 	int ret;
 
+	if (cpu_is_msm8625())
+		return 0;
 	/*
 	 * Enable all footswitches in manual mode (ie. not controlled along
 	 * with pcom clocks).
diff --git a/arch/arm/mach-msm/include/mach/bam_dmux.h b/arch/arm/mach-msm/include/mach/bam_dmux.h
index fb70da4..fe1c3f0 100644
--- a/arch/arm/mach-msm/include/mach/bam_dmux.h
+++ b/arch/arm/mach-msm/include/mach/bam_dmux.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
@@ -58,39 +58,54 @@
 
 int msm_bam_dmux_write(uint32_t id, struct sk_buff *skb);
 
-void msm_bam_dmux_kickoff_ul_wakeup(void);
+int msm_bam_dmux_kickoff_ul_wakeup(void);
+
+int msm_bam_dmux_ul_power_vote(void);
+
+int msm_bam_dmux_ul_power_unvote(void);
 
 int msm_bam_dmux_is_ch_full(uint32_t id);
 
 int msm_bam_dmux_is_ch_low(uint32_t id);
 #else
-int msm_bam_dmux_open(uint32_t id, void *priv,
+static inline int msm_bam_dmux_open(uint32_t id, void *priv,
 		       void (*notify)(void *priv, int event_type,
 						unsigned long data))
 {
 	return -ENODEV;
 }
 
-int msm_bam_dmux_close(uint32_t id)
+static inline int msm_bam_dmux_close(uint32_t id)
 {
 	return -ENODEV;
 }
 
-int msm_bam_dmux_write(uint32_t id, struct sk_buff *skb)
+static inline int msm_bam_dmux_write(uint32_t id, struct sk_buff *skb)
 {
 	return -ENODEV;
 }
 
-void msm_bam_dmux_kickoff_ul_wakeup(void)
-{
-}
-
-int msm_bam_dmux_is_ch_full(uint32_t id)
+static inline int msm_bam_dmux_kickoff_ul_wakeup(void)
 {
 	return -ENODEV;
 }
 
-int msm_bam_dmux_is_ch_low(uint32_t id)
+static inline int msm_bam_dmux_ul_power_vote(void)
+{
+	return -ENODEV;
+}
+
+static inline int msm_bam_dmux_ul_power_unvote(void)
+{
+	return -ENODEV;
+}
+
+static inline int msm_bam_dmux_is_ch_full(uint32_t id)
+{
+	return -ENODEV;
+}
+
+static inline int msm_bam_dmux_is_ch_low(uint32_t id)
 {
 	return -ENODEV;
 }
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 8c61a42..bb33289 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -75,7 +75,7 @@
 	VFE_MSG_STATS_AEC,
 	VFE_MSG_STATS_AF,
 	VFE_MSG_STATS_AWB,
-	VFE_MSG_STATS_RS,
+	VFE_MSG_STATS_RS, /* 10 */
 	VFE_MSG_STATS_CS,
 	VFE_MSG_STATS_IHIST,
 	VFE_MSG_STATS_SKIN,
@@ -85,11 +85,13 @@
 	VFE_MSG_SYNC_TIMER2,
 	VFE_MSG_COMMON,
 	VFE_MSG_V32_START,
-	VFE_MSG_V32_START_RECORDING,
+	VFE_MSG_V32_START_RECORDING, /* 20 */
 	VFE_MSG_V32_CAPTURE,
 	VFE_MSG_OUTPUT_IRQ,
 	VFE_MSG_V2X_PREVIEW,
 	VFE_MSG_V2X_CAPTURE,
+	VFE_MSG_OUTPUT_PRIMARY,
+	VFE_MSG_OUTPUT_SECONDARY,
 };
 
 enum vpe_resp_msg {
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index e1fc054..6e946aa 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -44,7 +44,11 @@
 #define EBI0_PAGE_OFFSET PAGE_OFFSET
 #define EBI0_SIZE 0x10000000
 
-#define EBI1_PHYS_OFFSET 0x40000000
+#ifndef __ASSEMBLY__
+
+extern unsigned long ebi1_phys_offset;
+
+#define EBI1_PHYS_OFFSET (ebi1_phys_offset)
 #define EBI1_PAGE_OFFSET (EBI0_PAGE_OFFSET + EBI0_SIZE)
 
 #if (defined(CONFIG_SPARSEMEM) && defined(CONFIG_VMSPLIT_3G))
@@ -60,6 +64,7 @@
 	(virt) - EBI0_PAGE_OFFSET + EBI0_PHYS_OFFSET)
 
 #endif
+#endif
 
 #endif
 
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 ba50a30..88bc3c6 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h
@@ -35,80 +35,43 @@
  *
  */
 
-#define MSM_VIC_BASE          IOMEM(0xFA000000)
-#define MSM_VIC_PHYS          0xC0000000
-#define MSM_VIC_SIZE          SZ_4K
+#define MSM7XXX_VIC_PHYS          0xC0000000
+#define MSM7XXX_VIC_SIZE          SZ_4K
 
-#define MSM_CSR_BASE          IOMEM(0xFA001000)
-#define MSM_CSR_PHYS          0xC0100000
-#define MSM_CSR_SIZE          SZ_4K
+#define MSM7XXX_CSR_PHYS          0xC0100000
+#define MSM7XXX_CSR_SIZE          SZ_4K
 
-#define MSM_TMR_PHYS          MSM_CSR_PHYS
-#define MSM_TMR_BASE          MSM_CSR_BASE
-#define MSM_TMR_SIZE          SZ_4K
+#define MSM7XXX_TMR_PHYS          MSM7XXX_CSR_PHYS
+#define MSM7XXX_TMR_SIZE          SZ_4K
 
-#define MSM_TMR0_BASE         MSM_TMR_BASE
+#define MSM7XXX_TMR0_PHYS         0xC0800000
+#define MSM7XXX_TMR0_SIZE         SZ_4K
 
-#define MSM_GPIO1_BASE        IOMEM(0xFA003000)
-#define MSM_GPIO1_PHYS        0xA9200000
-#define MSM_GPIO1_SIZE        SZ_4K
+#define MSM7XXX_GPIO1_PHYS        0xA9200000
+#define MSM7XXX_GPIO1_SIZE        SZ_4K
 
-#define MSM_GPIO2_BASE        IOMEM(0xFA004000)
-#define MSM_GPIO2_PHYS        0xA9300000
-#define MSM_GPIO2_SIZE        SZ_4K
+#define MSM7XXX_GPIO2_PHYS        0xA9300000
+#define MSM7XXX_GPIO2_SIZE        SZ_4K
 
-#define MSM_CLK_CTL_BASE      IOMEM(0xFA005000)
-#define MSM_CLK_CTL_PHYS      0xA8600000
-#define MSM_CLK_CTL_SIZE      SZ_4K
+#define MSM7XXX_CLK_CTL_PHYS      0xA8600000
+#define MSM7XXX_CLK_CTL_SIZE      SZ_4K
 
-#define MSM_L2CC_BASE         IOMEM(0xFA006000)
-#define MSM_L2CC_PHYS         0xC0400000
-#define MSM_L2CC_SIZE         SZ_4K
+#define MSM7XXX_L2CC_PHYS         0xC0400000
+#define MSM7XXX_L2CC_SIZE         SZ_4K
 
-#define MSM_QGIC_DIST_BASE    IOMEM(0xFA000000)
-#define MSM_QGIC_DIST_PHYS    0xC0000000
-#define MSM_QGIC_DIST_SIZE    SZ_4K
+#define MSM7XXX_UART1_PHYS        0xA9A00000
+#define MSM7XXX_UART1_SIZE        SZ_4K
 
-#define MSM_QGIC_CPU_BASE     IOMEM(0xFA007000)
-#define MSM_QGIC_CPU_PHYS     0xC0002000
-#define MSM_QGIC_CPU_SIZE     SZ_256
+#define MSM7XXX_UART2_PHYS        0xA9B00000
+#define MSM7XXX_UART2_SIZE        SZ_4K
 
-#define MSM_SCU_BASE          IOMEM(0xFA008000)
-#define MSM_SCU_PHYS          0xC0600000
-#define MSM_SCU_SIZE          SZ_256
+#define MSM7XXX_UART3_PHYS        0xA9C00000
+#define MSM7XXX_UART3_SIZE        SZ_4K
 
-#define MSM_SPM0_BASE         IOMEM(0xFA009000)
-#define MSM_SPM0_PHYS         0xC0200000
-#define MSM_SPM0_SIZE         SZ_4K
+#define MSM7XXX_MDC_PHYS	  0xAA500000
+#define MSM7XXX_MDC_SIZE          SZ_1M
 
-#define MSM_SPM1_BASE         IOMEM(0xFA00A000)
-#define MSM_SPM1_PHYS         0xC0700000
-#define MSM_SPM1_SIZE         SZ_4K
-
-#define MSM_CFG_CTL_BASE      IOMEM(0xFA00B000)
-#define MSM_CFG_CTL_PHYS      0xA9800000
-#define MSM_CFG_CTL_SIZE      SZ_4K
-
-#define MSM_SHARED_RAM_BASE   IOMEM(0xFA100000)
-#define MSM_SHARED_RAM_SIZE   SZ_1M
-
-#define MSM_UART1_PHYS        0xA9A00000
-#define MSM_UART1_SIZE        SZ_4K
-
-#define MSM_UART2_PHYS        0xA9B00000
-#define MSM_UART2_SIZE        SZ_4K
-
-#define MSM_UART3_PHYS        0xA9C00000
-#define MSM_UART3_SIZE        SZ_4K
-
-#define MSM_MDC_BASE	      IOMEM(0xFA200000)
-#define MSM_MDC_PHYS	      0xAA500000
-#define MSM_MDC_SIZE	      SZ_1M
-
-#define MSM_AD5_BASE          IOMEM(0xFA300000)
-#define MSM_AD5_PHYS          0xAC000000
-#define MSM_AD5_SIZE          (SZ_1M*13)
-
-#define MSM_STRONGLY_ORDERED_PAGE  0xFA0F0000
+#define MSM7XXX_AD5_PHYS          0xAC000000
+#define MSM7XXX_AD5_SIZE          (SZ_1M*13)
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8064.h b/arch/arm/mach-msm/include/mach/msm_iomap-8064.h
index c584c66..7479712 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8064.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8064.h
@@ -1,6 +1,6 @@
 /*
  * 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.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -100,4 +100,7 @@
 #define APQ8064_QFPROM_PHYS		0x00700000
 #define APQ8064_QFPROM_SIZE		SZ_4K
 
+#define APQ8064_SIC_NON_SECURE_PHYS	0x12100000
+#define APQ8064_SIC_NON_SECURE_SIZE	SZ_64K
+
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8625.h b/arch/arm/mach-msm/include/mach/msm_iomap-8625.h
new file mode 100644
index 0000000..8088a4c
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8625.h
@@ -0,0 +1,60 @@
+/*
+ * 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
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * The MSM peripherals are spread all over across 768MB of physical
+ * space, which makes just having a simple IO_ADDRESS macro to slide
+ * them into the right virtual location rough.  Instead, we will
+ * provide a master phys->virt mapping for peripherals here.
+ *
+ */
+
+#ifndef __ASM_ARCH_MSM_IOMAP_8625_H
+#define __ASM_ARCH_MSM_IOMAP_8625_H
+
+/* Physical base address and size of peripherals.
+ * Ordered by the virtual base addresses they will be mapped at.
+ *
+ * If you add or remove entries here, you'll want to edit the
+ * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your
+ * changes.
+ *
+ */
+
+#define MSM8625_TMR_PHYS		0xC0800000
+#define MSM8625_TMR_SIZE		SZ_4K
+
+#define MSM8625_TMR0_PHYS		0xC0100000
+#define MSM8625_TMR0_SIZE		SZ_4K
+
+#define MSM8625_CLK_CTL_PHYS		0xA8600000
+#define MSM8625_CLK_CTL_SIZE		SZ_4K
+
+#define MSM8625_QGIC_DIST_PHYS		0xC0000000
+#define MSM8625_QGIC_DIST_SIZE		SZ_4K
+
+#define MSM8625_QGIC_CPU_PHYS		0xC0002000
+#define MSM8625_QGIC_CPU_SIZE		SZ_4K
+
+#define MSM8625_SCU_PHYS		0xC0600000
+#define MSM8625_SCU_SIZE		SZ_256
+
+#define MSM8625_SPM0_PHYS		0xC0200000
+#define MSM8625_SPM0_SIZE		SZ_4K
+
+#define MSM8625_SPM1_PHYS		0xC0700000
+#define MSM8625_SPM1_SIZE		SZ_4K
+
+#define MSM8625_CFG_CTL_PHYS		0xA9800000
+#define MSM8625_CFG_CTL_SIZE		SZ_4K
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index ff0b368..ca8daaa 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -1,6 +1,6 @@
 /*
  * 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.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -47,7 +47,10 @@
 
 #if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064) || \
 	defined(CONFIG_ARCH_MSM8930) || defined(CONFIG_ARCH_MSM9615) || \
-	defined(CONFIG_ARCH_MSMCOPPER)
+	defined(CONFIG_ARCH_MSMCOPPER) || defined(CONFIG_ARCH_MSM7X27) || \
+	defined(CONFIG_ARCH_MSM7X01A) || defined(CONFIG_ARCH_MSM7X25) || \
+	defined(CONFIG_ARCH_MSM8625)
+
 /* Unified iomap */
 
 #define MSM_TMR_BASE		IOMEM(0xFA000000)	/*  4K	*/
@@ -79,8 +82,21 @@
 #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 */
 
-#if defined(CONFIG_ARCH_MSM9615)
+
+#define MSM_STRONGLY_ORDERED_PAGE	0xFA0F0000
+
+#if defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_MSM7X27)
 #define MSM_SHARED_RAM_SIZE	SZ_1M
 #else
 #define MSM_SHARED_RAM_SIZE	SZ_2M
@@ -91,6 +107,8 @@
 #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 */
@@ -104,7 +122,7 @@
 #elif defined(CONFIG_ARCH_FSM9XXX)
 #include "msm_iomap-fsm9xxx.h"
 #else
-#include "msm_iomap-7xxx.h"
+#error "Target compiling without iomap"
 #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
new file mode 100644
index 0000000..2831428
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_rtb.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MSM_RTB_H__
+#define __MSM_RTB_H__
+
+enum logk_event_type {
+	LOGK_NONE = 0,
+	LOGK_READL,
+	LOGK_WRITEL,
+	LOGK_OTHER,
+};
+
+#if defined(CONFIG_MSM_RTB)
+/*
+ * returns 1 if data was logged, 0 otherwise
+ */
+int uncached_logk_pc(enum logk_event_type log_type, void *caller,
+				void *data);
+
+/*
+ * returns 1 if data was logged, 0 otherwise
+ */
+int uncached_logk(enum logk_event_type log_type, void *data);
+
+#else
+
+static inline int uncached_logk_pc(enum logk_event_type log_type,
+					void *caller,
+					void *data) { return 0; }
+
+static inline int uncached_logk(enum logk_event_type log_type,
+					void *data) { return 0; }
+#endif
+#endif
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h b/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
index 884c5d0..dd5ddd8 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
@@ -36,6 +36,9 @@
 #define US_SET_DETECTION _IOWR(USF_IOCTL_MAGIC, 8, \
 				struct us_detect_info_type)
 
+#define US_GET_VERSION  _IOWR(USF_IOCTL_MAGIC, 9, \
+				struct us_version_info_type)
+
 /* Special timeout values */
 #define USF_NO_WAIT_TIMEOUT	0x00000000
 /* Infinitive */
@@ -72,6 +75,15 @@
 #define USF_KEYBOARD_EVENT 4
 #define USF_ALL_EVENTS (USF_TSC_EVENT | USF_MOUSE_EVENT | USF_KEYBOARD_EVENT)
 
+/* min, max array dimension */
+#define MIN_MAX_DIM 2
+
+/* coordinates (x,y,z) array dimension */
+#define COORDINATES_DIM 3
+
+/* tilts (x,y) array dimension */
+#define TILTS_DIM 2
+
 /* Max size of the client name */
 #define USF_MAX_CLIENT_NAME_SIZE	20
 /* Info structure common for TX and RX */
@@ -102,17 +114,27 @@
 	uint8_t *params_data;
 };
 
+/* Input events sources */
+enum us_input_event_src_type {
+	US_INPUT_SRC_PEN,
+	US_INPUT_SRC_FINGER,
+	US_INPUT_SRC_UNDEF
+};
+
 struct us_input_info_type {
 	/* Touch screen dimensions: min & max;for input module */
-	int tsc_x_dim[2];
-	int tsc_y_dim[2];
-    /* Touch screen fuzz; for input module */
-	int tsc_x_fuzz;
-	int tsc_y_fuzz;
+	int tsc_x_dim[MIN_MAX_DIM];
+	int tsc_y_dim[MIN_MAX_DIM];
+	int tsc_z_dim[MIN_MAX_DIM];
+	/* Touch screen tilt dimensions: min & max;for input module */
+	int tsc_x_tilt[MIN_MAX_DIM];
+	int tsc_y_tilt[MIN_MAX_DIM];
 	/* Touch screen pressure limits: min & max; for input module */
-	int tsc_pressure[2];
+	int tsc_pressure[MIN_MAX_DIM];
 	/* Bitmap of types of events (USF_X_EVENT), produced by calculator */
 	uint16_t event_types;
+	/* Input event source */
+	enum us_input_event_src_type event_src;
 };
 
 struct us_tx_info_type {
@@ -132,10 +154,10 @@
 #define	USF_PIX_COORDINATE  0 /* unit is pixel */
 #define	USF_CMM_COORDINATE  1 /* unit is 0.01 mm */
 struct point_event_type {
-/* Pen coordinates (x, y) in units, defined by <coordinates_type>  */
-	int coordinates[2];
-/* {x;y}  in degrees [-90; 90] */
-	uint32_t inclinations[2];
+/* Pen coordinates (x, y, z) in units, defined by <coordinates_type>  */
+	int coordinates[COORDINATES_DIM];
+	/* {x;y}  in transparent units */
+	int inclinations[TILTS_DIM];
 /* [0-1023] (10bits); 0 - pen up */
 	uint32_t pressure;
 /* 0 - mapped in the display pixel. 1 - raw in 0.01 mm (only for log); */
@@ -148,7 +170,7 @@
 #define USF_BUTTON_RIGHT_MASK  4
 struct mouse_event_type {
 /* The mouse relative movement (dX, dY, dZ) */
-	int rels[3];
+	int rels[COORDINATES_DIM];
 /* Bitmap of mouse buttons states: 1 - down, 0 - up; */
 	uint16_t buttons_states;
 };
@@ -232,4 +254,11 @@
 	bool is_us;
 };
 
+struct us_version_info_type {
+/* Size of memory for the version string */
+	uint16_t buf_size;
+/* Pointer to the memory for the version string */
+	char *pbuf;
+};
+
 #endif /* __USF_H__ */
diff --git a/arch/arm/mach-msm/include/mach/smem_log.h b/arch/arm/mach-msm/include/mach/smem_log.h
index b977a82..a94ae76 100644
--- a/arch/arm/mach-msm/include/mach/smem_log.h
+++ b/arch/arm/mach-msm/include/mach/smem_log.h
@@ -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
@@ -37,6 +37,7 @@
 #define SMEM_LOG_PROC_ID_MODEM          0x00000000
 #define SMEM_LOG_PROC_ID_Q6             0x40000000
 #define SMEM_LOG_PROC_ID_APPS           0x80000000
+#define SMEM_LOG_PROC_ID_WCNSS          0xC0000000
 
 #define SMEM_LOG_CONT                   0x10000000
 
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 79c9aed..830db1f 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -58,23 +58,23 @@
 #if defined(CONFIG_ARCH_MSM7X01A) || defined(CONFIG_ARCH_MSM7X27) \
 	|| defined(CONFIG_ARCH_MSM7X25)
 static struct map_desc msm_io_desc[] __initdata = {
-	MSM_DEVICE(VIC),
-	MSM_DEVICE(CSR),
-	MSM_DEVICE(TMR),
-	MSM_DEVICE(GPIO1),
-	MSM_DEVICE(GPIO2),
-	MSM_DEVICE(CLK_CTL),
-	MSM_DEVICE(AD5),
-	MSM_DEVICE(MDC),
+	MSM_CHIP_DEVICE(VIC, MSM7XXX),
+	MSM_CHIP_DEVICE(CSR, MSM7XXX),
+	MSM_CHIP_DEVICE(TMR, MSM7XXX),
+	MSM_CHIP_DEVICE(GPIO1, MSM7XXX),
+	MSM_CHIP_DEVICE(GPIO2, MSM7XXX),
+	MSM_CHIP_DEVICE(CLK_CTL, MSM7XXX),
+	MSM_CHIP_DEVICE(AD5, MSM7XXX),
+	MSM_CHIP_DEVICE(MDC, MSM7XXX),
 #if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
 	defined(CONFIG_DEBUG_MSM_UART3)
-	MSM_DEVICE(DEBUG_UART),
+	MSM_CHIP_DEVICE(DEBUG_UART, MSM7XXX),
 #endif
 #ifdef CONFIG_CACHE_L2X0
 	{
 		.virtual =  (unsigned long) MSM_L2CC_BASE,
-		.pfn =      __phys_to_pfn(MSM_L2CC_PHYS),
-		.length =   MSM_L2CC_SIZE,
+		.pfn =      __phys_to_pfn(MSM7XXX_L2CC_PHYS),
+		.length =   MSM7XXX_L2CC_SIZE,
 		.type =     MT_DEVICE,
 	},
 #endif
@@ -279,6 +279,7 @@
 		.type =     MT_DEVICE,
 	},
 	MSM_CHIP_DEVICE(QFPROM, APQ8064),
+	MSM_CHIP_DEVICE(SIC_NON_SECURE, APQ8064),
 };
 
 void __init msm_map_apq8064_io(void)
@@ -399,27 +400,27 @@
 
 #ifdef CONFIG_ARCH_MSM8625
 static struct map_desc msm8625_io_desc[] __initdata = {
-	MSM_DEVICE(QGIC_DIST),
-	MSM_DEVICE(QGIC_CPU),
-	MSM_DEVICE(TMR),
-	MSM_DEVICE(TMR0),
-	MSM_DEVICE(CSR),
-	MSM_DEVICE(SCU),
-	MSM_DEVICE(CFG_CTL),
-	MSM_DEVICE(GPIO1),
-	MSM_DEVICE(GPIO2),
-	MSM_DEVICE(CLK_CTL),
-	MSM_DEVICE(SPM0),
-	MSM_DEVICE(SPM1),
+	MSM_CHIP_DEVICE(CSR, MSM7XXX),
+	MSM_CHIP_DEVICE(GPIO1, MSM7XXX),
+	MSM_CHIP_DEVICE(GPIO2, MSM7XXX),
+	MSM_CHIP_DEVICE(QGIC_DIST, MSM8625),
+	MSM_CHIP_DEVICE(QGIC_CPU, MSM8625),
+	MSM_CHIP_DEVICE(TMR, MSM8625),
+	MSM_CHIP_DEVICE(TMR0, MSM8625),
+	MSM_CHIP_DEVICE(SCU, MSM8625),
+	MSM_CHIP_DEVICE(CFG_CTL, MSM8625),
+	MSM_CHIP_DEVICE(CLK_CTL, MSM8625),
+	MSM_CHIP_DEVICE(SPM0, MSM8625),
+	MSM_CHIP_DEVICE(SPM1, MSM8625),
 #if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
 	defined(CONFIG_DEBUG_MSM_UART3)
-	MSM_DEVICE(DEBUG_UART),
+	MSM_CHIP_DEVICE(DEBUG_UART, MSM7XXX),
 #endif
 #ifdef CONFIG_CACHE_L2X0
 	{
 		.virtual = (unsigned long) MSM_L2CC_BASE,
-		.pfn	 = __phys_to_pfn(MSM_L2CC_PHYS),
-		.length	 = MSM_L2CC_SIZE,
+		.pfn	 = __phys_to_pfn(MSM7XXX_L2CC_PHYS),
+		.length	 = MSM7XXX_L2CC_SIZE,
 		.type	 = MT_DEVICE,
 	},
 #endif
diff --git a/arch/arm/mach-msm/msm_rtb.c b/arch/arm/mach-msm/msm_rtb.c
new file mode 100644
index 0000000..d765f6a
--- /dev/null
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -0,0 +1,229 @@
+/*
+ * 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/atomic.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/memory_alloc.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <asm/io.h>
+#include <asm-generic/sizes.h>
+#include <mach/memory.h>
+#include <mach/msm_rtb.h>
+#include <mach/system.h>
+
+#define SENTINEL_BYTE_1 0xFF
+#define SENTINEL_BYTE_2 0xAA
+#define SENTINEL_BYTE_3 0xFF
+
+/* Write
+ * 1) 3 bytes sentinel
+ * 2) 1 bytes of log type
+ * 3) 4 bytes of where the caller came from
+ * 4) 4 bytes index
+ * 4) 4 bytes extra data from the caller
+ *
+ * Total = 16 bytes.
+ */
+struct msm_rtb_layout {
+	unsigned char sentinel[3];
+	unsigned char log_type;
+	void *caller;
+	unsigned long idx;
+	void *data;
+} __attribute__ ((__packed__));
+
+
+struct msm_rtb_state {
+	struct msm_rtb_layout *rtb;
+	unsigned long phys;
+	int nentries;
+	int size;
+	int enabled;
+	uint32_t filter;
+	int step_size;
+};
+
+#if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
+DEFINE_PER_CPU(atomic_t, msm_rtb_idx_cpu);
+#else
+static atomic_t msm_rtb_idx;
+#endif
+
+struct msm_rtb_state msm_rtb = {
+	.size = SZ_1M,
+};
+
+module_param_named(filter, msm_rtb.filter, uint, 0644);
+module_param_named(enable, msm_rtb.enabled, int, 0644);
+
+int msm_rtb_event_should_log(enum logk_event_type log_type)
+{
+	return msm_rtb.enabled &&
+		((1 << log_type) & msm_rtb.filter);
+}
+EXPORT_SYMBOL(msm_rtb_event_should_log);
+
+static void msm_rtb_emit_sentinel(struct msm_rtb_layout *start)
+{
+	start->sentinel[0] = SENTINEL_BYTE_1;
+	start->sentinel[1] = SENTINEL_BYTE_2;
+	start->sentinel[2] = SENTINEL_BYTE_3;
+}
+
+static void msm_rtb_write_type(enum logk_event_type log_type,
+			struct msm_rtb_layout *start)
+{
+	start->log_type = (char)log_type;
+}
+
+static void msm_rtb_write_caller(void *caller, struct msm_rtb_layout *start)
+{
+	start->caller = caller;
+}
+
+static void msm_rtb_write_idx(unsigned long idx,
+				struct msm_rtb_layout *start)
+{
+	start->idx = idx;
+}
+
+static void msm_rtb_write_data(void *data, struct msm_rtb_layout *start)
+{
+	start->data = data;
+}
+
+static int __init msm_rtb_set_buffer_size(char *p)
+{
+	int s;
+
+	s = memparse(p, NULL);
+	msm_rtb.size = ALIGN(s, SZ_4K);
+	return 0;
+}
+early_param("msm_rtb_size", msm_rtb_set_buffer_size);
+
+#if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
+static int msm_rtb_get_idx(void)
+{
+	int cpu, i;
+	atomic_t *index;
+
+	/*
+	 * ideally we would use get_cpu but this is a close enough
+	 * approximation for our purposes.
+	 */
+	cpu = raw_smp_processor_id();
+
+	index = &per_cpu(msm_rtb_idx_cpu, cpu);
+
+	i = atomic_add_return(msm_rtb.step_size, index);
+	i -= msm_rtb.step_size;
+
+	return i;
+}
+#else
+static int msm_rtb_get_idx(void)
+{
+	int i;
+
+	i = atomic_inc_return(&msm_rtb_idx);
+	i--;
+
+	return i;
+}
+#endif
+
+int uncached_logk_pc(enum logk_event_type log_type, void *caller,
+				void *data)
+{
+	int i;
+	struct msm_rtb_layout *start;
+
+	if (!msm_rtb_event_should_log(log_type))
+		return 0;
+
+	i = msm_rtb_get_idx();
+
+	start = &msm_rtb.rtb[i & (msm_rtb.nentries - 1)];
+
+	msm_rtb_emit_sentinel(start);
+	msm_rtb_write_type(log_type, start);
+	msm_rtb_write_caller(caller, start);
+	msm_rtb_write_idx(i, start);
+	msm_rtb_write_data(data, start);
+	mb();
+
+	return 1;
+}
+EXPORT_SYMBOL(uncached_logk_pc);
+
+noinline int uncached_logk(enum logk_event_type log_type, void *data)
+{
+	return uncached_logk_pc(log_type, __builtin_return_address(0), data);
+}
+EXPORT_SYMBOL(uncached_logk);
+
+int msm_rtb_init(void)
+{
+#if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
+	unsigned int cpu;
+#endif
+
+	if (msm_rtb.size <= 0 || msm_rtb.size > SZ_1M)
+		return -EINVAL;
+
+	/*
+	 * The ioremap call is made separately to store the physical
+	 * address of the buffer. This is necessary for cases where
+	 * the only way to access the buffer is a physical address.
+	 */
+	msm_rtb.phys = allocate_contiguous_ebi_nomap(msm_rtb.size, SZ_4K);
+
+	if (!msm_rtb.phys)
+		return -ENOMEM;
+
+	msm_rtb.rtb = ioremap(msm_rtb.phys, msm_rtb.size);
+
+	if (!msm_rtb.rtb) {
+		free_contiguous_memory_by_paddr(msm_rtb.phys);
+		return -ENOMEM;
+	}
+
+	msm_rtb.nentries = msm_rtb.size / sizeof(struct msm_rtb_layout);
+
+	/* Round this down to a power of 2 */
+	msm_rtb.nentries = __rounddown_pow_of_two(msm_rtb.nentries);
+
+	memset(msm_rtb.rtb, 0, msm_rtb.size);
+
+
+#if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
+	for_each_possible_cpu(cpu) {
+		atomic_t *a = &per_cpu(msm_rtb_idx_cpu, cpu);
+		atomic_set(a, cpu);
+	}
+	msm_rtb.step_size = num_possible_cpus();
+#else
+	atomic_set(&msm_rtb_idx, 0);
+	msm_rtb.step_size = 1;
+#endif
+
+
+	msm_rtb.enabled = 1;
+	return 0;
+}
+module_init(msm_rtb_init)
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index b16b687..0886975 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -21,8 +21,6 @@
 #include <linux/memblock.h>
 #include <linux/slab.h>
 
-#include <mach/socinfo.h>
-
 #include <asm/uaccess.h>
 #include <asm/setup.h>
 
@@ -244,10 +242,6 @@
 	struct pil_device *pil_d;
 	void *retval;
 
-	/* PIL is not yet supported on 8064. */
-	if (cpu_is_apq8064())
-		return NULL;
-
 	pil = retval = find_peripheral(name);
 	if (!pil)
 		return ERR_PTR(-ENODEV);
diff --git a/arch/arm/mach-msm/pil-q6v3.c b/arch/arm/mach-msm/pil-q6v3.c
index 7354d93..06b98e5 100644
--- a/arch/arm/mach-msm/pil-q6v3.c
+++ b/arch/arm/mach-msm/pil-q6v3.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
@@ -19,6 +19,7 @@
 #include <linux/elf.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/workqueue.h>
 
 #include <mach/msm_iomap.h>
 
@@ -66,7 +67,7 @@
 	void __iomem *base;
 	unsigned long start_addr;
 	struct clk *pll;
-	struct timer_list timer;
+	struct delayed_work work;
 };
 
 static int nop_verify_blob(struct pil_desc *pil, u32 phy_addr, size_t size)
@@ -83,36 +84,40 @@
 	return 0;
 }
 
-static void q6v3_remove_proxy_votes(unsigned long data)
+static void q6v3_remove_proxy_votes(struct work_struct *work)
 {
-	struct q6v3_data *drv = (struct q6v3_data *)data;
-	clk_disable(drv->pll);
+	struct q6v3_data *drv = container_of(work, struct q6v3_data, work.work);
+	clk_disable_unprepare(drv->pll);
 }
 
-static void q6v3_make_proxy_votes(struct device *dev)
+static int q6v3_make_proxy_votes(struct device *dev)
 {
 	int ret;
 	struct q6v3_data *drv = dev_get_drvdata(dev);
 
-	ret = clk_enable(drv->pll);
-	if (ret)
+	ret = clk_prepare_enable(drv->pll);
+	if (ret) {
 		dev_err(dev, "Failed to enable PLL\n");
-	mod_timer(&drv->timer, jiffies + msecs_to_jiffies(PROXY_VOTE_TIMEOUT));
+		return ret;
+	}
+	schedule_delayed_work(&drv->work, msecs_to_jiffies(PROXY_VOTE_TIMEOUT));
+	return 0;
 }
 
 static void q6v3_remove_proxy_votes_now(struct q6v3_data *drv)
 {
-	/* If the proxy vote hasn't been removed yet, remove it immediately. */
-	if (del_timer(&drv->timer))
-		q6v3_remove_proxy_votes((unsigned long)drv);
+	flush_delayed_work(&drv->work);
 }
 
 static int pil_q6v3_reset(struct pil_desc *pil)
 {
 	u32 reg;
+	int ret;
 	struct q6v3_data *drv = dev_get_drvdata(pil->dev);
 
-	q6v3_make_proxy_votes(pil->dev);
+	ret = q6v3_make_proxy_votes(pil->dev);
+	if (ret)
+		return ret;
 
 	/* Put Q6 into reset */
 	reg = readl_relaxed(LCC_Q6_FUNC);
@@ -198,7 +203,10 @@
 
 static int pil_q6v3_reset_trusted(struct pil_desc *pil)
 {
-	q6v3_make_proxy_votes(pil->dev);
+	int ret;
+	ret = q6v3_make_proxy_votes(pil->dev);
+	if (ret)
+		return ret;
 	return pas_auth_and_reset(PAS_Q6);
 }
 
@@ -250,7 +258,6 @@
 	if (IS_ERR(drv->pll))
 		return PTR_ERR(drv->pll);
 
-	setup_timer(&drv->timer, q6v3_remove_proxy_votes, (unsigned long)drv);
 	desc->name = "q6";
 	desc->dev = &pdev->dev;
 
@@ -262,15 +269,19 @@
 		dev_info(&pdev->dev, "using non-secure boot\n");
 	}
 
-	if (msm_pil_register(desc))
+	INIT_DELAYED_WORK(&drv->work, q6v3_remove_proxy_votes);
+
+	if (msm_pil_register(desc)) {
+		flush_delayed_work_sync(&drv->work);
 		return -EINVAL;
+	}
 	return 0;
 }
 
 static int __devexit pil_q6v3_driver_exit(struct platform_device *pdev)
 {
 	struct q6v3_data *drv = platform_get_drvdata(pdev);
-	del_timer_sync(&drv->timer);
+	flush_delayed_work_sync(&drv->work);
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index 29a9df9..bd49fc0 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -372,16 +372,20 @@
 		dev_err(&pdev->dev, "failed to get pll supply\n");
 		return PTR_ERR(drv->pll_supply);
 	}
-	ret = regulator_set_voltage(drv->pll_supply, 1800000, 1800000);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to set pll supply voltage\n");
-		goto err;
-	}
+	if (regulator_count_voltages(drv->pll_supply) > 0) {
+		ret = regulator_set_voltage(drv->pll_supply, 1800000, 1800000);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"failed to set pll supply voltage\n");
+			goto err;
+		}
 
-	ret = regulator_set_optimum_mode(drv->pll_supply, 100000);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to set pll supply optimum mode\n");
-		goto err;
+		ret = regulator_set_optimum_mode(drv->pll_supply, 100000);
+		if (ret < 0) {
+			dev_err(&pdev->dev,
+				"failed to set pll supply optimum mode\n");
+			goto err;
+		}
 	}
 
 	desc->name = "wcnss";
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c
index b60140e..1182a4d 100644
--- a/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c
@@ -192,7 +192,7 @@
 		pr_err("%s: Registration with APR failed\n", __func__);
 		goto fail;
 	}
-	pr_info("%s: Registering the common port with APR\n", __func__);
+	pr_debug("%s: Registering the common port with APR\n", __func__);
 	if (atomic_read(&this_mmap.ref_cnt) == 0) {
 		this_mmap.apr = apr_register("ADSP", "USM",
 					     (apr_fn)q6usm_mmapcallback,
@@ -393,7 +393,7 @@
 			u32 cpu_buf = port->cpu_buf;
 			pr_err("%s: expected[%d] != token[%d]\n",
 				__func__, port->expected_token, token);
-			pr_info("%s: dsp_buf=%d; cpu_buf=%d;\n",
+			pr_debug("%s: dsp_buf=%d; cpu_buf=%d;\n",
 				__func__,   port->dsp_buf, cpu_buf);
 
 			token = USM_WRONG_TOKEN;
@@ -439,7 +439,7 @@
 			port->dsp_buf = 0;
 		spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
 
-		pr_info("%s: WRITE_DONE: token=%d; dsp_buf=%d; cpu_buf=%d\n",
+		pr_debug("%s: WRITE_DONE: token=%d; dsp_buf=%d; cpu_buf=%d\n",
 			__func__,
 			token, port->dsp_buf, port->cpu_buf);
 
@@ -659,11 +659,11 @@
 	/* Transparent data copy */
 	memcpy(enc_cfg->enc_blk.transp_data, us_cfg->params,
 	       us_cfg->params_size);
-	pr_info("%s: cfg_size[%d], params_size[%d]\n",
+	pr_debug("%s: cfg_size[%d], params_size[%d]\n",
 		__func__,
 		enc_cfg->enc_blk.cfg_size,
 		us_cfg->params_size);
-	pr_info("%s: params[%d,%d,%d,%d, %d,%d,%d,%d]\n",
+	pr_debug("%s: params[%d,%d,%d,%d, %d,%d,%d,%d]\n",
 		__func__,
 		enc_cfg->enc_blk.transp_data[0],
 		enc_cfg->enc_blk.transp_data[1],
@@ -674,7 +674,7 @@
 		enc_cfg->enc_blk.transp_data[6],
 		enc_cfg->enc_blk.transp_data[7]
 	       );
-	pr_info("%s: srate:%d, ch=%d, bps= %d; dmap:0x%x; dev_id=0x%x\n",
+	pr_debug("%s: srate:%d, ch=%d, bps= %d; dmap:0x%x; dev_id=0x%x\n",
 		__func__, enc_cfg->enc_blk.cfg_common.sample_rate,
 		enc_cfg->enc_blk.cfg_common.ch_cfg,
 		enc_cfg->enc_blk.cfg_common.bits_per_sample,
@@ -759,7 +759,7 @@
 	       sizeof(struct usm_cfg_common));
 	/* Transparent data copy */
 	memcpy(dec_cfg->transp_data, us_cfg->params, us_cfg->params_size);
-	pr_info("%s: cfg_size[%d], params_size[%d]; parambytes[%d,%d,%d,%d]\n",
+	pr_debug("%s: cfg_size[%d], params_size[%d]; parambytes[%d,%d,%d,%d]\n",
 		__func__,
 		dec_cfg->cfg_size,
 		us_cfg->params_size,
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
index bc0706e..64f70c5 100644
--- a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
@@ -26,7 +26,7 @@
 #include "q6usm.h"
 
 /* The driver version*/
-#define DRV_VERSION "1.1.1"
+#define DRV_VERSION "1.2"
 
 /* Standard timeout in the asynchronous ops */
 #define USF_TIMEOUT_JIFFIES (3*HZ) /* 3 sec */
@@ -35,11 +35,26 @@
 #define USF_UNDEF_DEV_ID 0xffff
 
 /* RX memory mapping flag */
-#define	USF_VM_WRITE	2
+#define USF_VM_WRITE 2
 
 /* Number of events, copied from the user space to kernel one */
 #define USF_EVENTS_PORTION_SIZE 20
 
+/* Indexes in range definitions */
+#define MIN_IND 0
+#define MAX_IND 1
+
+/* The coordinates indexes */
+#define X_IND 0
+#define Y_IND 1
+#define Z_IND 2
+
+/* Place for opreation result, received from QDSP6 */
+#define APR_RESULT_IND 1
+
+/* Place for US detection result, received from QDSP6 */
+#define APR_US_DETECT_RESULT_IND 0
+
 /* The driver states */
 enum usf_state_type {
 	USF_IDLE_STATE,
@@ -94,12 +109,21 @@
 	uint16_t event_types;
 	/*  The device is "input" module registered client */
 	struct input_dev *input_if;
+	/*  The event source */
+	int event_src;
 };
 
 /* The MAX number of the supported devices */
 #define MAX_DEVS_NUMBER	1
 
 /* The opened devices container */
+static const int s_event_src_map[] = {
+	BTN_TOOL_PEN, /* US_INPUT_SRC_PEN*/
+	0,            /* US_INPUT_SRC_FINGER */
+	0,            /* US_INPUT_SRC_UNDEF */
+};
+
+/* The opened devices container */
 static int s_opened_devs[MAX_DEVS_NUMBER];
 
 static void usf_rx_cb(uint32_t opcode, uint32_t token,
@@ -140,7 +164,7 @@
 		break;
 
 	case USM_SESSION_EVENT_SIGNAL_DETECT_RESULT:
-		usf_xx->us_detect_type = (payload[0]) ?
+		usf_xx->us_detect_type = (payload[APR_US_DETECT_RESULT_IND]) ?
 					USF_US_DETECT_YES :
 					USF_US_DETECT_NO;
 
@@ -148,7 +172,7 @@
 		break;
 
 	case APR_BASIC_RSP_RESULT:
-		if (payload[1]) {
+		if (payload[APR_RESULT_IND]) {
 			usf_xx->usf_state = USF_ERROR_STATE;
 			usf_xx->new_region = USM_WRONG_TOKEN;
 			wake_up(&usf_xx->wait);
@@ -208,11 +232,11 @@
 		}
 	}
 
-	pr_info("%s: name=%s; buf_size:%d; dev_id:0x%x; sample_rate:%d\n",
+	pr_debug("%s: name=%s; buf_size:%d; dev_id:0x%x; sample_rate:%d\n",
 		__func__, usf_xx->client_name, config->buf_size,
 		config->dev_id, config->sample_rate);
 
-	pr_info("%s: buf_num:%d; format:%d; port_cnt:%d; data_size=%d\n",
+	pr_debug("%s: buf_num:%d; format:%d; port_cnt:%d; data_size=%d\n",
 		__func__, config->buf_num, config->stream_format,
 		config->port_cnt, config->params_data_size);
 
@@ -329,18 +353,30 @@
 		input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 		input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 		input_set_abs_params(input_dev, ABS_X,
-				     input_info->tsc_x_dim[0],
-				     input_info->tsc_x_dim[1],
-				     input_info->tsc_x_fuzz, 0);
+				     input_info->tsc_x_dim[MIN_IND],
+				     input_info->tsc_x_dim[MAX_IND],
+				     0, 0);
 		input_set_abs_params(input_dev, ABS_Y,
-				     input_info->tsc_y_dim[0],
-				     input_info->tsc_y_dim[1],
-				     input_info->tsc_y_fuzz, 0);
+				     input_info->tsc_y_dim[MIN_IND],
+				     input_info->tsc_y_dim[MAX_IND],
+				     0, 0);
+		input_set_abs_params(input_dev, ABS_DISTANCE,
+				     input_info->tsc_z_dim[MIN_IND],
+				     input_info->tsc_z_dim[MAX_IND],
+				     0, 0);
 
 		input_set_abs_params(input_dev, ABS_PRESSURE,
-				     input_info->tsc_pressure[0],
-				     input_info->tsc_pressure[1], 0, 0);
+				     input_info->tsc_pressure[MIN_IND],
+				     input_info->tsc_pressure[MAX_IND], 0, 0);
 
+		input_set_abs_params(input_dev, ABS_TILT_X,
+				     input_info->tsc_x_tilt[MIN_IND],
+				     input_info->tsc_x_tilt[MAX_IND],
+				     0, 0);
+		input_set_abs_params(input_dev, ABS_TILT_Y,
+				     input_info->tsc_y_tilt[MIN_IND],
+				     input_info->tsc_y_tilt[MAX_IND],
+				     0, 0);
 	}
 
 	if (input_info->event_types & USF_MOUSE_EVENT) {
@@ -363,6 +399,14 @@
 		memset(input_dev->keybit, 0xff, sizeof(input_dev->keybit));
 	}
 
+	if (input_info->event_src < ARRAY_SIZE(s_event_src_map))
+		usf_info->event_src = s_event_src_map[input_info->event_src];
+	else
+		usf_info->event_src = 0;
+
+	if (usf_info->event_src)
+		input_set_capability(input_dev, EV_KEY, usf_info->event_src);
+
 	rc = input_register_device(input_dev);
 	if (rc) {
 		pr_err("%s: input_register_device() failed; rc=%d\n",
@@ -371,31 +415,41 @@
 	} else {
 		usf_info->input_if = input_dev;
 		usf_info->event_types = input_info->event_types;
-		pr_info("%s: input device[%s] was registered\n",
+		pr_debug("%s: input device[%s] was registered\n",
 			__func__, input_dev->name);
 	}
 
 	return rc;
-
 }
 
-static void notify_tsc_event(struct input_dev *input_if,
-			     int x, int y, int pressure)
+static void notify_tsc_event(struct usf_type *usf_info,
+			     struct point_event_type *pe)
 {
-	if (pressure) {
-		input_report_abs(input_if, ABS_X, x);
-		input_report_abs(input_if, ABS_Y, y);
-		input_report_abs(input_if, ABS_PRESSURE, pressure);
-		input_report_key(input_if, BTN_TOUCH, !!pressure);
-	} else {
-		input_report_abs(input_if, ABS_PRESSURE, 0);
-		input_report_key(input_if, BTN_TOUCH, 0);
-	}
+	struct input_dev *input_if = usf_info->input_if;
+
+	input_report_abs(input_if, ABS_X, pe->coordinates[X_IND]);
+	input_report_abs(input_if, ABS_Y, pe->coordinates[Y_IND]);
+	input_report_abs(input_if, ABS_DISTANCE, pe->coordinates[Z_IND]);
+
+	input_report_abs(input_if, ABS_TILT_X, pe->inclinations[X_IND]);
+	input_report_abs(input_if, ABS_TILT_Y, pe->inclinations[Y_IND]);
+
+	input_report_abs(input_if, ABS_PRESSURE, pe->pressure);
+	input_report_key(input_if, BTN_TOUCH, !!(pe->pressure));
+
+	if (usf_info->event_src)
+		input_report_key(input_if, usf_info->event_src, 1);
 
 	input_sync(input_if);
 
-	pr_debug("%s: TSC event: x[%d], y[%d], pressure[%d]\n",
-		 __func__, x, y, pressure);
+	pr_debug("%s: TSC event: xyz[%d;%d;%d], incl[%d;%d], pressure[%d]\n",
+		 __func__,
+		 pe->coordinates[X_IND],
+		 pe->coordinates[Y_IND],
+		 pe->coordinates[Z_IND],
+		 pe->inclinations[X_IND],
+		 pe->inclinations[Y_IND],
+		 pe->pressure);
 }
 
 static void notify_mouse_event(struct input_dev *input_if,
@@ -406,9 +460,9 @@
 		return;
 	}
 
-	input_report_rel(input_if, REL_X, me->rels[0]);
-	input_report_rel(input_if, REL_Y, me->rels[1]);
-	input_report_rel(input_if, REL_Z, me->rels[2]);
+	input_report_rel(input_if, REL_X, me->rels[X_IND]);
+	input_report_rel(input_if, REL_Y, me->rels[Y_IND]);
+	input_report_rel(input_if, REL_Z, me->rels[Z_IND]);
 
 	input_report_key(input_if, BTN_LEFT,
 			 me->buttons_states & USF_BUTTON_LEFT_MASK);
@@ -420,7 +474,8 @@
 	input_sync(input_if);
 
 	pr_debug("%s: mouse event: dx[%d], dy[%d], buttons_states[%d]\n",
-		 __func__, me->rels[0], me->rels[1], me->buttons_states);
+		 __func__, me->rels[X_IND],
+		 me->rels[Y_IND], me->buttons_states);
 }
 
 static void notify_key_event(struct input_dev *input_if,
@@ -480,10 +535,7 @@
 					&(p_event->event_data.point_event);
 				if (pe->coordinates_type ==
 					USF_PIX_COORDINATE)
-					notify_tsc_event(input_if,
-						pe->coordinates[0],
-						pe->coordinates[1],
-						pe->pressure);
+					notify_tsc_event(usf_info, pe);
 				else
 					pr_debug("%s: wrong coord type: %d",
 						__func__,
@@ -495,9 +547,9 @@
 					&(p_event->event_data.mouse_event));
 				continue;
 			}
-			if (event->event_type & USF_KEYBOARD_EVENT)
+			if (p_event->event_type & USF_KEYBOARD_EVENT)
 				notify_key_event(input_if,
-					&(event->event_data.key_event));
+					&(p_event->event_data.key_event));
 		} /* loop in the portion */
 	} /* all events loop */
 }
@@ -589,7 +641,8 @@
 			kfree(p_usm_detect_info);
 			return -EFAULT;
 		}
-		p_usm_detect_info->algorithm_cfg_size = detect_info_size;
+		p_usm_detect_info->algorithm_cfg_size =
+				detect_info.params_data_size;
 	} else
 		usm_detect_info.algorithm_cfg_size = 0;
 
@@ -917,7 +970,7 @@
 	if (usf->input_if != NULL) {
 		input_unregister_device(usf->input_if);
 		usf->input_if = NULL;
-		pr_info("%s input_unregister_device",
+		pr_debug("%s input_unregister_device",
 			__func__);
 	}
 	usf_disable(usf_xx);
@@ -925,6 +978,40 @@
 	return 0;
 } /* usf_stop_tx */
 
+static int usf_get_version(unsigned long arg)
+{
+	struct us_version_info_type version_info;
+	int rc = copy_from_user(&version_info, (void *) arg,
+				sizeof(version_info));
+
+	if (rc) {
+		pr_err("%s: copy version_info from user; rc=%d\n",
+			__func__, rc);
+		return -EFAULT;
+	}
+
+	/* version_info.buf is pointer to place for the version string */
+	rc = copy_to_user(version_info.pbuf,
+			  DRV_VERSION,
+			  version_info.buf_size);
+	if (rc) {
+		pr_err("%s: copy to version_info.pbuf; rc=%d\n",
+			__func__, rc);
+		rc = -EFAULT;
+	}
+
+	rc = copy_to_user((void __user *)arg,
+			  &version_info,
+			  sizeof(version_info));
+	if (rc) {
+		pr_err("%s: copy version_info to user; rc=%d\n",
+			__func__, rc);
+		rc = -EFAULT;
+	}
+
+	return rc;
+} /* usf_get_version */
+
 static long usf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	int rc = 0;
@@ -1048,10 +1135,18 @@
 			rc = -EBADFD;
 		}
 		break;
-	} /* US_GET_TX_UPDATE */
+	} /* US_SET_DETECTION */
+
+	case US_GET_VERSION: {
+		rc = usf_get_version(arg);
+		break;
+	} /* US_GET_VERSION */
 
 	default:
-		rc = -EINVAL;
+		pr_err("%s: unsupported IOCTL command [%d]\n",
+		       __func__,
+		       cmd);
+		rc = -ENOTTY;
 		break;
 	}
 
@@ -1090,7 +1185,7 @@
 
 		if (s_opened_devs[ind] == 0) {
 			s_opened_devs[ind] = minor;
-			pr_info("%s: device %d is added; ind=%d\n",
+			pr_debug("%s: device %d is added; ind=%d\n",
 				__func__, minor, ind);
 			return ind;
 		}
@@ -1126,7 +1221,7 @@
 	usf->usf_tx.us_detect_type = USF_US_DETECT_UNDEF;
 	usf->usf_rx.us_detect_type = USF_US_DETECT_UNDEF;
 
-	pr_info("%s:usf in open\n", __func__);
+	pr_debug("%s:usf in open\n", __func__);
 	return 0;
 }
 
@@ -1135,12 +1230,12 @@
 {
 	struct usf_type *usf = file->private_data;
 
-	pr_info("%s: release entry\n", __func__);
+	pr_debug("%s: release entry\n", __func__);
 
 	if (usf->input_if != NULL) {
 		input_unregister_device(usf->input_if);
 		usf->input_if = NULL;
-		pr_info("%s input_unregister_device\n",  __func__);
+		pr_debug("%s input_unregister_device\n",  __func__);
 	}
 
 	usf_disable(&usf->usf_tx);
@@ -1149,7 +1244,7 @@
 	s_opened_devs[usf->dev_ind] = 0;
 
 	kfree(usf);
-	pr_info("%s: release exit\n", __func__);
+	pr_debug("%s: release exit\n", __func__);
 	return 0;
 }
 
@@ -1174,8 +1269,8 @@
 	int rc = 0;
 	uint16_t ind = 0;
 
-	pr_info("%s: USF SW version %s.\n", __func__, DRV_VERSION);
-	pr_info("%s: Max %d devs registration\n", __func__, MAX_DEVS_NUMBER);
+	pr_debug("%s: USF SW version %s.\n", __func__, DRV_VERSION);
+	pr_debug("%s: Max %d devs registration\n", __func__, MAX_DEVS_NUMBER);
 
 	for (ind = 0; ind < MAX_DEVS_NUMBER; ++ind) {
 		rc = misc_register(&usf_misc[ind]);
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 0bc3b0e..10593c6 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -1135,8 +1135,10 @@
 		return 0;
 
 	while ((xfer = ch_write_buffer(ch, &ptr)) != 0) {
-		if (!ch_is_open(ch))
+		if (!ch_is_open(ch)) {
+			len = orig_len;
 			break;
+		}
 		if (xfer > len)
 			xfer = len;
 		if (user_buf) {
@@ -1505,9 +1507,6 @@
 
 	ch = smd_get_channel(name, edge);
 	if (!ch) {
-		unsigned long flags;
-		struct smd_channel *ch;
-
 		/* check closing list for port */
 		spin_lock_irqsave(&smd_lock, flags);
 		list_for_each_entry(ch, &smd_ch_closing_list, ch_list) {
@@ -2620,6 +2619,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},
 };
 
 static int restart_notifier_cb(struct notifier_block *this,
diff --git a/arch/arm/mach-msm/smem_log.c b/arch/arm/mach-msm/smem_log.c
index 6b7573c..bf598b7 100644
--- a/arch/arm/mach-msm/smem_log.c
+++ b/arch/arm/mach-msm/smem_log.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
@@ -133,6 +133,7 @@
 	{ SMEM_LOG_PROC_ID_MODEM, "MODM" },
 	{ SMEM_LOG_PROC_ID_Q6, "QDSP" },
 	{ SMEM_LOG_PROC_ID_APPS, "APPS" },
+	{ SMEM_LOG_PROC_ID_WCNSS, "WCNSS" },
 };
 
 struct sym base_syms[] = {
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 67b1f7b..3d44075 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -978,7 +978,7 @@
 
 	if (cpu_is_msm7x01() || cpu_is_msm7x25() || cpu_is_msm7x27() ||
 	    cpu_is_msm7x25a() || cpu_is_msm7x27a() || cpu_is_msm7x25aa() ||
-	    cpu_is_msm7x27aa()) {
+	    cpu_is_msm7x27aa() || cpu_is_msm8625()) {
 		dgt->shift = MSM_DGT_SHIFT;
 		dgt->freq = 19200000 >> MSM_DGT_SHIFT;
 		dgt->clockevent.shift = 32 + MSM_DGT_SHIFT;
@@ -989,6 +989,11 @@
 		gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT
 			   |  MSM_CLOCK_FLAGS_ODD_MATCH_WRITE
 			   |  MSM_CLOCK_FLAGS_DELAYED_WRITE_POST;
+		if (cpu_is_msm8625()) {
+			dgt->irq = MSM8625_INT_DEBUG_TIMER_EXP;
+			gpt->irq = MSM8625_INT_GP_TIMER_EXP;
+			global_timer_offset =  MSM_TMR0_BASE - MSM_TMR_BASE;
+		}
 	} else if (cpu_is_qsd8x50()) {
 		dgt->freq = 4800000;
 		gpt->regbase = MSM_TMR_BASE;
@@ -1069,7 +1074,8 @@
 
 		ce->irq = clock->irq;
 		if (cpu_is_msm8x60() || cpu_is_msm8960() || cpu_is_apq8064() ||
-				cpu_is_msm8930() || cpu_is_msm9615()) {
+				cpu_is_msm8930() || cpu_is_msm9615() ||
+				cpu_is_msm8625()) {
 			clock->percpu_evt = alloc_percpu(struct clock_event_device *);
 			if (!clock->percpu_evt) {
 				pr_err("msm_timer_init: memory allocation "
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index 93aac06..14536f6 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -14,6 +14,7 @@
 #include <linux/percpu.h>
 
 #include <asm/mmu_context.h>
+#include <asm/thread_notify.h>
 #include <asm/tlbflush.h>
 
 static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
@@ -22,6 +23,66 @@
 DEFINE_PER_CPU(struct mm_struct *, current_mm);
 #endif
 
+static void write_contextidr(u32 contextidr)
+{
+	asm("mcr	p15, 0, %0, c13, c0, 1" : : "r" (contextidr));
+	isb();
+}
+
+#ifdef CONFIG_PID_IN_CONTEXTIDR
+static u32 read_contextidr(void)
+{
+	u32 contextidr;
+	asm("mrc	p15, 0, %0, c13, c0, 1" : "=r" (contextidr));
+	return contextidr;
+}
+
+static int contextidr_notifier(struct notifier_block *unused, unsigned long cmd,
+			       void *t)
+{
+	unsigned long flags;
+	u32 contextidr;
+	pid_t pid;
+	struct thread_info *thread = t;
+
+	if (cmd != THREAD_NOTIFY_SWITCH)
+		return NOTIFY_DONE;
+
+	pid = task_pid_nr(thread->task);
+	local_irq_save(flags);
+	contextidr = read_contextidr();
+	contextidr &= ~ASID_MASK;
+	contextidr |= pid << ASID_BITS;
+	write_contextidr(contextidr);
+	local_irq_restore(flags);
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block contextidr_notifier_block = {
+	.notifier_call = contextidr_notifier,
+};
+
+static int __init contextidr_notifier_init(void)
+{
+	return thread_register_notifier(&contextidr_notifier_block);
+}
+arch_initcall(contextidr_notifier_init);
+
+static void set_asid(unsigned int asid)
+{
+	u32 contextidr = read_contextidr();
+	contextidr &= ASID_MASK;
+	contextidr |= asid & ~ASID_MASK;
+	write_contextidr(contextidr);
+}
+#else
+static void set_asid(unsigned int asid)
+{
+	write_contextidr(asid);
+}
+#endif
+
 /*
  * We fork()ed a process, and we need a new context for the child
  * to run in.  We reserve version 0 for initial tasks so we will
@@ -37,8 +98,7 @@
 static void flush_context(void)
 {
 	/* set the reserved ASID before flushing the TLB */
-	asm("mcr	p15, 0, %0, c13, c0, 1\n" : : "r" (0));
-	isb();
+	set_asid(0);
 	local_flush_tlb_all();
 	if (icache_is_vivt_asid_tagged()) {
 		__flush_icache_all();
@@ -99,8 +159,7 @@
 	set_mm_context(mm, asid);
 
 	/* set the new ASID */
-	asm("mcr	p15, 0, %0, c13, c0, 1\n" : : "r" (mm->context.id));
-	isb();
+	set_asid(mm->context.id);
 }
 
 #else
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 1d2b845..0fb3106 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -99,6 +99,12 @@
 	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
 	mcr	p15, 0, r2, c7, c10, 4		@ drain write buffer
 	mcr	p15, 0, r0, c2, c0, 0		@ set TTB 0
+#ifdef CONFIG_PID_IN_CONTEXTIDR
+	mrc	p15, 0, r2, c13, c0, 1		@ read current context ID
+	bic	r2, r2, #0xff			@ extract the PID
+	and	r1, r1, #0xff
+	orr	r1, r1, r2			@ insert the PID into r1
+#endif
 	mcr	p15, 0, r1, c13, c0, 1		@ set context ID
 #endif
 	mov	pc, lr
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 5943005..de65c4b 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -124,6 +124,12 @@
 #ifdef CONFIG_ARM_ERRATA_754322
 	dsb
 #endif
+#ifdef CONFIG_PID_IN_CONTEXTIDR
+	mrc	p15, 0, r2, c13, c0, 1		@ read current context ID
+	bic	r2, r2, #0xff			@ extract the PID
+	and	r1, r1, #0xff
+	orr	r1, r1, r2			@ insert the PID into r1
+#endif
 	mcr	p15, 0, r2, c13, c0, 1		@ set reserved context ID
 	isb
 1:	mcr	p15, 0, r0, c2, c0, 0		@ set TTB 0
diff --git a/drivers/bluetooth/hci_smd.c b/drivers/bluetooth/hci_smd.c
index dbd1bd4..332922e 100644
--- a/drivers/bluetooth/hci_smd.c
+++ b/drivers/bluetooth/hci_smd.c
@@ -25,6 +25,7 @@
 #include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/wakelock.h>
+#include <linux/workqueue.h>
 #include <linux/uaccess.h>
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
@@ -47,6 +48,7 @@
 static int hcismd_set_enable(const char *val, struct kernel_param *kp);
 module_param_call(hcismd_set, hcismd_set_enable, NULL, &hcismd_set, 0644);
 
+static void hci_dev_restart(struct work_struct *worker);
 
 struct hci_smd_data {
 	struct hci_dev *hdev;
@@ -312,6 +314,7 @@
 {
 	struct hci_dev *hdev = hs.hdev;
 	struct hci_smd_data *hsmd = &hs;
+	struct work_struct *reset_worker;
 	int len = 0;
 
 	if (!hdev) {
@@ -335,6 +338,13 @@
 	case SMD_EVENT_CLOSE:
 		BT_INFO("Closing HCI-SMD channel :%s", EVENT_CHANNEL);
 		hci_smd_close(hdev);
+		reset_worker = kzalloc(sizeof(*reset_worker), GFP_ATOMIC);
+		if (!reset_worker) {
+			BT_ERR("Out of memory");
+			break;
+		}
+		INIT_WORK(reset_worker, hci_dev_restart);
+		schedule_work(reset_worker);
 		break;
 	default:
 		break;
@@ -464,6 +474,15 @@
 	}
 }
 
+static void hci_dev_restart(struct work_struct *worker)
+{
+	mutex_lock(&hci_smd_enable);
+	hci_smd_deregister_dev(&hs);
+	hci_smd_register_dev(&hs);
+	mutex_unlock(&hci_smd_enable);
+	kfree(worker);
+}
+
 static int hcismd_set_enable(const char *val, struct kernel_param *kp)
 {
 	int ret = 0;
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 9c1473f..6aed95c 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -60,6 +60,9 @@
 #define MIN_LATENCY_MULTIPLIER			(100)
 #define TRANSITION_LATENCY_LIMIT		(10 * 1000 * 1000)
 
+#define POWERSAVE_BIAS_MAXLEVEL			(1000)
+#define POWERSAVE_BIAS_MINLEVEL			(-1000)
+
 static void do_dbs_timer(struct work_struct *work);
 static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 				unsigned int event);
@@ -100,6 +103,9 @@
 };
 static DEFINE_PER_CPU(struct cpu_dbs_info_s, od_cpu_dbs_info);
 
+static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info);
+static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info);
+
 static unsigned int dbs_enable;	/* number of CPUs using this policy */
 
 /*
@@ -117,7 +123,7 @@
 	unsigned int down_differential;
 	unsigned int ignore_nice;
 	unsigned int sampling_down_factor;
-	unsigned int powersave_bias;
+	int          powersave_bias;
 	unsigned int io_is_busy;
 } dbs_tuners_ins = {
 	.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
@@ -179,10 +185,11 @@
 					  unsigned int freq_next,
 					  unsigned int relation)
 {
-	unsigned int freq_req, freq_reduc, freq_avg;
+	unsigned int freq_req, freq_avg;
 	unsigned int freq_hi, freq_lo;
 	unsigned int index = 0;
 	unsigned int jiffies_total, jiffies_hi, jiffies_lo;
+	int freq_reduc;
 	struct cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
 						   policy->cpu);
 
@@ -225,6 +232,26 @@
 	return freq_hi;
 }
 
+static int ondemand_powersave_bias_setspeed(struct cpufreq_policy *policy,
+					    struct cpufreq_policy *altpolicy,
+					    int level)
+{
+	if (level == POWERSAVE_BIAS_MAXLEVEL) {
+		/* maximum powersave; set to lowest frequency */
+		__cpufreq_driver_target(policy,
+			(altpolicy) ? altpolicy->min : policy->min,
+			CPUFREQ_RELATION_L);
+		return 1;
+	} else if (level == POWERSAVE_BIAS_MINLEVEL) {
+		/* minimum powersave; set to highest frequency */
+		__cpufreq_driver_target(policy,
+			(altpolicy) ? altpolicy->max : policy->max,
+			CPUFREQ_RELATION_H);
+		return 1;
+	}
+	return 0;
+}
+
 static void ondemand_powersave_bias_init_cpu(int cpu)
 {
 	struct cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
@@ -263,7 +290,12 @@
 show_one(down_differential, down_differential);
 show_one(sampling_down_factor, sampling_down_factor);
 show_one(ignore_nice_load, ignore_nice);
-show_one(powersave_bias, powersave_bias);
+
+static ssize_t show_powersave_bias
+(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", dbs_tuners_ins.powersave_bias);
+}
 
 static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
 				   const char *buf, size_t count)
@@ -378,18 +410,75 @@
 static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b,
 				    const char *buf, size_t count)
 {
-	unsigned int input;
-	int ret;
-	ret = sscanf(buf, "%u", &input);
+	int input  = 0;
+	int bypass = 0;
+	int ret, cpu, reenable_timer;
+	struct cpu_dbs_info_s *dbs_info;
+
+	ret = sscanf(buf, "%d", &input);
 
 	if (ret != 1)
 		return -EINVAL;
 
-	if (input > 1000)
-		input = 1000;
+	if (input >= POWERSAVE_BIAS_MAXLEVEL) {
+		input  = POWERSAVE_BIAS_MAXLEVEL;
+		bypass = 1;
+	} else if (input <= POWERSAVE_BIAS_MINLEVEL) {
+		input  = POWERSAVE_BIAS_MINLEVEL;
+		bypass = 1;
+	}
+
+	if (input == dbs_tuners_ins.powersave_bias) {
+		/* no change */
+		return count;
+	}
+
+	reenable_timer = ((dbs_tuners_ins.powersave_bias ==
+				POWERSAVE_BIAS_MAXLEVEL) ||
+				(dbs_tuners_ins.powersave_bias ==
+				POWERSAVE_BIAS_MINLEVEL));
 
 	dbs_tuners_ins.powersave_bias = input;
-	ondemand_powersave_bias_init();
+	if (!bypass) {
+		if (reenable_timer) {
+			/* reinstate dbs timer */
+			for_each_online_cpu(cpu) {
+				if (lock_policy_rwsem_write(cpu) < 0)
+					continue;
+
+				dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
+				if (dbs_info->cur_policy) {
+					/* restart dbs timer */
+					dbs_timer_init(dbs_info);
+				}
+				unlock_policy_rwsem_write(cpu);
+			}
+		}
+		ondemand_powersave_bias_init();
+	} else {
+		/* running at maximum or minimum frequencies; cancel
+		   dbs timer as periodic load sampling is not necessary */
+		for_each_online_cpu(cpu) {
+			if (lock_policy_rwsem_write(cpu) < 0)
+				continue;
+
+			dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
+			if (dbs_info->cur_policy) {
+				/* cpu using ondemand, cancel dbs timer */
+				mutex_lock(&dbs_info->timer_mutex);
+				dbs_timer_exit(dbs_info);
+
+				ondemand_powersave_bias_setspeed(
+					dbs_info->cur_policy,
+					NULL,
+					input);
+
+				mutex_unlock(&dbs_info->timer_mutex);
+			}
+			unlock_policy_rwsem_write(cpu);
+		}
+	}
+
 	return count;
 }
 
@@ -680,6 +769,12 @@
 {
 	int i;
 
+	if ((dbs_tuners_ins.powersave_bias == POWERSAVE_BIAS_MAXLEVEL) ||
+		(dbs_tuners_ins.powersave_bias == POWERSAVE_BIAS_MINLEVEL)) {
+		/* nothing to do */
+		return;
+	}
+
 	for_each_online_cpu(i) {
 		queue_work_on(i, input_wq, &per_cpu(dbs_refresh_work, i));
 	}
@@ -799,7 +894,12 @@
 		mutex_unlock(&dbs_mutex);
 
 		mutex_init(&this_dbs_info->timer_mutex);
-		dbs_timer_init(this_dbs_info);
+
+		if (!ondemand_powersave_bias_setspeed(
+					this_dbs_info->cur_policy,
+					NULL,
+					dbs_tuners_ins.powersave_bias))
+			dbs_timer_init(this_dbs_info);
 		break;
 
 	case CPUFREQ_GOV_STOP:
@@ -828,6 +928,11 @@
 		else if (policy->min > this_dbs_info->cur_policy->cur)
 			__cpufreq_driver_target(this_dbs_info->cur_policy,
 				policy->min, CPUFREQ_RELATION_L);
+		else if (dbs_tuners_ins.powersave_bias != 0)
+			ondemand_powersave_bias_setspeed(
+				this_dbs_info->cur_policy,
+				policy,
+				dbs_tuners_ins.powersave_bias);
 		mutex_unlock(&this_dbs_info->timer_mutex);
 		break;
 	}
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index 16ace6f..fc1cfb6 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -26,6 +26,7 @@
 #include <linux/vmalloc.h>
 #include <linux/memory_alloc.h>
 #include <linux/seq_file.h>
+#include <linux/fmem.h>
 #include <mach/msm_memtypes.h>
 #include <mach/scm.h>
 #include "ion_priv.h"
@@ -43,7 +44,7 @@
  * @secure_base:	Base address used when securing a heap that is shared.
  * @secure_size:	Size used when securing a heap that is shared.
  * @lock:	mutex to protect shared access.
- * @heap_secured:	Identifies the heap_id as secure or not.
+ * @heap_protected:	Indicates whether heap has been protected or not.
  * @allocated_bytes:	the total number of allocated bytes from the pool.
  * @total_size:	the total size of the memory pool.
  * @request_region:	function pointer to call when first mapping of memory
@@ -51,11 +52,14 @@
  * @release_region:	function pointer to call when last mapping of memory
  *			unmapped.
  * @bus_id: token used with request/release region.
- * @kmap_count:	the total number of times this heap has been mapped in
- *		kernel space.
+ * @kmap_cached_count:	the total number of times this heap has been mapped in
+ *			kernel space (cached).
+ * @kmap_uncached_count:the total number of times this heap has been mapped in
+ *			kernel space (un-cached).
  * @umap_count:	the total number of times this heap has been mapped in
  *		user space.
- * @alloc_count:the total number of times this heap has been allocated
+ * @reusable: indicates if the memory should be reused via fmem.
+ * @reserved_vrange: reserved virtual address range for use with fmem
  */
 struct ion_cp_heap {
 	struct ion_heap heap;
@@ -65,20 +69,22 @@
 	ion_phys_addr_t secure_base;
 	size_t secure_size;
 	struct mutex lock;
-	unsigned int heap_secured;
+	unsigned int heap_protected;
 	unsigned long allocated_bytes;
 	unsigned long total_size;
 	int (*request_region)(void *);
 	int (*release_region)(void *);
 	void *bus_id;
-	unsigned long kmap_count;
+	unsigned long kmap_cached_count;
+	unsigned long kmap_uncached_count;
 	unsigned long umap_count;
-	unsigned long alloc_count;
+	int reusable;
+	void *reserved_vrange;
 };
 
 enum {
-	NON_SECURED_HEAP = 0,
-	SECURED_HEAP = 1,
+	HEAP_NOT_PROTECTED = 0,
+	HEAP_PROTECTED = 1,
 };
 
 static int ion_cp_protect_mem(unsigned int phy_base, unsigned int size,
@@ -87,9 +93,19 @@
 static int ion_cp_unprotect_mem(unsigned int phy_base, unsigned int size,
 				unsigned int permission_type);
 
+/**
+ * Get the total number of kernel mappings.
+ * Must be called with heap->lock locked.
+ */
+static unsigned long ion_cp_get_total_kmap_count(
+					const struct ion_cp_heap *cp_heap)
+{
+	return cp_heap->kmap_cached_count + cp_heap->kmap_uncached_count;
+}
 
 /**
- * Protects memory if heap is unsecured heap.
+ * Protects memory if heap is unsecured heap. Also ensures that we are in
+ * the correct FMEM state if this heap is a reusable heap.
  * Must be called with heap->lock locked.
  */
 static int ion_cp_protect(struct ion_heap *heap)
@@ -98,23 +114,38 @@
 		container_of(heap, struct ion_cp_heap, heap);
 	int ret_value = 0;
 
-	if (cp_heap->heap_secured == NON_SECURED_HEAP) {
-		int ret_value = ion_cp_protect_mem(cp_heap->secure_base,
+	if (cp_heap->heap_protected == HEAP_NOT_PROTECTED) {
+		/* Make sure we are in C state when the heap is protected. */
+		if (cp_heap->reusable && !cp_heap->allocated_bytes) {
+			ret_value = fmem_set_state(FMEM_C_STATE);
+			if (ret_value)
+				goto out;
+		}
+
+		ret_value = ion_cp_protect_mem(cp_heap->secure_base,
 				cp_heap->secure_size, cp_heap->permission_type);
 		if (ret_value) {
 			pr_err("Failed to protect memory for heap %s - "
 				"error code: %d\n", heap->name, ret_value);
+
+			if (cp_heap->reusable && !cp_heap->allocated_bytes) {
+				if (fmem_set_state(FMEM_T_STATE) != 0)
+					pr_err("%s: unable to transition heap to T-state\n",
+						__func__);
+			}
 		} else {
-			cp_heap->heap_secured = SECURED_HEAP;
-			pr_debug("Protected heap %s @ 0x%x\n",
-				heap->name, (unsigned int) cp_heap->base);
+			cp_heap->heap_protected = HEAP_PROTECTED;
+			pr_debug("Protected heap %s @ 0x%lx\n",
+				heap->name, cp_heap->base);
 		}
 	}
+out:
 	return ret_value;
 }
 
 /**
- * Unprotects memory if heap is secure heap.
+ * Unprotects memory if heap is secure heap. Also ensures that we are in
+ * the correct FMEM state if this heap is a reusable heap.
  * Must be called with heap->lock locked.
  */
 static void ion_cp_unprotect(struct ion_heap *heap)
@@ -122,7 +153,7 @@
 	struct ion_cp_heap *cp_heap =
 		container_of(heap, struct ion_cp_heap, heap);
 
-	if (cp_heap->heap_secured == SECURED_HEAP) {
+	if (cp_heap->heap_protected == HEAP_PROTECTED) {
 		int error_code = ion_cp_unprotect_mem(
 			cp_heap->secure_base, cp_heap->secure_size,
 			cp_heap->permission_type);
@@ -130,9 +161,15 @@
 			pr_err("Failed to un-protect memory for heap %s - "
 				"error code: %d\n", heap->name, error_code);
 		} else  {
-			cp_heap->heap_secured = NON_SECURED_HEAP;
+			cp_heap->heap_protected = HEAP_NOT_PROTECTED;
 			pr_debug("Un-protected heap %s @ 0x%x\n", heap->name,
 				(unsigned int) cp_heap->base);
+
+			if (cp_heap->reusable && !cp_heap->allocated_bytes) {
+				if (fmem_set_state(FMEM_T_STATE) != 0)
+					pr_err("%s: unable to transition heap to T-state",
+						__func__);
+			}
 		}
 	}
 }
@@ -149,29 +186,35 @@
 		container_of(heap, struct ion_cp_heap, heap);
 
 	mutex_lock(&cp_heap->lock);
-
-	if (!secure_allocation && cp_heap->heap_secured == SECURED_HEAP) {
+	if (!secure_allocation && cp_heap->heap_protected == HEAP_PROTECTED) {
 		mutex_unlock(&cp_heap->lock);
 		pr_err("ION cannot allocate un-secure memory from protected"
 			" heap %s\n", heap->name);
 		return ION_CP_ALLOCATE_FAIL;
 	}
 
-	if (secure_allocation && cp_heap->umap_count > 0) {
+	if (secure_allocation &&
+	    (cp_heap->umap_count > 0 || cp_heap->kmap_cached_count > 0)) {
 		mutex_unlock(&cp_heap->lock);
 		pr_err("ION cannot allocate secure memory from heap with "
-			"outstanding user space mappings for heap %s\n",
-			heap->name);
+			"outstanding mappings: User space: %lu, kernel space "
+			"(cached): %lu\n", cp_heap->umap_count,
+					   cp_heap->kmap_cached_count);
 		return ION_CP_ALLOCATE_FAIL;
 	}
 
-	if (secure_allocation && ion_cp_protect(heap)) {
-		mutex_unlock(&cp_heap->lock);
-		return ION_CP_ALLOCATE_FAIL;
+	/*
+	 * if this is the first reusable allocation, transition
+	 * the heap
+	 */
+	if (cp_heap->reusable && !cp_heap->allocated_bytes) {
+		if (fmem_set_state(FMEM_C_STATE) != 0) {
+			mutex_unlock(&cp_heap->lock);
+			return ION_RESERVED_ALLOCATE_FAIL;
+		}
 	}
 
 	cp_heap->allocated_bytes += size;
-	++cp_heap->alloc_count;
 	mutex_unlock(&cp_heap->lock);
 
 	offset = gen_pool_alloc_aligned(cp_heap->pool,
@@ -189,11 +232,12 @@
 				cp_heap->allocated_bytes, size);
 
 		cp_heap->allocated_bytes -= size;
-		--cp_heap->alloc_count;
 
-		if (cp_heap->alloc_count == 0)
-			ion_cp_unprotect(heap);
-
+		if (cp_heap->reusable && !cp_heap->allocated_bytes) {
+			if (fmem_set_state(FMEM_T_STATE) != 0)
+				pr_err("%s: unable to transition heap to T-state\n",
+					__func__);
+		}
 		mutex_unlock(&cp_heap->lock);
 
 		return ION_CP_ALLOCATE_FAIL;
@@ -213,12 +257,13 @@
 	gen_pool_free(cp_heap->pool, addr, size);
 
 	mutex_lock(&cp_heap->lock);
-
 	cp_heap->allocated_bytes -= size;
-	--cp_heap->alloc_count;
 
-	if (cp_heap->alloc_count == 0)
-		ion_cp_unprotect(heap);
+	if (cp_heap->reusable && !cp_heap->allocated_bytes) {
+		if (fmem_set_state(FMEM_T_STATE) != 0)
+			pr_err("%s: unable to transition heap to T-state\n",
+				__func__);
+	}
 	mutex_unlock(&cp_heap->lock);
 }
 
@@ -248,30 +293,6 @@
 	buffer->priv_phys = ION_CP_ALLOCATE_FAIL;
 }
 
-
-/**
- * Checks if user space mapping is allowed.
- * NOTE: Will increment the mapping count if
- * mapping is allowed.
- * Will fail mapping if heap is secured.
- */
-static unsigned int is_user_mapping_allowed(struct ion_heap *heap)
-{
-	struct ion_cp_heap *cp_heap =
-		container_of(heap, struct ion_cp_heap, heap);
-
-	mutex_lock(&cp_heap->lock);
-
-	if (cp_heap->heap_secured == SECURED_HEAP) {
-		mutex_unlock(&cp_heap->lock);
-		return 0;
-	}
-	++cp_heap->umap_count;
-
-	mutex_unlock(&cp_heap->lock);
-	return 1;
-}
-
 struct scatterlist *ion_cp_heap_map_dma(struct ion_heap *heap,
 					      struct ion_buffer *buffer)
 {
@@ -304,7 +325,7 @@
 static int ion_cp_request_region(struct ion_cp_heap *cp_heap)
 {
 	int ret_value = 0;
-	if ((cp_heap->umap_count+cp_heap->kmap_count) == 1)
+	if ((cp_heap->umap_count + ion_cp_get_total_kmap_count(cp_heap)) == 0)
 		if (cp_heap->request_region)
 			ret_value = cp_heap->request_region(cp_heap->bus_id);
 	return ret_value;
@@ -316,48 +337,76 @@
 static int ion_cp_release_region(struct ion_cp_heap *cp_heap)
 {
 	int ret_value = 0;
-	if ((cp_heap->umap_count + cp_heap->kmap_count) == 0)
+	if ((cp_heap->umap_count + ion_cp_get_total_kmap_count(cp_heap)) == 0)
 		if (cp_heap->release_region)
 			ret_value = cp_heap->release_region(cp_heap->bus_id);
 	return ret_value;
 }
 
+void *ion_map_fmem_buffer(struct ion_buffer *buffer, unsigned long phys_base,
+				void *virt_base, unsigned long flags)
+{
+	int ret;
+	unsigned int offset = buffer->priv_phys - phys_base;
+	unsigned long start = ((unsigned long)virt_base) + offset;
+	const struct mem_type *type = ION_IS_CACHED(flags) ?
+				get_mem_type(MT_DEVICE_CACHED) :
+				get_mem_type(MT_DEVICE);
+
+	if (phys_base > buffer->priv_phys)
+		return NULL;
+
+
+	ret = ioremap_page_range(start, start + buffer->size,
+			buffer->priv_phys, __pgprot(type->prot_pte));
+
+	if (!ret)
+		return (void *)start;
+	else
+		return NULL;
+}
+
 void *ion_cp_heap_map_kernel(struct ion_heap *heap,
 				   struct ion_buffer *buffer,
 				   unsigned long flags)
 {
 	struct ion_cp_heap *cp_heap =
 		container_of(heap, struct ion_cp_heap, heap);
-	void *ret_value;
+	void *ret_value = NULL;
 
 	mutex_lock(&cp_heap->lock);
+	if ((cp_heap->heap_protected == HEAP_NOT_PROTECTED) ||
+	    ((cp_heap->heap_protected == HEAP_PROTECTED) &&
+	      !ION_IS_CACHED(flags))) {
 
-	if (cp_heap->heap_secured == SECURED_HEAP && ION_IS_CACHED(flags)) {
-		pr_err("Unable to map secured heap %s as cached\n", heap->name);
-		mutex_unlock(&cp_heap->lock);
-		return NULL;
-	}
+		if (ion_cp_request_region(cp_heap)) {
+			mutex_unlock(&cp_heap->lock);
+			return NULL;
+		}
 
-	++cp_heap->kmap_count;
+		if (cp_heap->reusable) {
+			ret_value = ion_map_fmem_buffer(buffer, cp_heap->base,
+					cp_heap->reserved_vrange, flags);
 
-	if (ion_cp_request_region(cp_heap)) {
-		--cp_heap->kmap_count;
-		mutex_unlock(&cp_heap->lock);
-		return NULL;
+		} else {
+			if (ION_IS_CACHED(flags))
+				ret_value = ioremap_cached(buffer->priv_phys,
+							   buffer->size);
+			else
+				ret_value = ioremap(buffer->priv_phys,
+						    buffer->size);
+		}
+
+		if (!ret_value) {
+			ion_cp_release_region(cp_heap);
+		} else {
+			if (ION_IS_CACHED(buffer->flags))
+				++cp_heap->kmap_cached_count;
+			else
+				++cp_heap->kmap_uncached_count;
+		}
 	}
 	mutex_unlock(&cp_heap->lock);
-
-	if (ION_IS_CACHED(flags))
-		ret_value = ioremap_cached(buffer->priv_phys, buffer->size);
-	else
-		ret_value = ioremap(buffer->priv_phys, buffer->size);
-
-	if (!ret_value) {
-		mutex_lock(&cp_heap->lock);
-		--cp_heap->kmap_count;
-		ion_cp_release_region(cp_heap);
-		mutex_unlock(&cp_heap->lock);
-	}
 	return ret_value;
 }
 
@@ -367,11 +416,18 @@
 	struct ion_cp_heap *cp_heap =
 		container_of(heap, struct ion_cp_heap, heap);
 
-	__arch_iounmap(buffer->vaddr);
+	if (cp_heap->reusable)
+		unmap_kernel_range((unsigned long)buffer->vaddr, buffer->size);
+	else
+		__arch_iounmap(buffer->vaddr);
+
 	buffer->vaddr = NULL;
 
 	mutex_lock(&cp_heap->lock);
-	--cp_heap->kmap_count;
+	if (ION_IS_CACHED(buffer->flags))
+		--cp_heap->kmap_cached_count;
+	else
+		--cp_heap->kmap_uncached_count;
 	ion_cp_release_region(cp_heap);
 	mutex_unlock(&cp_heap->lock);
 
@@ -382,17 +438,15 @@
 			struct vm_area_struct *vma, unsigned long flags)
 {
 	int ret_value = -EAGAIN;
-	if (is_user_mapping_allowed(heap)) {
+	struct ion_cp_heap *cp_heap =
+		container_of(heap, struct ion_cp_heap, heap);
 
-		struct ion_cp_heap *cp_heap =
-			container_of(heap, struct ion_cp_heap, heap);
-
-		mutex_lock(&cp_heap->lock);
+	mutex_lock(&cp_heap->lock);
+	if (cp_heap->heap_protected == HEAP_NOT_PROTECTED) {
 		if (ion_cp_request_region(cp_heap)) {
 			mutex_unlock(&cp_heap->lock);
 			return -EINVAL;
 		}
-		mutex_unlock(&cp_heap->lock);
 
 		 if (ION_IS_CACHED(flags))
 			ret_value =  remap_pfn_range(vma, vma->vm_start,
@@ -407,13 +461,12 @@
 				vma->vm_end - vma->vm_start,
 				pgprot_noncached(vma->vm_page_prot));
 
-		 if (ret_value) {
-			mutex_lock(&cp_heap->lock);
-			--cp_heap->umap_count;
+		if (ret_value)
 			ion_cp_release_region(cp_heap);
-			mutex_unlock(&cp_heap->lock);
-		}
+		else
+			++cp_heap->umap_count;
 	}
+	mutex_unlock(&cp_heap->lock);
 	return ret_value;
 }
 
@@ -459,28 +512,26 @@
 {
 	unsigned long total_alloc;
 	unsigned long total_size;
-	unsigned long alloc_count;
 	unsigned long umap_count;
 	unsigned long kmap_count;
-	unsigned long heap_secured;
+	unsigned long heap_protected;
 	struct ion_cp_heap *cp_heap =
 		container_of(heap, struct ion_cp_heap, heap);
 
 	mutex_lock(&cp_heap->lock);
 	total_alloc = cp_heap->allocated_bytes;
 	total_size = cp_heap->total_size;
-	alloc_count = cp_heap->alloc_count;
 	umap_count = cp_heap->umap_count;
-	kmap_count = cp_heap->kmap_count;
-	heap_secured = cp_heap->heap_secured == SECURED_HEAP;
+	kmap_count = ion_cp_get_total_kmap_count(cp_heap);
+	heap_protected = cp_heap->heap_protected == HEAP_PROTECTED;
 	mutex_unlock(&cp_heap->lock);
 
 	seq_printf(s, "total bytes currently allocated: %lx\n", total_alloc);
 	seq_printf(s, "total heap size: %lx\n", total_size);
-	seq_printf(s, "allocation count: %lx\n", alloc_count);
 	seq_printf(s, "umapping count: %lx\n", umap_count);
 	seq_printf(s, "kmapping count: %lx\n", kmap_count);
-	seq_printf(s, "secured heap: %s\n", heap_secured ? "Yes" : "No");
+	seq_printf(s, "heap protected: %s\n", heap_protected ? "Yes" : "No");
+	seq_printf(s, "reusable: %s\n", cp_heap->reusable  ? "Yes" : "No");
 
 	return 0;
 }
@@ -491,7 +542,15 @@
 	struct ion_cp_heap *cp_heap =
 		container_of(heap, struct ion_cp_heap, heap);
 	mutex_lock(&cp_heap->lock);
-	ret_value = ion_cp_protect(heap);
+	if (cp_heap->umap_count == 0 && cp_heap->kmap_cached_count == 0) {
+		ret_value = ion_cp_protect(heap);
+	} else {
+		pr_err("ION cannot secure heap with outstanding mappings: "
+		       "User space: %lu, kernel space (cached): %lu\n",
+		       cp_heap->umap_count, cp_heap->kmap_cached_count);
+		ret_value = -EINVAL;
+	}
+
 	mutex_unlock(&cp_heap->lock);
 	return ret_value;
 }
@@ -545,18 +604,20 @@
 		goto destroy_pool;
 
 	cp_heap->allocated_bytes = 0;
-	cp_heap->alloc_count = 0;
 	cp_heap->umap_count = 0;
-	cp_heap->kmap_count = 0;
+	cp_heap->kmap_cached_count = 0;
+	cp_heap->kmap_uncached_count = 0;
 	cp_heap->total_size = heap_data->size;
 	cp_heap->heap.ops = &cp_heap_ops;
 	cp_heap->heap.type = ION_HEAP_TYPE_CP;
-	cp_heap->heap_secured = NON_SECURED_HEAP;
+	cp_heap->heap_protected = HEAP_NOT_PROTECTED;
 	cp_heap->secure_base = cp_heap->base;
 	cp_heap->secure_size = heap_data->size;
 	if (heap_data->extra_data) {
 		struct ion_cp_heap_pdata *extra_data =
 				heap_data->extra_data;
+		cp_heap->reusable = extra_data->reusable;
+		cp_heap->reserved_vrange = extra_data->virt_addr;
 		cp_heap->permission_type = extra_data->permission_type;
 		if (extra_data->secure_size) {
 			cp_heap->secure_base = extra_data->secure_base;
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index 78dfe6e..1d40aef 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -230,6 +230,9 @@
 struct ion_heap *ion_cp_heap_create(struct ion_platform_heap *);
 void ion_cp_heap_destroy(struct ion_heap *);
 
+struct ion_heap *ion_reusable_heap_create(struct ion_platform_heap *);
+void ion_reusable_heap_destroy(struct ion_heap *);
+
 /**
  * kernel api to allocate/free from carveout -- used when carveout is
  * used to back an architecture specific custom heap
@@ -248,4 +251,24 @@
 #define ION_CARVEOUT_ALLOCATE_FAIL -1
 #define ION_CP_ALLOCATE_FAIL -1
 
+/**
+ * The reserved heap returns physical addresses, since 0 may be a valid
+ * physical address, this is used to indicate allocation failed
+ */
+#define ION_RESERVED_ALLOCATE_FAIL -1
+
+/**
+ * ion_map_fmem_buffer - map fmem allocated memory into the kernel
+ * @buffer - buffer to map
+ * @phys_base - physical base of the heap
+ * @virt_base - virtual base of the heap
+ * @flags - flags for the heap
+ *
+ * Map fmem allocated memory into the kernel address space. This
+ * is designed to be used by other heaps that need fmem behavior.
+ * The virtual range must be pre-allocated.
+ */
+void *ion_map_fmem_buffer(struct ion_buffer *buffer, unsigned long phys_base,
+				void *virt_base, unsigned long flags);
+
 #endif /* _ION_PRIV_H */
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index f71f514..2a2892e 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/memory_alloc.h>
+#include <linux/fmem.h>
 #include <mach/ion.h>
 #include <mach/msm_memtypes.h>
 #include "../ion_priv.h"
@@ -86,10 +87,20 @@
 		if (shared_heap) {
 			struct ion_cp_heap_pdata *cp_data =
 			   (struct ion_cp_heap_pdata *) shared_heap->extra_data;
-			heap->base = msm_ion_get_base(
-				heap->size + shared_heap->size,
-				shared_heap->memory_type,
-				co_heap_data->align);
+			if (cp_data->reusable) {
+				const struct fmem_data *fmem_info =
+					fmem_get_info();
+				heap->base = fmem_info->phys -
+					     fmem_info->reserved_size;
+				cp_data->virt_addr = fmem_info->virt;
+				pr_info("ION heap %s using FMEM\n",
+							shared_heap->name);
+			} else {
+				heap->base = msm_ion_get_base(
+					heap->size + shared_heap->size,
+					shared_heap->memory_type,
+					co_heap_data->align);
+			}
 			if (heap->base) {
 				shared_heap->base = heap->base + heap->size;
 				cp_data->secure_base = heap->base;
@@ -138,13 +149,24 @@
 			((struct ion_co_heap_pdata *) heap->extra_data)->align;
 			break;
 		case ION_HEAP_TYPE_CP:
-			align =
-			((struct ion_cp_heap_pdata *) heap->extra_data)->align;
+		{
+			struct ion_cp_heap_pdata *data =
+				(struct ion_cp_heap_pdata *)
+				heap->extra_data;
+			if (data->reusable) {
+				const struct fmem_data *fmem_info =
+					fmem_get_info();
+				heap->base = fmem_info->phys;
+				data->virt_addr = fmem_info->virt;
+				pr_info("ION heap %s using FMEM\n", heap->name);
+			}
+			align = data->align;
 			break;
+		}
 		default:
 			break;
 		}
-		if (align) {
+		if (align && !heap->base) {
 			heap->base = msm_ion_get_base(heap->size,
 						      heap->memory_type,
 						      align);
diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile
index 7b8f3e6..5189388 100644
--- a/drivers/gpu/msm/Makefile
+++ b/drivers/gpu/msm/Makefile
@@ -25,6 +25,8 @@
 	adreno_a2xx.o \
 	adreno_a2xx_trace.o \
 	adreno_a2xx_snapshot.o \
+	adreno_a3xx.o \
+	adreno_a3xx_snapshot.o \
 	adreno.o
 
 msm_adreno-$(CONFIG_DEBUG_FS) += adreno_debugfs.o
diff --git a/drivers/gpu/msm/a2xx_reg.h b/drivers/gpu/msm/a2xx_reg.h
index 50b2745..4c0bd19 100644
--- a/drivers/gpu/msm/a2xx_reg.h
+++ b/drivers/gpu/msm/a2xx_reg.h
@@ -278,6 +278,7 @@
 #define REG_CP_ME_CNTL                   0x01F6
 #define REG_CP_ME_RAM_DATA               0x01FA
 #define REG_CP_ME_RAM_WADDR              0x01F8
+#define REG_CP_ME_RAM_RADDR              0x01F9
 #define REG_CP_ME_STATUS                 0x01F7
 #define REG_CP_PFP_UCODE_ADDR            0x00C0
 #define REG_CP_PFP_UCODE_DATA            0x00C1
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
new file mode 100644
index 0000000..1806886
--- /dev/null
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -0,0 +1,491 @@
+/* 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 _A300_REG_H
+#define _A300_REG_H
+
+/* Interrupt bit positions within RBBM_INT_0 */
+
+#define A3XX_INT_RBBM_GPU_IDLE 0
+#define A3XX_INT_RBBM_AHB_ERROR 1
+#define A3XX_INT_RBBM_REG_TIMEOUT 2
+#define A3XX_INT_RBBM_ME_MS_TIMEOUT 3
+#define A3XX_INT_RBBM_PFP_MS_TIMEOUT 4
+#define A3XX_INT_RBBM_ATB_BUS_OVERFLOW 5
+#define A3XX_INT_VFD_ERROR 6
+#define A3XX_INT_CP_SW_INT 7
+#define A3XX_INT_CP_T0_PACKET_IN_IB 8
+#define A3XX_INT_CP_OPCODE_ERROR 9
+#define A3XX_INT_CP_RESERVED_BIT_ERROR 10
+#define A3XX_INT_CP_HW_FAULT 11
+#define A3xx_INT_CP_DMA 12
+#define A3XX_INT_CP_IB2_INT 13
+#define A3XX_INT_CP_IB1_INT 14
+#define A3XX_INT_CP_RB_INT 15
+#define A3XX_INT_CP_REG_PROTECT_FAULT 16
+#define A3XX_INT_CP_RB_DONE_TS 17
+#define A3XX_INT_CP_VS_DONE_TS 18
+#define A3XX_INT_CP_PS_DONE_TS 19
+#define A3XX_INT_CACHE_FLUSH_TS 20
+#define A3XX_INT_CP_AHB_ERROR_HALT 21
+#define A3XX_INT_MISC_HANG_DETECT 24
+#define A3XX_INT_UCHE_OOB_ACCESS 25
+
+/* Register definitions */
+
+#define A3XX_RBBM_HW_VERSION 0x000
+#define A3XX_RBBM_HW_RELEASE 0x001
+#define A3XX_RBBM_HW_CONFIGURATION 0x002
+#define A3XX_RBBM_SW_RESET_CMD 0x018
+#define A3XX_RBBM_AHB_CTL0 0x020
+#define A3XX_RBBM_AHB_CTL1 0x021
+#define A3XX_RBBM_AHB_CMD 0x022
+#define A3XX_RBBM_AHB_ERROR_STATUS 0x027
+#define A3XX_RBBM_GPR0_CTL 0x02E
+/* This the same register as on A2XX, just in a different place */
+#define A3XX_RBBM_STATUS 0x030
+#define A3XX_RBBM_INTERFACE_HANG_INT_CTL 0x50
+#define A3XX_RBBM_INTERFACE_HANG_MASK_CTL0 0x51
+#define A3XX_RBBM_INTERFACE_HANG_MASK_CTL1 0x54
+#define A3XX_RBBM_INTERFACE_HANG_MASK_CTL2 0x57
+#define A3XX_RBBM_INTERFACE_HANG_MASK_CTL3 0x5A
+#define A3XX_RBBM_INT_CLEAR_CMD 0x061
+#define A3XX_RBBM_INT_0_MASK 0x063
+#define A3XX_RBBM_INT_0_STATUS 0x064
+#define A3XX_RBBM_GPU_BUSY_MASKED 0x88
+#define A3XX_RBBM_RBBM_CTL 0x100
+#define A3XX_RBBM_RBBM_CTL 0x100
+#define A3XX_RBBM_PERFCTR_PWR_1_LO 0x0EC
+#define A3XX_RBBM_PERFCTR_PWR_1_HI 0x0ED
+#define A3XX_RBBM_DEBUG_BUS_CTL             0x111
+#define A3XX_RBBM_DEBUG_BUS_DATA_STATUS     0x112
+/* Following two are same as on A2XX, just in a different place */
+#define A3XX_CP_PFP_UCODE_ADDR 0x1C9
+#define A3XX_CP_PFP_UCODE_DATA 0x1CA
+#define A3XX_CP_ROQ_ADDR 0x1CC
+#define A3XX_CP_ROQ_DATA 0x1CD
+#define A3XX_CP_MEQ_ADDR 0x1DA
+#define A3XX_CP_MEQ_DATA 0x1DB
+#define A3XX_CP_HW_FAULT  0x45C
+#define A3XX_CP_AHB_FAULT 0x54D
+#define A3XX_CP_PROTECT_CTRL 0x45E
+#define A3XX_CP_PROTECT_STATUS 0x45F
+#define A3XX_CP_PROTECT_REG_0 0x460
+#define A3XX_CP_PROTECT_REG_1 0x461
+#define A3XX_CP_PROTECT_REG_2 0x462
+#define A3XX_CP_PROTECT_REG_3 0x463
+#define A3XX_CP_PROTECT_REG_4 0x464
+#define A3XX_CP_PROTECT_REG_5 0x465
+#define A3XX_CP_PROTECT_REG_6 0x466
+#define A3XX_CP_PROTECT_REG_7 0x467
+#define A3XX_CP_PROTECT_REG_8 0x468
+#define A3XX_CP_PROTECT_REG_9 0x469
+#define A3XX_CP_PROTECT_REG_A 0x46A
+#define A3XX_CP_PROTECT_REG_B 0x46B
+#define A3XX_CP_PROTECT_REG_C 0x46C
+#define A3XX_CP_PROTECT_REG_D 0x46D
+#define A3XX_CP_PROTECT_REG_E 0x46E
+#define A3XX_CP_PROTECT_REG_F 0x46F
+#define A3XX_CP_SCRATCH_REG2 0x57A
+#define A3XX_CP_SCRATCH_REG3 0x57B
+#define A3XX_VSC_BIN_SIZE 0xC01
+#define A3XX_VSC_SIZE_ADDRESS 0xC02
+#define A3XX_VSC_PIPE_CONFIG_0 0xC06
+#define A3XX_VSC_PIPE_DATA_ADDRESS_0 0xC07
+#define A3XX_VSC_PIPE_DATA_LENGTH_0 0xC08
+#define A3XX_VSC_PIPE_CONFIG_1 0xC09
+#define A3XX_VSC_PIPE_DATA_ADDRESS_1 0xC0A
+#define A3XX_VSC_PIPE_DATA_LENGTH_1 0xC0B
+#define A3XX_VSC_PIPE_CONFIG_2 0xC0C
+#define A3XX_VSC_PIPE_DATA_ADDRESS_2 0xC0D
+#define A3XX_VSC_PIPE_DATA_LENGTH_2 0xC0E
+#define A3XX_VSC_PIPE_CONFIG_3 0xC0F
+#define A3XX_VSC_PIPE_DATA_ADDRESS_3 0xC10
+#define A3XX_VSC_PIPE_DATA_LENGTH_3 0xC11
+#define A3XX_VSC_PIPE_CONFIG_4 0xC12
+#define A3XX_VSC_PIPE_DATA_ADDRESS_4 0xC13
+#define A3XX_VSC_PIPE_DATA_LENGTH_4 0xC14
+#define A3XX_VSC_PIPE_CONFIG_5 0xC15
+#define A3XX_VSC_PIPE_DATA_ADDRESS_5 0xC16
+#define A3XX_VSC_PIPE_DATA_LENGTH_5 0xC17
+#define A3XX_VSC_PIPE_CONFIG_6 0xC18
+#define A3XX_VSC_PIPE_DATA_ADDRESS_6 0xC19
+#define A3XX_VSC_PIPE_DATA_LENGTH_6 0xC1A
+#define A3XX_VSC_PIPE_CONFIG_7 0xC1B
+#define A3XX_VSC_PIPE_DATA_ADDRESS_7 0xC1C
+#define A3XX_VSC_PIPE_DATA_LENGTH_7 0xC1D
+#define A3XX_GRAS_CL_USER_PLANE_X0 0xCA0
+#define A3XX_GRAS_CL_USER_PLANE_Y0 0xCA1
+#define A3XX_GRAS_CL_USER_PLANE_Z0 0xCA2
+#define A3XX_GRAS_CL_USER_PLANE_W0 0xCA3
+#define A3XX_GRAS_CL_USER_PLANE_X1 0xCA4
+#define A3XX_GRAS_CL_USER_PLANE_Y1 0xCA5
+#define A3XX_GRAS_CL_USER_PLANE_Z1 0xCA6
+#define A3XX_GRAS_CL_USER_PLANE_W1 0xCA7
+#define A3XX_GRAS_CL_USER_PLANE_X2 0xCA8
+#define A3XX_GRAS_CL_USER_PLANE_Y2 0xCA9
+#define A3XX_GRAS_CL_USER_PLANE_Z2 0xCAA
+#define A3XX_GRAS_CL_USER_PLANE_W2 0xCAB
+#define A3XX_GRAS_CL_USER_PLANE_X3 0xCAC
+#define A3XX_GRAS_CL_USER_PLANE_Y3 0xCAD
+#define A3XX_GRAS_CL_USER_PLANE_Z3 0xCAE
+#define A3XX_GRAS_CL_USER_PLANE_W3 0xCAF
+#define A3XX_GRAS_CL_USER_PLANE_X4 0xCB0
+#define A3XX_GRAS_CL_USER_PLANE_Y4 0xCB1
+#define A3XX_GRAS_CL_USER_PLANE_Z4 0xCB2
+#define A3XX_GRAS_CL_USER_PLANE_W4 0xCB3
+#define A3XX_GRAS_CL_USER_PLANE_X5 0xCB4
+#define A3XX_GRAS_CL_USER_PLANE_Y5 0xCB5
+#define A3XX_GRAS_CL_USER_PLANE_Z5 0xCB6
+#define A3XX_GRAS_CL_USER_PLANE_W5 0xCB7
+#define A3XX_VPC_VPC_DEBUG_RAM_SEL 0xE61
+#define A3XX_VPC_VPC_DEBUG_RAM_READ 0xE62
+#define A3XX_UCHE_CACHE_INVALIDATE0_REG 0xEA0
+#define A3XX_GRAS_CL_CLIP_CNTL 0x2040
+#define A3XX_GRAS_CL_GB_CLIP_ADJ 0x2044
+#define A3XX_GRAS_CL_VPORT_XOFFSET 0x2048
+#define A3XX_GRAS_CL_VPORT_ZOFFSET 0x204C
+#define A3XX_GRAS_CL_VPORT_ZSCALE 0x204D
+#define A3XX_GRAS_SU_POINT_MINMAX 0x2068
+#define A3XX_GRAS_SU_POINT_SIZE 0x2069
+#define A3XX_GRAS_SU_POLY_OFFSET_SCALE 0x206C
+#define A3XX_GRAS_SU_POLY_OFFSET_OFFSET 0x206D
+#define A3XX_GRAS_SU_MODE_CONTROL 0x2070
+#define A3XX_GRAS_SC_CONTROL 0x2072
+#define A3XX_GRAS_SC_SCREEN_SCISSOR_TL 0x2074
+#define A3XX_GRAS_SC_SCREEN_SCISSOR_BR 0x2075
+#define A3XX_GRAS_SC_WINDOW_SCISSOR_TL 0x2079
+#define A3XX_GRAS_SC_WINDOW_SCISSOR_BR 0x207A
+#define A3XX_RB_MODE_CONTROL 0x20C0
+#define A3XX_RB_RENDER_CONTROL 0x20C1
+#define A3XX_RB_MSAA_CONTROL 0x20C2
+#define A3XX_RB_MRT_CONTROL0 0x20C4
+#define A3XX_RB_MRT_BUF_INFO0 0x20C5
+#define A3XX_RB_MRT_BLEND_CONTROL0 0x20C7
+#define A3XX_RB_MRT_BLEND_CONTROL1 0x20CB
+#define A3XX_RB_MRT_BLEND_CONTROL2 0x20CF
+#define A3XX_RB_MRT_BLEND_CONTROL3 0x20D3
+#define A3XX_RB_BLEND_RED 0x20E4
+#define A3XX_RB_COPY_CONTROL 0x20EC
+#define A3XX_RB_COPY_DEST_INFO 0x20EF
+#define A3XX_RB_DEPTH_CONTROL 0x2100
+#define A3XX_RB_STENCIL_CONTROL 0x2104
+#define A3XX_PC_VSTREAM_CONTROL 0x21E4
+#define A3XX_PC_VERTEX_REUSE_BLOCK_CNTL 0x21EA
+#define A3XX_PC_PRIM_VTX_CNTL 0x21EC
+#define A3XX_PC_RESTART_INDEX 0x21ED
+#define A3XX_HLSQ_CONTROL_0_REG 0x2200
+#define A3XX_HLSQ_VS_CONTROL_REG 0x2204
+#define A3XX_HLSQ_CONST_FSPRESV_RANGE_REG 0x2207
+#define A3XX_HLSQ_CL_NDRANGE_0_REG 0x220A
+#define A3XX_HLSQ_CL_NDRANGE_2_REG 0x220C
+#define A3XX_HLSQ_CL_CONTROL_0_REG 0x2211
+#define A3XX_HLSQ_CL_CONTROL_1_REG 0x2212
+#define A3XX_HLSQ_CL_KERNEL_CONST_REG 0x2214
+#define A3XX_HLSQ_CL_KERNEL_GROUP_X_REG 0x2215
+#define A3XX_HLSQ_CL_KERNEL_GROUP_Z_REG 0x2217
+#define A3XX_HLSQ_CL_WG_OFFSET_REG 0x221A
+#define A3XX_VFD_CONTROL_0 0x2240
+#define A3XX_VFD_INDEX_MIN 0x2242
+#define A3XX_VFD_FETCH_INSTR_0_0 0x2246
+#define A3XX_VFD_FETCH_INSTR_0_4 0x224E
+#define A3XX_VFD_DECODE_INSTR_0 0x2266
+#define A3XX_VFD_VS_THREADING_THRESHOLD 0x227E
+#define A3XX_VPC_ATTR 0x2280
+#define A3XX_VPC_VARY_CYLWRAP_ENABLE_1 0x228B
+#define A3XX_SP_SP_CTRL_REG 0x22C0
+#define A3XX_SP_VS_CTRL_REG0 0x22C4
+#define A3XX_SP_VS_CTRL_REG1 0x22C5
+#define A3XX_SP_VS_PARAM_REG 0x22C6
+#define A3XX_SP_VS_OUT_REG_7 0x22CE
+#define A3XX_SP_VS_VPC_DST_REG_0 0x22D0
+#define A3XX_SP_VS_OBJ_OFFSET_REG 0x22D4
+#define A3XX_SP_VS_PVT_MEM_SIZE_REG 0x22D8
+#define A3XX_SP_VS_LENGTH_REG 0x22DF
+#define A3XX_SP_FS_CTRL_REG0 0x22E0
+#define A3XX_SP_FS_CTRL_REG1 0x22E1
+#define A3XX_SP_FS_OBJ_OFFSET_REG 0x22E2
+#define A3XX_SP_FS_PVT_MEM_SIZE_REG 0x22E6
+#define A3XX_SP_FS_FLAT_SHAD_MODE_REG_0 0x22E8
+#define A3XX_SP_FS_FLAT_SHAD_MODE_REG_1 0x22E9
+#define A3XX_SP_FS_OUTPUT_REG 0x22EC
+#define A3XX_SP_FS_MRT_REG_0 0x22F0
+#define A3XX_SP_FS_IMAGE_OUTPUT_REG_0 0x22F4
+#define A3XX_SP_FS_IMAGE_OUTPUT_REG_3 0x22F7
+#define A3XX_SP_FS_LENGTH_REG 0x22FF
+#define A3XX_TPL1_TP_VS_TEX_OFFSET 0x2340
+#define A3XX_TPL1_TP_FS_TEX_OFFSET 0x2342
+#define A3XX_TPL1_TP_FS_BORDER_COLOR_BASE_ADDR 0x2343
+#define A3XX_VBIF_FIXED_SORT_EN 0x300C
+#define A3XX_VBIF_FIXED_SORT_SEL0 0x300D
+#define A3XX_VBIF_FIXED_SORT_SEL1 0x300E
+
+/* Bit flags for RBBM_CTL */
+#define RBBM_RBBM_CTL_RESET_PWR_CTR1  (1 << 1)
+#define RBBM_RBBM_CTL_ENABLE_PWR_CTR1  (17 << 1)
+
+/* Various flags used by the context switch code */
+
+#define SP_MULTI 0
+#define SP_BUFFER_MODE 1
+#define SP_TWO_VTX_QUADS 0
+#define SP_PIXEL_BASED 0
+#define SP_R8G8B8A8_UNORM 8
+#define SP_FOUR_PIX_QUADS 1
+
+#define HLSQ_DIRECT 0
+#define HLSQ_BLOCK_ID_SP_VS 4
+#define HLSQ_SP_VS_INSTR 0
+#define HLSQ_SP_FS_INSTR 0
+#define HLSQ_BLOCK_ID_SP_FS 6
+#define HLSQ_TWO_PIX_QUADS 0
+#define HLSQ_TWO_VTX_QUADS 0
+#define HLSQ_BLOCK_ID_TP_TEX 2
+#define HLSQ_TP_TEX_SAMPLERS 0
+#define HLSQ_TP_TEX_MEMOBJ 1
+#define HLSQ_BLOCK_ID_TP_MIPMAP 3
+#define HLSQ_TP_MIPMAP_BASE 1
+#define HLSQ_FOUR_PIX_QUADS 1
+
+#define RB_FACTOR_ONE 1
+#define RB_BLEND_OP_ADD 0
+#define RB_FACTOR_ZERO 0
+#define RB_DITHER_DISABLE 0
+#define RB_DITHER_ALWAYS 1
+#define RB_FRAG_NEVER 0
+#define RB_ENDIAN_NONE 0
+#define RB_R8G8B8A8_UNORM 8
+#define RB_RESOLVE_PASS 2
+#define RB_CLEAR_MODE_RESOLVE 1
+#define RB_TILINGMODE_LINEAR 0
+#define RB_REF_NEVER 0
+#define RB_STENCIL_KEEP 0
+#define RB_RENDERING_PASS 0
+#define RB_TILINGMODE_32X32 2
+
+#define PC_DRAW_TRIANGLES 2
+#define PC_DI_PT_RECTLIST 8
+#define PC_DI_SRC_SEL_AUTO_INDEX 2
+#define PC_DI_INDEX_SIZE_16_BIT 0
+#define PC_DI_IGNORE_VISIBILITY 0
+#define PC_DI_PT_TRILIST 4
+#define PC_DI_SRC_SEL_IMMEDIATE 1
+#define PC_DI_INDEX_SIZE_32_BIT 1
+
+#define UCHE_ENTIRE_CACHE 1
+#define UCHE_OP_INVALIDATE 1
+
+/*
+ * The following are bit field shifts within some of the registers defined
+ * above. These are used in the context switch code in conjunction with the
+ * _SET macro
+ */
+
+#define GRAS_CL_CLIP_CNTL_CLIP_DISABLE 16
+#define GRAS_CL_CLIP_CNTL_IJ_PERSP_CENTER 12
+#define GRAS_CL_CLIP_CNTL_PERSP_DIVISION_DISABLE 21
+#define GRAS_CL_CLIP_CNTL_VP_CLIP_CODE_IGNORE 19
+#define GRAS_CL_CLIP_CNTL_VP_XFORM_DISABLE 20
+#define GRAS_CL_CLIP_CNTL_ZFAR_CLIP_DISABLE 17
+#define GRAS_CL_VPORT_XSCALE_VPORT_XSCALE 0
+#define GRAS_CL_VPORT_YSCALE_VPORT_YSCALE 0
+#define GRAS_CL_VPORT_ZSCALE_VPORT_ZSCALE 0
+#define GRAS_SC_CONTROL_RASTER_MODE 12
+#define GRAS_SC_CONTROL_RENDER_MODE 4
+#define GRAS_SC_SCREEN_SCISSOR_BR_BR_X 0
+#define GRAS_SC_SCREEN_SCISSOR_BR_BR_Y 16
+#define GRAS_SC_WINDOW_SCISSOR_BR_BR_X 0
+#define GRAS_SC_WINDOW_SCISSOR_BR_BR_Y 16
+#define HLSQ_CONSTFSPRESERVEDRANGEREG_ENDENTRY 16
+#define HLSQ_CONSTFSPRESERVEDRANGEREG_STARTENTRY 0
+#define HLSQ_CTRL0REG_CHUNKDISABLE 26
+#define HLSQ_CTRL0REG_CONSTSWITCHMODE 27
+#define HLSQ_CTRL0REG_FSSUPERTHREADENABLE 6
+#define HLSQ_CTRL0REG_FSTHREADSIZE 4
+#define HLSQ_CTRL0REG_LAZYUPDATEDISABLE 28
+#define HLSQ_CTRL0REG_RESERVED2 10
+#define HLSQ_CTRL0REG_SPCONSTFULLUPDATE 29
+#define HLSQ_CTRL0REG_SPSHADERRESTART 9
+#define HLSQ_CTRL0REG_TPFULLUPDATE 30
+#define HLSQ_CTRL1REG_RESERVED1 9
+#define HLSQ_CTRL1REG_VSSUPERTHREADENABLE 8
+#define HLSQ_CTRL1REG_VSTHREADSIZE 6
+#define HLSQ_CTRL2REG_PRIMALLOCTHRESHOLD 26
+#define HLSQ_FSCTRLREG_FSCONSTLENGTH 0
+#define HLSQ_FSCTRLREG_FSCONSTSTARTOFFSET 12
+#define HLSQ_FSCTRLREG_FSINSTRLENGTH 24
+#define HLSQ_VSCTRLREG_VSINSTRLENGTH 24
+#define PC_PRIM_VTX_CONTROL_POLYMODE_BACK_PTYPE 8
+#define PC_PRIM_VTX_CONTROL_POLYMODE_FRONT_PTYPE 5
+#define PC_PRIM_VTX_CONTROL_PROVOKING_VTX_LAST 25
+#define PC_PRIM_VTX_CONTROL_STRIDE_IN_VPC 0
+#define PC_DRAW_INITIATOR_PRIM_TYPE 0
+#define PC_DRAW_INITIATOR_SOURCE_SELECT 6
+#define PC_DRAW_INITIATOR_VISIBILITY_CULLING_MODE 9
+#define PC_DRAW_INITIATOR_INDEX_SIZE 0x0B
+#define PC_DRAW_INITIATOR_SMALL_INDEX 0x0D
+#define PC_DRAW_INITIATOR_PRE_DRAW_INITIATOR_ENABLE 0x0E
+#define RB_COPYCONTROL_COPY_GMEM_BASE 14
+#define RB_COPYCONTROL_RESOLVE_CLEAR_MODE 4
+#define RB_COPYDESTBASE_COPY_DEST_BASE 4
+#define RB_COPYDESTINFO_COPY_COMPONENT_ENABLE 14
+#define RB_COPYDESTINFO_COPY_DEST_ENDIAN 18
+#define RB_COPYDESTINFO_COPY_DEST_FORMAT 2
+#define RB_COPYDESTINFO_COPY_DEST_TILE 0
+#define RB_COPYDESTPITCH_COPY_DEST_PITCH 0
+#define RB_DEPTHCONTROL_Z_TEST_FUNC 4
+#define RB_MODECONTROL_RENDER_MODE 8
+#define RB_MODECONTROL_MARB_CACHE_SPLIT_MODE 15
+#define RB_MODECONTROL_PACKER_TIMER_ENABLE 16
+#define RB_MRTBLENDCONTROL_ALPHA_BLEND_OPCODE 21
+#define RB_MRTBLENDCONTROL_ALPHA_DEST_FACTOR 24
+#define RB_MRTBLENDCONTROL_ALPHA_SRC_FACTOR 16
+#define RB_MRTBLENDCONTROL_CLAMP_ENABLE 29
+#define RB_MRTBLENDCONTROL_RGB_BLEND_OPCODE 5
+#define RB_MRTBLENDCONTROL_RGB_DEST_FACTOR 8
+#define RB_MRTBLENDCONTROL_RGB_SRC_FACTOR 0
+#define RB_MRTBUFBASE_COLOR_BUF_BASE 4
+#define RB_MRTBUFINFO_COLOR_BUF_PITCH 17
+#define RB_MRTBUFINFO_COLOR_FORMAT 0
+#define RB_MRTBUFINFO_COLOR_TILE_MODE 6
+#define RB_MRTCONTROL_COMPONENT_ENABLE 24
+#define RB_MRTCONTROL_DITHER_MODE 12
+#define RB_MRTCONTROL_READ_DEST_ENABLE 3
+#define RB_MRTCONTROL_ROP_CODE 8
+#define RB_MSAACONTROL_MSAA_DISABLE 10
+#define RB_MSAACONTROL_SAMPLE_MASK 16
+#define RB_RENDERCONTROL_ALPHA_TEST_FUNC 24
+#define RB_RENDERCONTROL_BIN_WIDTH 4
+#define RB_RENDERCONTROL_DISABLE_COLOR_PIPE 12
+#define RB_STENCILCONTROL_STENCIL_FAIL 11
+#define RB_STENCILCONTROL_STENCIL_FAIL_BF 23
+#define RB_STENCILCONTROL_STENCIL_FUNC 8
+#define RB_STENCILCONTROL_STENCIL_FUNC_BF 20
+#define RB_STENCILCONTROL_STENCIL_ZFAIL 17
+#define RB_STENCILCONTROL_STENCIL_ZFAIL_BF 29
+#define RB_STENCILCONTROL_STENCIL_ZPASS 14
+#define RB_STENCILCONTROL_STENCIL_ZPASS_BF 26
+#define SP_FSCTRLREG0_FSFULLREGFOOTPRINT 10
+#define SP_FSCTRLREG0_FSICACHEINVALID 2
+#define SP_FSCTRLREG0_FSINOUTREGOVERLAP 18
+#define SP_FSCTRLREG0_FSINSTRBUFFERMODE 1
+#define SP_FSCTRLREG0_FSLENGTH 24
+#define SP_FSCTRLREG0_FSSUPERTHREADMODE 21
+#define SP_FSCTRLREG0_FSTHREADMODE 0
+#define SP_FSCTRLREG0_FSTHREADSIZE 20
+#define SP_FSCTRLREG0_PIXLODENABLE 22
+#define SP_FSCTRLREG1_FSCONSTLENGTH 0
+#define SP_FSCTRLREG1_FSINITIALOUTSTANDING 20
+#define SP_FSCTRLREG1_HALFPRECVAROFFSET 24
+#define SP_FSMRTREG_REGID 0
+#define SP_FSOUTREG_PAD0 2
+#define SP_IMAGEOUTPUTREG_MRTFORMAT 0
+#define SP_IMAGEOUTPUTREG_PAD0 6
+#define SP_OBJOFFSETREG_CONSTOBJECTSTARTOFFSET 16
+#define SP_OBJOFFSETREG_SHADEROBJOFFSETINIC 25
+#define SP_SHADERLENGTH_LEN 0
+#define SP_SPCTRLREG_CONSTMODE 18
+#define SP_SPCTRLREG_SLEEPMODE 20
+#define SP_VSCTRLREG0_VSFULLREGFOOTPRINT 10
+#define SP_VSCTRLREG0_VSICACHEINVALID 2
+#define SP_VSCTRLREG0_VSINSTRBUFFERMODE 1
+#define SP_VSCTRLREG0_VSLENGTH 24
+#define SP_VSCTRLREG0_VSSUPERTHREADMODE 21
+#define SP_VSCTRLREG0_VSTHREADMODE 0
+#define SP_VSCTRLREG0_VSTHREADSIZE 20
+#define SP_VSCTRLREG1_VSINITIALOUTSTANDING 24
+#define SP_VSOUTREG_COMPMASK0 9
+#define SP_VSPARAMREG_POSREGID 0
+#define SP_VSPARAMREG_PSIZEREGID 8
+#define SP_VSPARAMREG_TOTALVSOUTVAR 20
+#define SP_VSVPCDSTREG_OUTLOC0 0
+#define TPL1_TPTEXOFFSETREG_BASETABLEPTR 16
+#define TPL1_TPTEXOFFSETREG_MEMOBJOFFSET 8
+#define TPL1_TPTEXOFFSETREG_SAMPLEROFFSET 0
+#define UCHE_INVALIDATE1REG_OPCODE 0x1C
+#define UCHE_INVALIDATE1REG_ALLORPORTION 0x1F
+#define VFD_BASEADDR_BASEADDR 0
+#define VFD_CTRLREG0_PACKETSIZE 18
+#define VFD_CTRLREG0_STRMDECINSTRCNT 22
+#define VFD_CTRLREG0_STRMFETCHINSTRCNT 27
+#define VFD_CTRLREG0_TOTALATTRTOVS 0
+#define VFD_CTRLREG1_MAXSTORAGE 0
+#define VFD_CTRLREG1_REGID4INST 24
+#define VFD_CTRLREG1_REGID4VTX 16
+#define VFD_DECODEINSTRUCTIONS_CONSTFILL 4
+#define VFD_DECODEINSTRUCTIONS_FORMAT 6
+#define VFD_DECODEINSTRUCTIONS_LASTCOMPVALID 29
+#define VFD_DECODEINSTRUCTIONS_REGID 12
+#define VFD_DECODEINSTRUCTIONS_SHIFTCNT 24
+#define VFD_DECODEINSTRUCTIONS_SWITCHNEXT 30
+#define VFD_DECODEINSTRUCTIONS_WRITEMASK 0
+#define VFD_FETCHINSTRUCTIONS_BUFSTRIDE 7
+#define VFD_FETCHINSTRUCTIONS_FETCHSIZE 0
+#define VFD_FETCHINSTRUCTIONS_INDEXDECODE 18
+#define VFD_FETCHINSTRUCTIONS_STEPRATE 24
+#define VFD_FETCHINSTRUCTIONS_SWITCHNEXT 17
+#define VFD_THREADINGTHRESHOLD_REGID_VTXCNT 8
+#define VFD_THREADINGTHRESHOLD_RESERVED6 4
+#define VPC_VPCATTR_LMSIZE 28
+#define VPC_VPCATTR_THRHDASSIGN 12
+#define VPC_VPCATTR_TOTALATTR 0
+#define VPC_VPCPACK_NUMFPNONPOSVAR 8
+#define VPC_VPCPACK_NUMNONPOSVSVAR 16
+#define VPC_VPCVARPSREPLMODE_COMPONENT08 0
+#define VPC_VPCVARPSREPLMODE_COMPONENT09 2
+#define VPC_VPCVARPSREPLMODE_COMPONENT0A 4
+#define VPC_VPCVARPSREPLMODE_COMPONENT0B 6
+#define VPC_VPCVARPSREPLMODE_COMPONENT0C 8
+#define VPC_VPCVARPSREPLMODE_COMPONENT0D 10
+#define VPC_VPCVARPSREPLMODE_COMPONENT0E 12
+#define VPC_VPCVARPSREPLMODE_COMPONENT0F 14
+#define VPC_VPCVARPSREPLMODE_COMPONENT10 16
+#define VPC_VPCVARPSREPLMODE_COMPONENT11 18
+#define VPC_VPCVARPSREPLMODE_COMPONENT12 20
+#define VPC_VPCVARPSREPLMODE_COMPONENT13 22
+#define VPC_VPCVARPSREPLMODE_COMPONENT14 24
+#define VPC_VPCVARPSREPLMODE_COMPONENT15 26
+#define VPC_VPCVARPSREPLMODE_COMPONENT16 28
+#define VPC_VPCVARPSREPLMODE_COMPONENT17 30
+
+/* RBBM Debug bus block IDs */
+#define RBBM_BLOCK_ID_NONE             0x0
+#define RBBM_BLOCK_ID_CP               0x1
+#define RBBM_BLOCK_ID_RBBM             0x2
+#define RBBM_BLOCK_ID_VBIF             0x3
+#define RBBM_BLOCK_ID_HLSQ             0x4
+#define RBBM_BLOCK_ID_UCHE             0x5
+#define RBBM_BLOCK_ID_PC               0x8
+#define RBBM_BLOCK_ID_VFD              0x9
+#define RBBM_BLOCK_ID_VPC              0xa
+#define RBBM_BLOCK_ID_TSE              0xb
+#define RBBM_BLOCK_ID_RAS              0xc
+#define RBBM_BLOCK_ID_VSC              0xd
+#define RBBM_BLOCK_ID_SP_0             0x10
+#define RBBM_BLOCK_ID_SP_1             0x11
+#define RBBM_BLOCK_ID_SP_2             0x12
+#define RBBM_BLOCK_ID_SP_3             0x13
+#define RBBM_BLOCK_ID_TPL1_0           0x18
+#define RBBM_BLOCK_ID_TPL1_1           0x19
+#define RBBM_BLOCK_ID_TPL1_2           0x1a
+#define RBBM_BLOCK_ID_TPL1_3           0x1b
+#define RBBM_BLOCK_ID_RB_0             0x20
+#define RBBM_BLOCK_ID_RB_1             0x21
+#define RBBM_BLOCK_ID_RB_2             0x22
+#define RBBM_BLOCK_ID_RB_3             0x23
+#define RBBM_BLOCK_ID_MARB_0           0x28
+#define RBBM_BLOCK_ID_MARB_1           0x29
+#define RBBM_BLOCK_ID_MARB_2           0x2a
+#define RBBM_BLOCK_ID_MARB_3           0x2b
+
+#endif
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index ce76a8f..b44dccc 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -10,7 +10,6 @@
  * GNU General Public License for more details.
  *
  */
-#include <linux/delay.h>
 #include <linux/uaccess.h>
 #include <linux/vmalloc.h>
 #include <linux/ioctl.h>
@@ -29,7 +28,7 @@
 #include "adreno_postmortem.h"
 
 #include "a2xx_reg.h"
-#include "kgsl_mmu.h"
+#include "a3xx_reg.h"
 
 #define DRIVER_VERSION_MAJOR   3
 #define DRIVER_VERSION_MINOR   1
@@ -155,35 +154,10 @@
 	{ ADRENO_REV_A225, 2, 2, ANY_ID, ANY_ID,
 		"a225_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
 		1536, 768 },
+	{ ADRENO_REV_A320, 3, 1, ANY_ID, ANY_ID,
+		"a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev },
 };
 
-static void adreno_gmeminit(struct adreno_device *adreno_dev)
-{
-	struct kgsl_device *device = &adreno_dev->dev;
-	union reg_rb_edram_info rb_edram_info;
-	unsigned int gmem_size;
-	unsigned int edram_value = 0;
-
-	/* make sure edram range is aligned to size */
-	BUG_ON(adreno_dev->gmemspace.gpu_base &
-				(adreno_dev->gmemspace.sizebytes - 1));
-
-	/* get edram_size value equivalent */
-	gmem_size = (adreno_dev->gmemspace.sizebytes >> 14);
-	while (gmem_size >>= 1)
-		edram_value++;
-
-	rb_edram_info.val = 0;
-
-	rb_edram_info.f.edram_size = edram_value;
-	rb_edram_info.f.edram_mapping_mode = 0; /* EDRAM_MAP_UPPER */
-
-	/* must be aligned to size */
-	rb_edram_info.f.edram_range = (adreno_dev->gmemspace.gpu_base >> 14);
-
-	adreno_regwrite(device, REG_RB_EDRAM_INFO, rb_edram_info.val);
-}
-
 static irqreturn_t adreno_isr(int irq, void *data)
 {
 	irqreturn_t result;
@@ -360,7 +334,32 @@
 }
 
 static unsigned int
-adreno_getchipid(struct kgsl_device *device)
+a3xx_getchipid(struct kgsl_device *device)
+{
+	unsigned int chipid = 0;
+	unsigned int coreid, majorid, minorid, patchid;
+	unsigned int version;
+
+	adreno_regread(device, A3XX_RBBM_HW_VERSION, &version);
+
+	coreid = 0x03;
+
+	/* Version might not be set - if it isn't, assume this is 320 */
+	if (version)
+		majorid = version & 0x0F;
+	else
+		majorid = 1;
+
+	minorid = (version >> 4) & 0xFFF;
+	patchid = 0;
+
+	chipid = (coreid << 24) | (majorid << 16) | (minorid << 8) | patchid;
+
+	return chipid;
+}
+
+static unsigned int
+a2xx_getchipid(struct kgsl_device *device)
 {
 	unsigned int chipid = 0;
 	unsigned int coreid, majorid, minorid, patchid, revid;
@@ -398,6 +397,15 @@
 	return chipid;
 }
 
+static unsigned int
+adreno_getchipid(struct kgsl_device *device)
+{
+	if (cpu_is_apq8064())
+		return a3xx_getchipid(device);
+	else
+		return a2xx_getchipid(device);
+}
+
 static inline bool _rev_match(unsigned int id, unsigned int entry)
 {
 	return (entry == ANY_ID || entry == id);
@@ -493,7 +501,6 @@
 {
 	int status = -EINVAL;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	int init_reftimestamp = 0x7fffffff;
 
 	kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
 
@@ -509,92 +516,36 @@
 		goto error_clk_off;
 	}
 
-	if (adreno_is_a20x(adreno_dev)) {
+	/* Set up the MMU */
+	if (adreno_is_a2xx(adreno_dev)) {
 		/*
 		 * the MH_CLNT_INTF_CTRL_CONFIG registers aren't present
 		 * on older gpus
 		 */
-		device->mh.mh_intf_cfg1 = 0;
-		device->mh.mh_intf_cfg2 = 0;
+		if (adreno_is_a20x(adreno_dev)) {
+			device->mh.mh_intf_cfg1 = 0;
+			device->mh.mh_intf_cfg2 = 0;
+		}
+
+		kgsl_mh_start(device);
 	}
 
-	kgsl_mh_start(device);
-
-	if (kgsl_mmu_start(device))
+	status = kgsl_mmu_start(device);
+	if (status)
 		goto error_clk_off;
 
-	/*We need to make sure all blocks are powered up and clocked before
-	*issuing a soft reset.  The overrides will then be turned off (set to 0)
-	*/
-	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0xfffffffe);
-	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xffffffff);
-
-	/* Only reset CP block if all blocks have previously been reset */
-	if (!(device->flags & KGSL_FLAGS_SOFT_RESET) ||
-		!adreno_is_a22x(adreno_dev)) {
-		adreno_regwrite(device, REG_RBBM_SOFT_RESET, 0xFFFFFFFF);
-		device->flags |= KGSL_FLAGS_SOFT_RESET;
-	} else
-		adreno_regwrite(device, REG_RBBM_SOFT_RESET, 0x00000001);
-
-	/* The core is in an indeterminate state until the reset completes
-	 * after 30ms.
-	 */
-	msleep(30);
-
-	adreno_regwrite(device, REG_RBBM_SOFT_RESET, 0x00000000);
-
-	adreno_regwrite(device, REG_RBBM_CNTL, 0x00004442);
-
-	if (adreno_is_a225(adreno_dev)) {
-		/* Enable large instruction store for A225 */
-		adreno_regwrite(device, REG_SQ_FLOW_CONTROL, 0x18000000);
-	}
-
-	adreno_regwrite(device, REG_SQ_VS_PROGRAM, 0x00000000);
-	adreno_regwrite(device, REG_SQ_PS_PROGRAM, 0x00000000);
-
-	if (cpu_is_msm8960() || cpu_is_msm8930())
-		adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0x200);
-	else
-		adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0);
-
-	if (!adreno_is_a22x(adreno_dev))
-		adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0);
-	else
-		adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0x80);
-
-	kgsl_sharedmem_set(&device->memstore, 0, 0, device->memstore.size);
-
-	kgsl_sharedmem_writel(&device->memstore,
-			      KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts),
-			      init_reftimestamp);
-
-	adreno_regwrite(device, REG_RBBM_DEBUG, 0x00080000);
-
-	/* Make sure interrupts are disabled */
-
-	adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
-	adreno_regwrite(device, REG_CP_INT_CNTL, 0);
-	adreno_regwrite(device, REG_SQ_INT_CNTL, 0);
-
-	if (adreno_is_a22x(adreno_dev))
-		adreno_dev->gmemspace.sizebytes = SZ_512K;
-	else
-		adreno_dev->gmemspace.sizebytes = SZ_256K;
-	adreno_gmeminit(adreno_dev);
+	/* Start the GPU */
+	adreno_dev->gpudev->start(adreno_dev);
 
 	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
 	device->ftbl->irqctrl(device, 1);
 
 	status = adreno_ringbuffer_start(&adreno_dev->ringbuffer, init_ram);
-	if (status != 0)
-		goto error_irq_off;
+	if (status == 0) {
+		mod_timer(&device->idle_timer, jiffies + FIRST_TIMEOUT);
+		return 0;
+	}
 
-	mod_timer(&device->idle_timer, jiffies + FIRST_TIMEOUT);
-	return status;
-
-error_irq_off:
 	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
 	kgsl_mmu_stop(device);
 error_clk_off:
@@ -869,7 +820,8 @@
 		msecs_to_jiffies(adreno_dev->wait_timeout);
 	unsigned long wait_time = jiffies + wait_timeout;
 
-	kgsl_cffdump_regpoll(device->id, REG_RBBM_STATUS << 2,
+	kgsl_cffdump_regpoll(device->id,
+		adreno_dev->gpudev->reg_rbbm_status << 2,
 		0x00000000, 0x80000000);
 	/* first, wait until the CP has consumed all the commands in
 	 * the ring buffer
@@ -890,9 +842,15 @@
 	/* now, wait for the GPU to finish its operations */
 	wait_time = jiffies + wait_timeout;
 	while (time_before(jiffies, wait_time)) {
-		adreno_regread(device, REG_RBBM_STATUS, &rbbm_status);
-		if (rbbm_status == 0x110)
-			return 0;
+		adreno_regread(device, adreno_dev->gpudev->reg_rbbm_status,
+			&rbbm_status);
+		if (adreno_is_a2xx(adreno_dev)) {
+			if (rbbm_status == 0x110)
+				return 0;
+		} else {
+			if (!(rbbm_status & 0x80000000))
+				return 0;
+		}
 	}
 
 err:
@@ -918,10 +876,17 @@
 		GSL_RB_GET_READPTR(rb, &rb->rptr);
 		if (!device->active_cnt && (rb->rptr == rb->wptr)) {
 			/* Is the core idle? */
-			adreno_regread(device, REG_RBBM_STATUS,
-					    &rbbm_status);
-			if (rbbm_status == 0x110)
-				status = true;
+			adreno_regread(device,
+				adreno_dev->gpudev->reg_rbbm_status,
+				&rbbm_status);
+
+			if (adreno_is_a2xx(adreno_dev)) {
+				if (rbbm_status == 0x110)
+					status = true;
+			} else {
+				if (!(rbbm_status & 0x80000000))
+					status = true;
+			}
 		}
 	} else {
 		status = true;
@@ -1278,44 +1243,29 @@
 static void adreno_power_stats(struct kgsl_device *device,
 				struct kgsl_power_stats *stats)
 {
-	unsigned int reg;
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+	unsigned int cycles;
+
+	/* Get the busy cycles counted since the counter was last reset */
+	/* Calling this function also resets and restarts the counter */
+
+	cycles = adreno_dev->gpudev->busy_cycles(adreno_dev);
 
 	/* In order to calculate idle you have to have run the algorithm *
 	 * at least once to get a start time. */
 	if (pwr->time != 0) {
-		s64 tmp;
-		/* Stop the performance moniter and read the current *
-		 * busy cycles. */
-		adreno_regwrite(device,
-			REG_CP_PERFMON_CNTL,
-			REG_PERF_MODE_CNT |
-			REG_PERF_STATE_FREEZE);
-		adreno_regread(device, REG_RBBM_PERFCOUNTER1_LO, &reg);
-		tmp = ktime_to_us(ktime_get());
+		s64 tmp = ktime_to_us(ktime_get());
 		stats->total_time = tmp - pwr->time;
 		pwr->time = tmp;
-		stats->busy_time = adreno_ticks_to_us(reg, device->pwrctrl.
+		stats->busy_time = adreno_ticks_to_us(cycles, device->pwrctrl.
 				pwrlevels[device->pwrctrl.active_pwrlevel].
 				gpu_freq);
-
-		adreno_regwrite(device,
-			REG_CP_PERFMON_CNTL,
-			REG_PERF_MODE_CNT |
-			REG_PERF_STATE_RESET);
 	} else {
 		stats->total_time = 0;
 		stats->busy_time = 0;
 		pwr->time = ktime_to_us(ktime_get());
 	}
-
-	/* re-enable the performance moniters */
-	adreno_regread(device, REG_RBBM_PM_OVERRIDE2, &reg);
-	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, (reg | 0x40));
-	adreno_regwrite(device, REG_RBBM_PERFCOUNTER1_SELECT, 0x1);
-	adreno_regwrite(device,
-		REG_CP_PERFMON_CNTL,
-		REG_PERF_MODE_CNT | REG_PERF_STATE_ENABLE);
 }
 
 void adreno_irqctrl(struct kgsl_device *device, int state)
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index bdba624..9c2d704 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -52,6 +52,7 @@
 	ADRENO_REV_A205 = 205,
 	ADRENO_REV_A220 = 220,
 	ADRENO_REV_A225 = 225,
+	ADRENO_REV_A320 = 320,
 };
 
 struct adreno_gpudev;
@@ -77,18 +78,28 @@
 };
 
 struct adreno_gpudev {
-	int (*ctxt_gpustate_shadow)(struct adreno_device *,
-		struct adreno_context *);
-	int (*ctxt_gmem_shadow)(struct adreno_device *,
-		struct adreno_context *);
+	/*
+	 * These registers are in a different location on A3XX,  so define
+	 * them in the structure and use them as variables.
+	 */
+	unsigned int reg_rbbm_status;
+	unsigned int reg_cp_pfp_ucode_data;
+	unsigned int reg_cp_pfp_ucode_addr;
+
+	/* GPU specific function hooks */
+	int (*ctxt_create)(struct adreno_device *, struct adreno_context *);
 	void (*ctxt_save)(struct adreno_device *, struct adreno_context *);
 	void (*ctxt_restore)(struct adreno_device *, struct adreno_context *);
 	irqreturn_t (*irq_handler)(struct adreno_device *);
 	void (*irq_control)(struct adreno_device *, int);
 	void * (*snapshot)(struct adreno_device *, void *, int *, int);
+	void (*rb_init)(struct adreno_device *, struct adreno_ringbuffer *);
+	void (*start)(struct adreno_device *);
+	unsigned int (*busy_cycles)(struct adreno_device *);
 };
 
 extern struct adreno_gpudev adreno_a2xx_gpudev;
+extern struct adreno_gpudev adreno_a3xx_gpudev;
 
 /* A2XX register sets defined in adreno_a2xx.c */
 extern const unsigned int a200_registers[];
@@ -96,6 +107,10 @@
 extern const unsigned int a200_registers_count;
 extern const unsigned int a220_registers_count;
 
+/* A3XX register set defined in adreno_a3xx.c */
+extern const unsigned int a3xx_registers[];
+extern const unsigned int a3xx_registers_count;
+
 int adreno_idle(struct kgsl_device *device, unsigned int timeout);
 void adreno_regread(struct kgsl_device *device, unsigned int offsetwords,
 				unsigned int *value);
@@ -147,7 +162,12 @@
 
 static inline int adreno_is_a2xx(struct adreno_device *adreno_dev)
 {
-	return (adreno_dev->gpurev <= ADRENO_REV_A225);
+	return (adreno_dev->gpurev <= 299);
+}
+
+static inline int adreno_is_a3xx(struct adreno_device *adreno_dev)
+{
+	return (adreno_dev->gpurev >= 300);
 }
 
 /**
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 7098002..e31b76b 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -11,6 +11,9 @@
  *
  */
 
+#include <linux/delay.h>
+#include <mach/socinfo.h>
+
 #include "kgsl.h"
 #include "kgsl_sharedmem.h"
 #include "kgsl_cffdump.h"
@@ -619,14 +622,16 @@
 	unsigned int addr = shadow->gmemshadow.gpuaddr;
 	unsigned int offset = (addr - (addr & 0xfffff000)) / bytesperpixel;
 
-	/* Store TP0_CHICKEN register */
-	*cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
-	*cmds++ = REG_TP0_CHICKEN;
+	if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
+		/* Store TP0_CHICKEN register */
+		*cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+		*cmds++ = REG_TP0_CHICKEN;
 
-	*cmds++ = tmp_ctx.chicken_restore;
+		*cmds++ = tmp_ctx.chicken_restore;
 
-	*cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
-	*cmds++ = 0;
+		*cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+		*cmds++ = 0;
+	}
 
 	/* Set TP0_CHICKEN to zero */
 	*cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
@@ -829,13 +834,15 @@
 	unsigned int *cmds = shadow->gmem_restore_commands;
 	unsigned int *start = cmds;
 
-	/* Store TP0_CHICKEN register */
-	*cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
-	*cmds++ = REG_TP0_CHICKEN;
-	*cmds++ = tmp_ctx.chicken_restore;
+	if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
+		/* Store TP0_CHICKEN register */
+		*cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+		*cmds++ = REG_TP0_CHICKEN;
+		*cmds++ = tmp_ctx.chicken_restore;
 
-	*cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
-	*cmds++ = 0;
+		*cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+		*cmds++ = 0;
+	}
 
 	/* Set TP0_CHICKEN to zero */
 	*cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
@@ -1297,45 +1304,22 @@
 }
 
 /* create buffers for saving/restoring registers, constants, & GMEM */
-static int a2xx_ctxt_gpustate_shadow(struct adreno_device *adreno_dev,
+static int a2xx_create_gpustate_shadow(struct adreno_device *adreno_dev,
 			struct adreno_context *drawctxt)
 {
-	int result;
-
-	/* Allocate vmalloc memory to store the gpustate */
-	result = kgsl_allocate(&drawctxt->gpustate,
-		drawctxt->pagetable, _context_size(adreno_dev));
-
-	if (result)
-		return result;
-
 	drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW;
 
-	/* Blank out h/w register, constant, and command buffer shadows. */
-	kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0,
-			   _context_size(adreno_dev));
-
-	/* set-up command and vertex buffer pointers */
-	tmp_ctx.cmd = tmp_ctx.start
-	    = (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
-
 	/* build indirect command buffers to save & restore regs/constants */
 	build_regrestore_cmds(adreno_dev, drawctxt);
 	build_regsave_cmds(adreno_dev, drawctxt);
 
 	build_shader_save_restore_cmds(adreno_dev, drawctxt);
 
-	kgsl_cache_range_op(&drawctxt->gpustate,
-			    KGSL_CACHE_OP_FLUSH);
-
-	kgsl_cffdump_syncmem(NULL, &drawctxt->gpustate,
-			drawctxt->gpustate.gpuaddr,
-			drawctxt->gpustate.size, false);
 	return 0;
 }
 
 /* create buffers for saving/restoring registers, constants, & GMEM */
-static int a2xx_ctxt_gmem_shadow(struct adreno_device *adreno_dev,
+static int a2xx_create_gmem_shadow(struct adreno_device *adreno_dev,
 			struct adreno_context *drawctxt)
 {
 	int result;
@@ -1362,7 +1346,8 @@
 		&tmp_ctx.cmd);
 
 	/* build TP0_CHICKEN register restore command buffer */
-	tmp_ctx.cmd = build_chicken_restore_cmds(drawctxt);
+	if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE))
+		tmp_ctx.cmd = build_chicken_restore_cmds(drawctxt);
 
 	/* build indirect command buffers to save & restore gmem */
 	drawctxt->context_gmem_shadow.gmem_save_commands = tmp_ctx.cmd;
@@ -1385,7 +1370,61 @@
 	return 0;
 }
 
-static void a2xx_ctxt_save(struct adreno_device *adreno_dev,
+static int a2xx_drawctxt_create(struct adreno_device *adreno_dev,
+	struct adreno_context *drawctxt)
+{
+	int ret;
+
+	/*
+	 * Allocate memory for the GPU state and the context commands.
+	 * Despite the name, this is much more then just storage for
+	 * the gpustate.  This contains command space for gmem save
+	 * and texture and vertex buffer storage too
+	 */
+
+	ret = kgsl_allocate(&drawctxt->gpustate,
+		drawctxt->pagetable, _context_size(adreno_dev));
+
+	if (ret)
+		return ret;
+
+	kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0,
+		_context_size(adreno_dev));
+
+	tmp_ctx.cmd = tmp_ctx.start
+	    = (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
+
+	if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
+		ret = a2xx_create_gpustate_shadow(adreno_dev, drawctxt);
+		if (ret)
+			goto done;
+
+		drawctxt->flags |= CTXT_FLAGS_SHADER_SAVE;
+	}
+
+	if (!(drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC)) {
+		ret = a2xx_create_gmem_shadow(adreno_dev, drawctxt);
+		if (ret)
+			goto done;
+	}
+
+	/* Flush and sync the gpustate memory */
+
+	kgsl_cache_range_op(&drawctxt->gpustate,
+			    KGSL_CACHE_OP_FLUSH);
+
+	kgsl_cffdump_syncmem(NULL, &drawctxt->gpustate,
+			drawctxt->gpustate.gpuaddr,
+			drawctxt->gpustate.size, false);
+
+done:
+	if (ret)
+		kgsl_sharedmem_free(&drawctxt->gpustate);
+
+	return ret;
+}
+
+static void a2xx_drawctxt_save(struct adreno_device *adreno_dev,
 			struct adreno_context *context)
 {
 	struct kgsl_device *device = &adreno_dev->dev;
@@ -1398,25 +1437,27 @@
 		KGSL_CTXT_WARN(device,
 			"Current active context has caused gpu hang\n");
 
-	KGSL_CTXT_INFO(device,
-		"active context flags %08x\n", context->flags);
+	if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
 
-	/* save registers and constants. */
-	adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
-		context->reg_save, 3);
-
-	if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
-		/* save shader partitioning and instructions. */
-		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
-			context->shader_save, 3);
-
-		/* fixup shader partitioning parameter for
-		 *  SET_SHADER_BASES.
-		 */
+		/* save registers and constants. */
 		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
-			context->shader_fixup, 3);
+			context->reg_save, 3);
 
-		context->flags |= CTXT_FLAGS_SHADER_RESTORE;
+		if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
+			/* save shader partitioning and instructions. */
+			adreno_ringbuffer_issuecmds(device,
+				KGSL_CMD_FLAGS_PMODE,
+				context->shader_save, 3);
+
+			/*
+			 * fixup shader partitioning parameter for
+			 *  SET_SHADER_BASES.
+			 */
+			adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+				context->shader_fixup, 3);
+
+			context->flags |= CTXT_FLAGS_SHADER_RESTORE;
+		}
 	}
 
 	if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
@@ -1428,8 +1469,10 @@
 			context->context_gmem_shadow.gmem_save, 3);
 
 		/* Restore TP0_CHICKEN */
-		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
-			context->chicken_restore, 3);
+		if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
+			adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+				context->chicken_restore, 3);
+		}
 
 		context->flags |= CTXT_FLAGS_GMEM_RESTORE;
 	} else if (adreno_is_a225(adreno_dev)) {
@@ -1459,7 +1502,7 @@
 	}
 }
 
-static void a2xx_ctxt_restore(struct adreno_device *adreno_dev,
+static void a2xx_drawctxt_restore(struct adreno_device *adreno_dev,
 			struct adreno_context *context)
 {
 	struct kgsl_device *device = &adreno_dev->dev;
@@ -1495,21 +1538,27 @@
 		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
 			context->context_gmem_shadow.gmem_restore, 3);
 
-		/* Restore TP0_CHICKEN */
-		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
-			context->chicken_restore, 3);
+		if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
+			/* Restore TP0_CHICKEN */
+			adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+				context->chicken_restore, 3);
+		}
 
 		context->flags &= ~CTXT_FLAGS_GMEM_RESTORE;
 	}
 
-	/* restore registers and constants. */
-	adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
-		context->reg_restore, 3);
+	if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
 
-	/* restore shader instructions & partitioning. */
-	if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
+		/* restore registers and constants. */
 		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
-			context->shader_restore, 3);
+			context->reg_restore, 3);
+
+		/* restore shader instructions & partitioning. */
+		if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
+			adreno_ringbuffer_issuecmds(device,
+				KGSL_CMD_FLAGS_NONE,
+				context->shader_restore, 3);
+		}
 	}
 
 	if (adreno_is_a20x(adreno_dev)) {
@@ -1703,16 +1752,207 @@
 	wmb();
 }
 
+static void a2xx_rb_init(struct adreno_device *adreno_dev,
+			struct adreno_ringbuffer *rb)
+{
+	unsigned int *cmds, cmds_gpu;
+
+	/* ME_INIT */
+	cmds = adreno_ringbuffer_allocspace(rb, 19);
+	cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*(rb->wptr-19);
+
+	GSL_RB_WRITE(cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT, 18));
+	/* All fields present (bits 9:0) */
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x000003ff);
+	/* Disable/Enable Real-Time Stream processing (present but ignored) */
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+	/* Enable (2D <-> 3D) implicit synchronization (present but ignored) */
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+
+	GSL_RB_WRITE(cmds, cmds_gpu,
+		SUBBLOCK_OFFSET(REG_RB_SURFACE_INFO));
+	GSL_RB_WRITE(cmds, cmds_gpu,
+		SUBBLOCK_OFFSET(REG_PA_SC_WINDOW_OFFSET));
+	GSL_RB_WRITE(cmds, cmds_gpu,
+		SUBBLOCK_OFFSET(REG_VGT_MAX_VTX_INDX));
+	GSL_RB_WRITE(cmds, cmds_gpu,
+		SUBBLOCK_OFFSET(REG_SQ_PROGRAM_CNTL));
+	GSL_RB_WRITE(cmds, cmds_gpu,
+		SUBBLOCK_OFFSET(REG_RB_DEPTHCONTROL));
+	GSL_RB_WRITE(cmds, cmds_gpu,
+		SUBBLOCK_OFFSET(REG_PA_SU_POINT_SIZE));
+	GSL_RB_WRITE(cmds, cmds_gpu,
+		SUBBLOCK_OFFSET(REG_PA_SC_LINE_CNTL));
+	GSL_RB_WRITE(cmds, cmds_gpu,
+		SUBBLOCK_OFFSET(REG_PA_SU_POLY_OFFSET_FRONT_SCALE));
+
+	/* Instruction memory size: */
+	GSL_RB_WRITE(cmds, cmds_gpu,
+		(adreno_encode_istore_size(adreno_dev)
+		| adreno_dev->pix_shader_start));
+	/* Maximum Contexts */
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000001);
+	/* Write Confirm Interval and The CP will wait the
+	* wait_interval * 16 clocks between polling  */
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+
+	/* NQ and External Memory Swap */
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+	/* Protected mode error checking */
+	GSL_RB_WRITE(cmds, cmds_gpu, GSL_RB_PROTECTED_MODE_CONTROL);
+	/* Disable header dumping and Header dump address */
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+	/* Header dump size */
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+
+	adreno_ringbuffer_submit(rb);
+}
+
+static unsigned int a2xx_busy_cycles(struct adreno_device *adreno_dev)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+	unsigned int reg, val;
+
+	/* Freeze the counter */
+	adreno_regwrite(device, REG_CP_PERFMON_CNTL,
+		REG_PERF_MODE_CNT | REG_PERF_STATE_FREEZE);
+
+	/* Get the value */
+	adreno_regread(device, REG_RBBM_PERFCOUNTER1_LO, &val);
+
+	/* Reset the counter */
+	adreno_regwrite(device, REG_CP_PERFMON_CNTL,
+		REG_PERF_MODE_CNT | REG_PERF_STATE_RESET);
+
+	/* Re-Enable the performance monitors */
+	adreno_regread(device, REG_RBBM_PM_OVERRIDE2, &reg);
+	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, (reg | 0x40));
+	adreno_regwrite(device, REG_RBBM_PERFCOUNTER1_SELECT, 0x1);
+	adreno_regwrite(device, REG_CP_PERFMON_CNTL,
+		REG_PERF_MODE_CNT | REG_PERF_STATE_ENABLE);
+
+	return val;
+}
+
+static void a2xx_gmeminit(struct adreno_device *adreno_dev)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+	union reg_rb_edram_info rb_edram_info;
+	unsigned int gmem_size;
+	unsigned int edram_value = 0;
+
+	/* make sure edram range is aligned to size */
+	BUG_ON(adreno_dev->gmemspace.gpu_base &
+				(adreno_dev->gmemspace.sizebytes - 1));
+
+	/* get edram_size value equivalent */
+	gmem_size = (adreno_dev->gmemspace.sizebytes >> 14);
+	while (gmem_size >>= 1)
+		edram_value++;
+
+	rb_edram_info.val = 0;
+
+	rb_edram_info.f.edram_size = edram_value;
+	rb_edram_info.f.edram_mapping_mode = 0; /* EDRAM_MAP_UPPER */
+
+	/* must be aligned to size */
+	rb_edram_info.f.edram_range = (adreno_dev->gmemspace.gpu_base >> 14);
+
+	adreno_regwrite(device, REG_RB_EDRAM_INFO, rb_edram_info.val);
+}
+
+static void a2xx_start(struct adreno_device *adreno_dev)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+	int init_reftimestamp = 0x7fffffff;
+
+	/*
+	 * We need to make sure all blocks are powered up and clocked
+	 * before issuing a soft reset.  The overrides will then be
+	 * turned off (set to 0)
+	 */
+	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0xfffffffe);
+	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xffffffff);
+
+	/*
+	 * Only reset CP block if all blocks have previously been
+	 * reset
+	 */
+	if (!(device->flags & KGSL_FLAGS_SOFT_RESET) ||
+		!adreno_is_a22x(adreno_dev)) {
+		adreno_regwrite(device, REG_RBBM_SOFT_RESET,
+			0xFFFFFFFF);
+		device->flags |= KGSL_FLAGS_SOFT_RESET;
+	} else {
+		adreno_regwrite(device, REG_RBBM_SOFT_RESET,
+			0x00000001);
+	}
+	/*
+	 * The core is in an indeterminate state until the reset
+	 * completes after 30ms.
+	 */
+	msleep(30);
+
+	adreno_regwrite(device, REG_RBBM_SOFT_RESET, 0x00000000);
+
+	if (adreno_is_a225(adreno_dev)) {
+		/* Enable large instruction store for A225 */
+		adreno_regwrite(device, REG_SQ_FLOW_CONTROL,
+			0x18000000);
+	}
+
+	adreno_regwrite(device, REG_RBBM_CNTL, 0x00004442);
+
+	adreno_regwrite(device, REG_SQ_VS_PROGRAM, 0x00000000);
+	adreno_regwrite(device, REG_SQ_PS_PROGRAM, 0x00000000);
+
+	if (cpu_is_msm8960() || cpu_is_msm8930())
+		adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0x200);
+	else
+		adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0);
+
+	if (!adreno_is_a22x(adreno_dev))
+		adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0);
+	else
+		adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0x80);
+
+	kgsl_sharedmem_set(&device->memstore, 0, 0, device->memstore.size);
+
+	kgsl_sharedmem_writel(&device->memstore,
+			      KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts),
+			      init_reftimestamp);
+
+	adreno_regwrite(device, REG_RBBM_DEBUG, 0x00080000);
+
+	/* Make sure interrupts are disabled */
+	adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
+	adreno_regwrite(device, REG_CP_INT_CNTL, 0);
+	adreno_regwrite(device, REG_SQ_INT_CNTL, 0);
+
+	if (adreno_is_a22x(adreno_dev))
+		adreno_dev->gmemspace.sizebytes = SZ_512K;
+	else
+		adreno_dev->gmemspace.sizebytes = SZ_256K;
+
+	a2xx_gmeminit(adreno_dev);
+}
+
 /* Defined in adreno_a2xx_snapshot.c */
 void *a2xx_snapshot(struct adreno_device *adreno_dev, void *snapshot,
 	int *remain, int hang);
 
 struct adreno_gpudev adreno_a2xx_gpudev = {
-	.ctxt_gpustate_shadow = a2xx_ctxt_gpustate_shadow,
-	.ctxt_gmem_shadow = a2xx_ctxt_gmem_shadow,
-	.ctxt_save = a2xx_ctxt_save,
-	.ctxt_restore = a2xx_ctxt_restore,
+	.reg_rbbm_status = REG_RBBM_STATUS,
+	.reg_cp_pfp_ucode_addr = REG_CP_PFP_UCODE_ADDR,
+	.reg_cp_pfp_ucode_data = REG_CP_PFP_UCODE_DATA,
+
+	.ctxt_create = a2xx_drawctxt_create,
+	.ctxt_save = a2xx_drawctxt_save,
+	.ctxt_restore = a2xx_drawctxt_restore,
 	.irq_handler = a2xx_irq_handler,
 	.irq_control = a2xx_irq_control,
 	.snapshot = a2xx_snapshot,
+	.rb_init = a2xx_rb_init,
+	.busy_cycles = a2xx_busy_cycles,
+	.start = a2xx_start,
 };
diff --git a/drivers/gpu/msm/adreno_a2xx_snapshot.c b/drivers/gpu/msm/adreno_a2xx_snapshot.c
index 30d692b..091db22 100644
--- a/drivers/gpu/msm/adreno_a2xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a2xx_snapshot.c
@@ -224,24 +224,6 @@
 	return DEBUG_SECTION_SZ(MIUDEBUG_COUNT);
 }
 
-/* Helper function to snapshot a section of indexed registers */
-
-static void *a2xx_snapshot_indexed_registers(struct kgsl_device *device,
-		void *snapshot, int *remain,
-		unsigned int index, unsigned int data, unsigned int start,
-		unsigned int count)
-{
-	struct kgsl_snapshot_indexed_registers iregs;
-	iregs.index = index;
-	iregs.data = data;
-	iregs.start = start;
-	iregs.count = count;
-
-	return kgsl_snapshot_add_section(device,
-		 KGSL_SNAPSHOT_SECTION_INDEXED_REGS, snapshot,
-		 remain, kgsl_snapshot_dump_indexed_regs, &iregs);
-}
-
 /* A2XX GPU snapshot function - this is where all of the A2XX specific
  * bits and pieces are grabbed into the snapshot memory
  */
@@ -269,12 +251,12 @@
 		kgsl_snapshot_dump_regs, &regs);
 
 	/* CP_STATE_DEBUG indexed registers */
-	snapshot = a2xx_snapshot_indexed_registers(device, snapshot,
+	snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
 			remain, REG_CP_STATE_DEBUG_INDEX,
 			REG_CP_STATE_DEBUG_DATA, 0x0, 0x14);
 
 	/* CP_ME indexed registers */
-	snapshot = a2xx_snapshot_indexed_registers(device, snapshot,
+	snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
 			remain, REG_CP_ME_CNTL, REG_CP_ME_STATUS,
 			64, 44);
 
@@ -293,7 +275,7 @@
 
 	/* SU debug indexed registers (only for < 470) */
 	if (!adreno_is_a22x(adreno_dev))
-		snapshot = a2xx_snapshot_indexed_registers(device, snapshot,
+		snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
 				remain, REG_PA_SU_DEBUG_CNTL,
 				REG_PA_SU_DEBUG_DATA,
 				0, 0x1B);
@@ -304,26 +286,26 @@
 			a2xx_snapshot_cpdebug, NULL);
 
 	/* MH debug indexed registers */
-	snapshot = a2xx_snapshot_indexed_registers(device, snapshot,
+	snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
 			remain, MH_DEBUG_CTRL, MH_DEBUG_DATA, 0x0, 0x40);
 
 	/* Leia only register sets */
 	if (adreno_is_a22x(adreno_dev)) {
 		/* RB DEBUG indexed regisers */
-		snapshot = a2xx_snapshot_indexed_registers(device, snapshot,
+		snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
 			remain, REG_RB_DEBUG_CNTL, REG_RB_DEBUG_DATA, 0, 8);
 
 		/* RB DEBUG indexed registers bank 2 */
-		snapshot = a2xx_snapshot_indexed_registers(device, snapshot,
+		snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
 			remain, REG_RB_DEBUG_CNTL, REG_RB_DEBUG_DATA + 0x1000,
 			0, 8);
 
 		/* PC_DEBUG indexed registers */
-		snapshot = a2xx_snapshot_indexed_registers(device, snapshot,
+		snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
 			remain, REG_PC_DEBUG_CNTL, REG_PC_DEBUG_DATA, 0, 8);
 
 		/* GRAS_DEBUG indexed registers */
-		snapshot = a2xx_snapshot_indexed_registers(device, snapshot,
+		snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
 			remain, REG_GRAS_DEBUG_CNTL, REG_GRAS_DEBUG_DATA, 0, 4);
 
 		/* MIU debug registers */
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
new file mode 100644
index 0000000..1bad811
--- /dev/null
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -0,0 +1,2597 @@
+/* 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/delay.h>
+
+#include "kgsl.h"
+#include "adreno.h"
+#include "kgsl_sharedmem.h"
+#include "kgsl_cffdump.h"
+#include "a3xx_reg.h"
+
+/*
+ * Set of registers to dump for A3XX on postmortem and snapshot.
+ * Registers in pairs - first value is the start offset, second
+ * is the stop offset (inclusive)
+ */
+
+const unsigned int a3xx_registers[] = {
+	0x0000, 0x0002, 0x0010, 0x0012, 0x0018, 0x0018, 0x0020, 0x0027,
+	0x0029, 0x002b, 0x002e, 0x0033, 0x0040, 0x0042, 0x0050, 0x005c,
+	0x0060, 0x006c, 0x0080, 0x0082, 0x0084, 0x0088, 0x0090, 0x00e5,
+	0x00ea, 0x00ed, 0x0100, 0x0100, 0x0110, 0x0123, 0x01c0, 0x01c1,
+	0x01c3, 0x01c5, 0x01c7, 0x01c7, 0x01d5, 0x01d9, 0x01dc, 0x01dd,
+	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,
+	0x0612, 0x0614, 0x0c01, 0x0c02, 0x0c06, 0x0c1d, 0x0c3d, 0x0c3f,
+	0x0c48, 0x0c4b, 0x0c80, 0x0c80, 0x0c88, 0x0c8b, 0x0ca0, 0x0cb7,
+	0x0cc0, 0x0cc1, 0x0cc6, 0x0cc7, 0x0ce4, 0x0ce5, 0x0e00, 0x0e05,
+	0x0e0c, 0x0e0c, 0x0e22, 0x0e23, 0x0e41, 0x0e45, 0x0e64, 0x0e65,
+	0x0e80, 0x0e82, 0x0e84, 0x0e89, 0x0ea0, 0x0ea1, 0x0ea4, 0x0ea7,
+	0x0ec4, 0x0ecb, 0x0ee0, 0x0ee0, 0x0f00, 0x0f01, 0x0f03, 0x0f09,
+	0x2040, 0x2040, 0x2044, 0x2044, 0x2048, 0x204d, 0x2068, 0x2069,
+	0x206c, 0x206d, 0x2070, 0x2070, 0x2072, 0x2072, 0x2074, 0x2075,
+	0x2079, 0x207a, 0x20c0, 0x20d3, 0x20e4, 0x20ef, 0x2100, 0x2109,
+	0x210c, 0x210c, 0x210e, 0x210e, 0x2110, 0x2111, 0x2114, 0x2115,
+	0x21e4, 0x21e4, 0x21ea, 0x21ea, 0x21ec, 0x21ed, 0x21f0, 0x21f0,
+	0x2200, 0x2212, 0x2214, 0x2217, 0x221a, 0x221a, 0x2240, 0x227e,
+	0x2280, 0x228b, 0x22c0, 0x22c0, 0x22c4, 0x22ce, 0x22d0, 0x22d8,
+	0x22df, 0x22e6, 0x22e8, 0x22e9, 0x22ec, 0x22ec, 0x22f0, 0x22f7,
+	0x22ff, 0x22ff, 0x2340, 0x2343, 0x2348, 0x2349, 0x2350, 0x2356,
+	0x2360, 0x2360, 0x2440, 0x2440, 0x2444, 0x2444, 0x2448, 0x244d,
+	0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470, 0x2472, 0x2472,
+	0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3, 0x24e4, 0x24ef,
+	0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e, 0x2510, 0x2511,
+	0x2514, 0x2515, 0x25e4, 0x25e4, 0x25ea, 0x25ea, 0x25ec, 0x25ed,
+	0x25f0, 0x25f0, 0x2600, 0x2612, 0x2614, 0x2617, 0x261a, 0x261a,
+	0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0, 0x26c4, 0x26ce,
+	0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9, 0x26ec, 0x26ec,
+	0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743, 0x2748, 0x2749,
+	0x2750, 0x2756, 0x2760, 0x2760,
+};
+
+const unsigned int a3xx_registers_count = ARRAY_SIZE(a3xx_registers) / 2;
+
+/* Simple macro to facilitate bit setting in the gmem2sys and sys2gmem
+ * functions.
+ */
+
+#define _SET(_shift, _val) ((_val) << (_shift))
+
+/*
+ ****************************************************************************
+ *
+ * Context state shadow structure:
+ *
+ * +---------------------+------------+-------------+---------------------+---+
+ * | ALU Constant Shadow | Reg Shadow | C&V Buffers | Shader Instr Shadow |Tex|
+ * +---------------------+------------+-------------+---------------------+---+
+ *
+ *		 8K - ALU Constant Shadow (8K aligned)
+ *		 4K - H/W Register Shadow (8K aligned)
+ *		 5K - Command and Vertex Buffers
+ *		 8K - Shader Instruction Shadow
+ *		 ~6K - Texture Constant Shadow
+ *
+ *
+ ***************************************************************************
+ */
+
+/* Sizes of all sections in state shadow memory */
+#define ALU_SHADOW_SIZE      (8*1024) /* 8KB */
+#define REG_SHADOW_SIZE      (4*1024) /* 4KB */
+#define CMD_BUFFER_SIZE      (5*1024) /* 5KB */
+#define TEX_SIZE_MEM_OBJECTS 896      /* bytes */
+#define TEX_SIZE_MIPMAP      1936     /* bytes */
+#define TEX_SIZE_SAMPLER_OBJ 256      /* bytes */
+#define TEX_SHADOW_SIZE                            \
+	((TEX_SIZE_MEM_OBJECTS + TEX_SIZE_MIPMAP + \
+	TEX_SIZE_SAMPLER_OBJ)*2) /* ~6KB */
+#define SHADER_SHADOW_SIZE   (8*1024) /* 8KB */
+
+/* Total context size, excluding GMEM shadow */
+#define CONTEXT_SIZE                         \
+	(ALU_SHADOW_SIZE+REG_SHADOW_SIZE +   \
+	CMD_BUFFER_SIZE+SHADER_SHADOW_SIZE + \
+	TEX_SHADOW_SIZE)
+
+/* Offsets to different sections in context shadow memory */
+#define REG_OFFSET ALU_SHADOW_SIZE
+#define CMD_OFFSET (REG_OFFSET+REG_SHADOW_SIZE)
+#define SHADER_OFFSET (CMD_OFFSET+CMD_BUFFER_SIZE)
+#define TEX_OFFSET (SHADER_OFFSET+SHADER_SHADOW_SIZE)
+#define VS_TEX_OFFSET_MEM_OBJECTS TEX_OFFSET
+#define VS_TEX_OFFSET_MIPMAP (VS_TEX_OFFSET_MEM_OBJECTS+TEX_SIZE_MEM_OBJECTS)
+#define VS_TEX_OFFSET_SAMPLER_OBJ (VS_TEX_OFFSET_MIPMAP+TEX_SIZE_MIPMAP)
+#define FS_TEX_OFFSET_MEM_OBJECTS \
+	(VS_TEX_OFFSET_SAMPLER_OBJ+TEX_SIZE_SAMPLER_OBJ)
+#define FS_TEX_OFFSET_MIPMAP (FS_TEX_OFFSET_MEM_OBJECTS+TEX_SIZE_MEM_OBJECTS)
+#define FS_TEX_OFFSET_SAMPLER_OBJ (FS_TEX_OFFSET_MIPMAP+TEX_SIZE_MIPMAP)
+
+/* The offset for fragment shader data in HLSQ context */
+#define SSIZE (16*1024)
+
+#define HLSQ_SAMPLER_OFFSET 0x000
+#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
+
+#define BUILD_PC_DRAW_INITIATOR(prim_type, source_select, index_size, \
+	vis_cull_mode) \
+	(((prim_type)      << PC_DRAW_INITIATOR_PRIM_TYPE) | \
+	((source_select)   << PC_DRAW_INITIATOR_SOURCE_SELECT) | \
+	((index_size & 1)  << PC_DRAW_INITIATOR_INDEX_SIZE) | \
+	((index_size >> 1) << PC_DRAW_INITIATOR_SMALL_INDEX) | \
+	((vis_cull_mode)   << PC_DRAW_INITIATOR_VISIBILITY_CULLING_MODE) | \
+	(1                 << PC_DRAW_INITIATOR_PRE_DRAW_INITIATOR_ENABLE))
+
+/*
+ * List of context registers (starting from dword offset 0x2000).
+ * Each line contains start and end of a range of registers.
+ */
+static const unsigned int context_register_ranges[] = {
+	A3XX_GRAS_CL_CLIP_CNTL, A3XX_GRAS_CL_CLIP_CNTL,
+	A3XX_GRAS_CL_GB_CLIP_ADJ, A3XX_GRAS_CL_GB_CLIP_ADJ,
+	A3XX_GRAS_CL_VPORT_XOFFSET, A3XX_GRAS_CL_VPORT_ZSCALE,
+	A3XX_GRAS_SU_POINT_MINMAX, A3XX_GRAS_SU_POINT_SIZE,
+	A3XX_GRAS_SU_POLY_OFFSET_SCALE, A3XX_GRAS_SU_POLY_OFFSET_OFFSET,
+	A3XX_GRAS_SU_MODE_CONTROL, A3XX_GRAS_SU_MODE_CONTROL,
+	A3XX_GRAS_SC_CONTROL, A3XX_GRAS_SC_CONTROL,
+	A3XX_GRAS_SC_SCREEN_SCISSOR_TL, A3XX_GRAS_SC_SCREEN_SCISSOR_BR,
+	A3XX_GRAS_SC_WINDOW_SCISSOR_TL, A3XX_GRAS_SC_WINDOW_SCISSOR_BR,
+	A3XX_RB_MODE_CONTROL, A3XX_RB_MRT_BLEND_CONTROL3,
+	A3XX_RB_BLEND_RED, A3XX_RB_COPY_DEST_INFO,
+	A3XX_RB_DEPTH_CONTROL, A3XX_RB_DEPTH_CONTROL,
+	A3XX_PC_VSTREAM_CONTROL, A3XX_PC_VSTREAM_CONTROL,
+	A3XX_PC_VERTEX_REUSE_BLOCK_CNTL, A3XX_PC_VERTEX_REUSE_BLOCK_CNTL,
+	A3XX_PC_PRIM_VTX_CNTL, A3XX_PC_RESTART_INDEX,
+	A3XX_HLSQ_CONTROL_0_REG, A3XX_HLSQ_CONST_FSPRESV_RANGE_REG,
+	A3XX_HLSQ_CL_NDRANGE_0_REG, A3XX_HLSQ_CL_NDRANGE_0_REG,
+	A3XX_HLSQ_CL_NDRANGE_2_REG, A3XX_HLSQ_CL_CONTROL_1_REG,
+	A3XX_HLSQ_CL_KERNEL_CONST_REG, A3XX_HLSQ_CL_KERNEL_GROUP_Z_REG,
+	A3XX_HLSQ_CL_WG_OFFSET_REG, A3XX_HLSQ_CL_WG_OFFSET_REG,
+	A3XX_VFD_CONTROL_0, A3XX_VFD_VS_THREADING_THRESHOLD,
+	A3XX_SP_SP_CTRL_REG, A3XX_SP_SP_CTRL_REG,
+	A3XX_SP_VS_CTRL_REG0, A3XX_SP_VS_OUT_REG_7,
+	A3XX_SP_VS_VPC_DST_REG_0, A3XX_SP_VS_PVT_MEM_SIZE_REG,
+	A3XX_SP_VS_LENGTH_REG, A3XX_SP_FS_PVT_MEM_SIZE_REG,
+	A3XX_SP_FS_FLAT_SHAD_MODE_REG_0, A3XX_SP_FS_FLAT_SHAD_MODE_REG_1,
+	A3XX_SP_FS_OUTPUT_REG, A3XX_SP_FS_OUTPUT_REG,
+	A3XX_SP_FS_MRT_REG_0, A3XX_SP_FS_IMAGE_OUTPUT_REG_3,
+	A3XX_SP_FS_LENGTH_REG, A3XX_SP_FS_LENGTH_REG,
+	A3XX_TPL1_TP_VS_TEX_OFFSET, A3XX_TPL1_TP_FS_BORDER_COLOR_BASE_ADDR,
+	A3XX_VPC_ATTR, A3XX_VPC_VARY_CYLWRAP_ENABLE_1,
+};
+
+/* Global registers that need to be saved separately */
+static const unsigned int global_registers[] = {
+	A3XX_GRAS_CL_USER_PLANE_X0, A3XX_GRAS_CL_USER_PLANE_Y0,
+	A3XX_GRAS_CL_USER_PLANE_Z0, A3XX_GRAS_CL_USER_PLANE_W0,
+	A3XX_GRAS_CL_USER_PLANE_X1, A3XX_GRAS_CL_USER_PLANE_Y1,
+	A3XX_GRAS_CL_USER_PLANE_Z1, A3XX_GRAS_CL_USER_PLANE_W1,
+	A3XX_GRAS_CL_USER_PLANE_X2, A3XX_GRAS_CL_USER_PLANE_Y2,
+	A3XX_GRAS_CL_USER_PLANE_Z2, A3XX_GRAS_CL_USER_PLANE_W2,
+	A3XX_GRAS_CL_USER_PLANE_X3, A3XX_GRAS_CL_USER_PLANE_Y3,
+	A3XX_GRAS_CL_USER_PLANE_Z3, A3XX_GRAS_CL_USER_PLANE_W3,
+	A3XX_GRAS_CL_USER_PLANE_X4, A3XX_GRAS_CL_USER_PLANE_Y4,
+	A3XX_GRAS_CL_USER_PLANE_Z4, A3XX_GRAS_CL_USER_PLANE_W4,
+	A3XX_GRAS_CL_USER_PLANE_X5, A3XX_GRAS_CL_USER_PLANE_Y5,
+	A3XX_GRAS_CL_USER_PLANE_Z5, A3XX_GRAS_CL_USER_PLANE_W5,
+	A3XX_VSC_BIN_SIZE,
+	A3XX_VSC_PIPE_CONFIG_0, A3XX_VSC_PIPE_CONFIG_1,
+	A3XX_VSC_PIPE_CONFIG_2, A3XX_VSC_PIPE_CONFIG_3,
+	A3XX_VSC_PIPE_CONFIG_4, A3XX_VSC_PIPE_CONFIG_5,
+	A3XX_VSC_PIPE_CONFIG_6, A3XX_VSC_PIPE_CONFIG_7,
+	A3XX_VSC_PIPE_DATA_ADDRESS_0, A3XX_VSC_PIPE_DATA_ADDRESS_1,
+	A3XX_VSC_PIPE_DATA_ADDRESS_2, A3XX_VSC_PIPE_DATA_ADDRESS_3,
+	A3XX_VSC_PIPE_DATA_ADDRESS_4, A3XX_VSC_PIPE_DATA_ADDRESS_5,
+	A3XX_VSC_PIPE_DATA_ADDRESS_6, A3XX_VSC_PIPE_DATA_ADDRESS_7,
+	A3XX_VSC_PIPE_DATA_LENGTH_0, A3XX_VSC_PIPE_DATA_LENGTH_1,
+	A3XX_VSC_PIPE_DATA_LENGTH_2, A3XX_VSC_PIPE_DATA_LENGTH_3,
+	A3XX_VSC_PIPE_DATA_LENGTH_4, A3XX_VSC_PIPE_DATA_LENGTH_5,
+	A3XX_VSC_PIPE_DATA_LENGTH_6, A3XX_VSC_PIPE_DATA_LENGTH_7,
+	A3XX_VSC_SIZE_ADDRESS
+};
+
+#define GLOBAL_REGISTER_COUNT ARRAY_SIZE(global_registers)
+
+/* A scratchpad used to build commands during context create */
+static struct tmp_ctx {
+	unsigned int *cmd; /* Next available dword in C&V buffer */
+
+	/* Addresses in comamnd buffer where registers are saved */
+	uint32_t reg_values[GLOBAL_REGISTER_COUNT];
+	uint32_t gmem_base; /* Base GPU address of GMEM */
+} tmp_ctx;
+
+#ifndef GSL_CONTEXT_SWITCH_CPU_SYNC
+/*
+ * Function for executing dest = ( (reg & and) ROL rol ) | or
+ */
+static unsigned int *rmw_regtomem(unsigned int *cmd,
+				  unsigned int reg, unsigned int and,
+				  unsigned int rol, unsigned int or,
+				  unsigned int dest)
+{
+	/* CP_SCRATCH_REG2 = (CP_SCRATCH_REG2 & 0x00000000) | reg */
+	*cmd++ = cp_type3_packet(CP_REG_RMW, 3);
+	*cmd++ = (1 << 30) | A3XX_CP_SCRATCH_REG2;
+	*cmd++ = 0x00000000;	/* AND value */
+	*cmd++ = reg;		/* OR address */
+
+	/* CP_SCRATCH_REG2 = ( (CP_SCRATCH_REG2 & and) ROL rol ) |  or */
+	*cmd++ = cp_type3_packet(CP_REG_RMW, 3);
+	*cmd++ = (rol << 24) | A3XX_CP_SCRATCH_REG2;
+	*cmd++ = and;		/* AND value */
+	*cmd++ = or;		/* OR value */
+
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ = A3XX_CP_SCRATCH_REG2;
+	*cmd++ = dest;
+
+	return cmd;
+}
+#endif
+
+static void build_regconstantsave_cmds(struct adreno_device *adreno_dev,
+				       struct adreno_context *drawctxt)
+{
+	unsigned int *cmd = tmp_ctx.cmd;
+	unsigned int *start = cmd;
+	unsigned int i;
+
+	drawctxt->constant_save_commands[0].hostptr = cmd;
+	drawctxt->constant_save_commands[0].gpuaddr =
+	    virt2gpu(cmd, &drawctxt->gpustate);
+	cmd++;
+
+	*cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+	*cmd++ = 0;
+
+#ifndef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
+	/*
+	 * Context registers are already shadowed; just need to
+	 * disable shadowing to prevent corruption.
+	 */
+
+	*cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
+	*cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
+	*cmd++ = 4 << 16;	/* regs, start=0 */
+	*cmd++ = 0x0;		/* count = 0 */
+
+#else
+	/*
+	 * Make sure the HW context has the correct register values before
+	 * reading them.
+	 */
+
+	/* Write context registers into shadow */
+	for (i = 0; i < ARRAY_SIZE(context_register_ranges) / 2; i++) {
+		unsigned int start = context_register_ranges[i * 2];
+		unsigned int end = context_register_ranges[i * 2 + 1];
+		*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+		*cmd++ = ((end - start + 1) << REG_TO_MEM_LOOP_COUNT_SHIFT) |
+			start;
+		*cmd++ = ((drawctxt->gpustate.gpuaddr + REG_OFFSET)
+			  & 0xFFFFE000) + (start - 0x2000) * 4;
+	}
+#endif
+
+	/* Need to handle some of the global registers separately */
+	for (i = 0; i < ARRAY_SIZE(global_registers); i++) {
+		*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+		*cmd++ = global_registers[i];
+		*cmd++ = tmp_ctx.reg_values[i];
+	}
+
+	/* Save vertex shader constants */
+	*cmd++ = cp_type3_packet(CP_COND_EXEC, 4);
+	*cmd++ = drawctxt->cond_execs[2].gpuaddr >> 2;
+	*cmd++ = drawctxt->cond_execs[2].gpuaddr >> 2;
+	*cmd++ = 0x0000FFFF;
+	*cmd++ = 3; /* EXEC_COUNT */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	drawctxt->constant_save_commands[1].hostptr = cmd;
+	drawctxt->constant_save_commands[1].gpuaddr =
+	    virt2gpu(cmd, &drawctxt->gpustate);
+	/*
+	   From fixup:
+
+	   dwords = SP_VS_CTRL_REG1.VSCONSTLENGTH / 4
+	   src = (HLSQ_SHADOW_BASE + 0x2000) / 4
+
+	   From register spec:
+	   SP_VS_CTRL_REG1.VSCONSTLENGTH [09:00]: 0-512, unit = 128bits.
+	 */
+	*cmd++ = 0;	/* (dwords << REG_TO_MEM_LOOP_COUNT_SHIFT) | src  */
+	/* ALU constant shadow base */
+	*cmd++ = drawctxt->gpustate.gpuaddr & 0xfffffffc;
+
+	/* Save fragment shader constants */
+	*cmd++ = cp_type3_packet(CP_COND_EXEC, 4);
+	*cmd++ = drawctxt->cond_execs[3].gpuaddr >> 2;
+	*cmd++ = drawctxt->cond_execs[3].gpuaddr >> 2;
+	*cmd++ = 0x0000FFFF;
+	*cmd++ = 3; /* EXEC_COUNT */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	drawctxt->constant_save_commands[2].hostptr = cmd;
+	drawctxt->constant_save_commands[2].gpuaddr =
+	    virt2gpu(cmd, &drawctxt->gpustate);
+	/*
+	   From fixup:
+
+	   dwords = SP_FS_CTRL_REG1.FSCONSTLENGTH / 4
+	   src = (HLSQ_SHADOW_BASE + 0x2000 + SSIZE) / 4
+
+	   From register spec:
+	   SP_FS_CTRL_REG1.FSCONSTLENGTH [09:00]: 0-512, unit = 128bits.
+	 */
+	*cmd++ = 0;	/* (dwords << REG_TO_MEM_LOOP_COUNT_SHIFT) | src  */
+
+	/*
+	   From fixup:
+
+	   base = drawctxt->gpustate.gpuaddr (ALU constant shadow base)
+	   offset = SP_FS_OBJ_OFFSET_REG.CONSTOBJECTSTARTOFFSET
+
+	   From register spec:
+	   SP_FS_OBJ_OFFSET_REG.CONSTOBJECTSTARTOFFSET [16:24]: Constant object
+	   start offset in on chip RAM,
+	   128bit aligned
+
+	   dst = base + offset
+	   Because of the base alignment we can use
+	   dst = base | offset
+	 */
+	*cmd++ = 0;		/* dst */
+
+	/* Save VS texture memory objects */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ =
+	    ((TEX_SIZE_MEM_OBJECTS / 4) << REG_TO_MEM_LOOP_COUNT_SHIFT) |
+		((HLSQ_SHADOW_BASE + HLSQ_MEMOBJ_OFFSET) / 4);
+	*cmd++ =
+	    (drawctxt->gpustate.gpuaddr +
+	     VS_TEX_OFFSET_MEM_OBJECTS) & 0xfffffffc;
+
+	/* Save VS texture mipmap pointers */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ =
+	    ((TEX_SIZE_MIPMAP / 4) << REG_TO_MEM_LOOP_COUNT_SHIFT) |
+		((HLSQ_SHADOW_BASE + HLSQ_MIPMAP_OFFSET) / 4);
+	*cmd++ =
+	    (drawctxt->gpustate.gpuaddr + VS_TEX_OFFSET_MIPMAP) & 0xfffffffc;
+
+	/* Save VS texture sampler objects */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ = ((TEX_SIZE_SAMPLER_OBJ / 4) << REG_TO_MEM_LOOP_COUNT_SHIFT) |
+		((HLSQ_SHADOW_BASE + HLSQ_SAMPLER_OFFSET) / 4);
+	*cmd++ =
+	    (drawctxt->gpustate.gpuaddr +
+	     VS_TEX_OFFSET_SAMPLER_OBJ) & 0xfffffffc;
+
+	/* Save FS texture memory objects */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ =
+	    ((TEX_SIZE_MEM_OBJECTS / 4) << REG_TO_MEM_LOOP_COUNT_SHIFT) |
+		((HLSQ_SHADOW_BASE + HLSQ_MEMOBJ_OFFSET + SSIZE) / 4);
+	*cmd++ =
+	    (drawctxt->gpustate.gpuaddr +
+	     FS_TEX_OFFSET_MEM_OBJECTS) & 0xfffffffc;
+
+	/* Save FS texture mipmap pointers */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ =
+	    ((TEX_SIZE_MIPMAP / 4) << REG_TO_MEM_LOOP_COUNT_SHIFT) |
+		((HLSQ_SHADOW_BASE + HLSQ_MIPMAP_OFFSET + SSIZE) / 4);
+	*cmd++ =
+	    (drawctxt->gpustate.gpuaddr + FS_TEX_OFFSET_MIPMAP) & 0xfffffffc;
+
+	/* Save FS texture sampler objects */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ =
+	    ((TEX_SIZE_SAMPLER_OBJ / 4) << REG_TO_MEM_LOOP_COUNT_SHIFT) |
+		((HLSQ_SHADOW_BASE + HLSQ_SAMPLER_OFFSET + SSIZE) / 4);
+	*cmd++ =
+	    (drawctxt->gpustate.gpuaddr +
+	     FS_TEX_OFFSET_SAMPLER_OBJ) & 0xfffffffc;
+
+	/* Create indirect buffer command for above command sequence */
+	create_ib1(drawctxt, drawctxt->regconstant_save, start, cmd);
+
+	tmp_ctx.cmd = cmd;
+}
+
+/* Copy GMEM contents to system memory shadow. */
+static unsigned int *build_gmem2sys_cmds(struct adreno_device *adreno_dev,
+					 struct adreno_context *drawctxt,
+					 struct gmem_shadow_t *shadow)
+{
+	unsigned int *cmds = tmp_ctx.cmd;
+	unsigned int *start = cmds;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_RB_MODE_CONTROL);
+
+	/* RB_MODE_CONTROL */
+	*cmds++ = _SET(RB_MODECONTROL_RENDER_MODE, RB_RESOLVE_PASS) |
+		_SET(RB_MODECONTROL_MARB_CACHE_SPLIT_MODE, 1) |
+		_SET(RB_MODECONTROL_PACKER_TIMER_ENABLE, 1);
+	/* RB_RENDER_CONTROL */
+	*cmds++ = _SET(RB_RENDERCONTROL_BIN_WIDTH, shadow->width >> 5) |
+		_SET(RB_RENDERCONTROL_DISABLE_COLOR_PIPE, 1);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
+	*cmds++ = CP_REG(A3XX_RB_COPY_CONTROL);
+	/* RB_COPY_CONTROL */
+	*cmds++ = _SET(RB_COPYCONTROL_RESOLVE_CLEAR_MODE,
+		RB_CLEAR_MODE_RESOLVE) |
+		_SET(RB_COPYCONTROL_COPY_GMEM_BASE,
+		tmp_ctx.gmem_base >> 14);
+	/* RB_COPY_DEST_BASE */
+	*cmds++ = _SET(RB_COPYDESTBASE_COPY_DEST_BASE,
+		shadow->gmemshadow.gpuaddr >> 5);
+	/* RB_COPY_DEST_PITCH */
+	*cmds++ = _SET(RB_COPYDESTPITCH_COPY_DEST_PITCH,
+		(shadow->pitch * 4) / 32);
+	/* RB_COPY_DEST_INFO */
+	*cmds++ = _SET(RB_COPYDESTINFO_COPY_DEST_TILE,
+		RB_TILINGMODE_LINEAR) |
+		_SET(RB_COPYDESTINFO_COPY_DEST_FORMAT, RB_R8G8B8A8_UNORM) |
+		_SET(RB_COPYDESTINFO_COPY_COMPONENT_ENABLE, 0X0F) |
+		_SET(RB_COPYDESTINFO_COPY_DEST_ENDIAN, RB_ENDIAN_NONE);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_GRAS_SC_CONTROL);
+	/* GRAS_SC_CONTROL */
+	*cmds++ = _SET(GRAS_SC_CONTROL_RENDER_MODE, 2);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_VFD_CONTROL_0);
+	/* VFD_CONTROL_0 */
+	*cmds++ = _SET(VFD_CTRLREG0_TOTALATTRTOVS, 4) |
+		_SET(VFD_CTRLREG0_PACKETSIZE, 2) |
+		_SET(VFD_CTRLREG0_STRMDECINSTRCNT, 1) |
+		_SET(VFD_CTRLREG0_STRMFETCHINSTRCNT, 1);
+	/* VFD_CONTROL_1 */
+	*cmds++ = _SET(VFD_CTRLREG1_MAXSTORAGE, 1) |
+		_SET(VFD_CTRLREG1_REGID4VTX,  252) |
+		_SET(VFD_CTRLREG1_REGID4INST,  252);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_VFD_FETCH_INSTR_0_0);
+	/* VFD_FETCH_INSTR_0_0 */
+	*cmds++ = _SET(VFD_FETCHINSTRUCTIONS_FETCHSIZE, 11) |
+		_SET(VFD_FETCHINSTRUCTIONS_BUFSTRIDE, 12) |
+		_SET(VFD_FETCHINSTRUCTIONS_STEPRATE, 1);
+	/* VFD_FETCH_INSTR_1_0 */
+	*cmds++ = _SET(VFD_BASEADDR_BASEADDR,
+		shadow->quad_vertices.gpuaddr);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_VFD_DECODE_INSTR_0);
+	/* VFD_DECODE_INSTR_0 */
+	*cmds++ = _SET(VFD_DECODEINSTRUCTIONS_WRITEMASK, 0x0F) |
+		_SET(VFD_DECODEINSTRUCTIONS_CONSTFILL, 1) |
+		_SET(VFD_DECODEINSTRUCTIONS_FORMAT, 2) |
+		_SET(VFD_DECODEINSTRUCTIONS_REGID, 5) |
+		_SET(VFD_DECODEINSTRUCTIONS_SHIFTCNT, 12) |
+		_SET(VFD_DECODEINSTRUCTIONS_LASTCOMPVALID, 1);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
+	*cmds++ = CP_REG(A3XX_HLSQ_CONTROL_0_REG);
+	/* HLSQ_CONTROL_0_REG */
+	*cmds++ = _SET(HLSQ_CTRL0REG_FSTHREADSIZE, HLSQ_TWO_PIX_QUADS) |
+		_SET(HLSQ_CTRL0REG_FSSUPERTHREADENABLE, 1) |
+		_SET(HLSQ_CTRL0REG_SPSHADERRESTART, 1) |
+		_SET(HLSQ_CTRL0REG_RESERVED2, 1) |
+		_SET(HLSQ_CTRL0REG_CHUNKDISABLE, 1) |
+		_SET(HLSQ_CTRL0REG_CONSTSWITCHMODE, 1) |
+		_SET(HLSQ_CTRL0REG_LAZYUPDATEDISABLE, 1) |
+		_SET(HLSQ_CTRL0REG_SPCONSTFULLUPDATE, 1) |
+		_SET(HLSQ_CTRL0REG_TPFULLUPDATE, 1);
+	/* HLSQ_CONTROL_1_REG */
+	*cmds++ = _SET(HLSQ_CTRL1REG_VSTHREADSIZE, HLSQ_TWO_VTX_QUADS) |
+		_SET(HLSQ_CTRL1REG_VSSUPERTHREADENABLE, 1) |
+		_SET(HLSQ_CTRL1REG_RESERVED1, 4);
+	/* HLSQ_CONTROL_2_REG */
+	*cmds++ = _SET(HLSQ_CTRL2REG_PRIMALLOCTHRESHOLD, 31);
+	/* HLSQ_CONTROL_3_REG */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
+	*cmds++ = CP_REG(A3XX_HLSQ_VS_CONTROL_REG);
+	/* HLSQ_VS_CONTROL_REG */
+	*cmds++ = _SET(HLSQ_VSCTRLREG_VSINSTRLENGTH, 1);
+	/* HLSQ_FS_CONTROL_REG */
+	*cmds++ = _SET(HLSQ_FSCTRLREG_FSCONSTLENGTH, 1) |
+		_SET(HLSQ_FSCTRLREG_FSCONSTSTARTOFFSET, 272) |
+		_SET(HLSQ_FSCTRLREG_FSINSTRLENGTH, 1);
+	/* HLSQ_CONST_VSPRESV_RANGE_REG */
+	*cmds++ = 0x00000000;
+	/* HLSQ_CONST_FSPRESV_RANGE_REQ */
+	*cmds++ = _SET(HLSQ_CONSTFSPRESERVEDRANGEREG_STARTENTRY, 32) |
+		_SET(HLSQ_CONSTFSPRESERVEDRANGEREG_ENDENTRY, 32);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_SP_FS_LENGTH_REG);
+	/* SP_FS_LENGTH_REG */
+	*cmds++ = _SET(SP_SHADERLENGTH_LEN, 1);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_SP_SP_CTRL_REG);
+	/* SP_SP_CTRL_REG */
+	*cmds++ = _SET(SP_SPCTRLREG_CONSTMODE, 1) |
+		_SET(SP_SPCTRLREG_SLEEPMODE, 1);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 12);
+	*cmds++ = CP_REG(A3XX_SP_VS_CTRL_REG0);
+	/* SP_VS_CTRL_REG0 */
+	*cmds++ = _SET(SP_VSCTRLREG0_VSTHREADMODE, SP_MULTI) |
+		_SET(SP_VSCTRLREG0_VSINSTRBUFFERMODE, SP_BUFFER_MODE) |
+		_SET(SP_VSCTRLREG0_VSICACHEINVALID, 1) |
+		_SET(SP_VSCTRLREG0_VSFULLREGFOOTPRINT, 3) |
+		_SET(SP_VSCTRLREG0_VSTHREADSIZE, SP_TWO_VTX_QUADS) |
+		_SET(SP_VSCTRLREG0_VSSUPERTHREADMODE, 1) |
+		_SET(SP_VSCTRLREG0_VSLENGTH, 1);
+	/* SP_VS_CTRL_REG1 */
+	*cmds++ = _SET(SP_VSCTRLREG1_VSINITIALOUTSTANDING, 4);
+	/* SP_VS_PARAM_REG */
+	*cmds++ = _SET(SP_VSPARAMREG_POSREGID, 1) |
+		_SET(SP_VSPARAMREG_PSIZEREGID, 252);
+	/* SP_VS_OUT_REG_0 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OUT_REG_1 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OUT_REG_2 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OUT_REG_3 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OUT_REG_4 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OUT_REG_5 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OUT_REG_6 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OUT_REG_7 */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 7);
+	*cmds++ = CP_REG(A3XX_SP_VS_VPC_DST_REG_0);
+	/* SP_VS_VPC_DST_REG_0 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_VPC_DST_REG_1 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_VPC_DST_REG_2 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_VPC_DST_REG_3 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OBJ_OFFSET_REG */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OBJ_START_REG */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 6);
+	*cmds++ = CP_REG(A3XX_SP_VS_LENGTH_REG);
+	/* SP_VS_LENGTH_REG */
+	*cmds++ = _SET(SP_SHADERLENGTH_LEN, 1);
+	/* SP_FS_CTRL_REG0 */
+	*cmds++ = _SET(SP_FSCTRLREG0_FSTHREADMODE, SP_MULTI) |
+		_SET(SP_FSCTRLREG0_FSINSTRBUFFERMODE, SP_BUFFER_MODE) |
+		_SET(SP_FSCTRLREG0_FSICACHEINVALID, 1) |
+		_SET(SP_FSCTRLREG0_FSFULLREGFOOTPRINT, 2) |
+		_SET(SP_FSCTRLREG0_FSINOUTREGOVERLAP, 1) |
+		_SET(SP_FSCTRLREG0_FSTHREADSIZE, SP_TWO_VTX_QUADS) |
+		_SET(SP_FSCTRLREG0_FSSUPERTHREADMODE, 1) |
+		_SET(SP_FSCTRLREG0_FSLENGTH, 1);
+	/* SP_FS_CTRL_REG1 */
+	*cmds++ = _SET(SP_FSCTRLREG1_FSCONSTLENGTH, 1) |
+		_SET(SP_FSCTRLREG1_FSINITIALOUTSTANDING, 2) |
+		_SET(SP_FSCTRLREG1_HALFPRECVAROFFSET, 63);
+	/* SP_FS_OBJ_OFFSET_REG */
+	*cmds++ = _SET(SP_OBJOFFSETREG_CONSTOBJECTSTARTOFFSET, 272) |
+		_SET(SP_OBJOFFSETREG_SHADEROBJOFFSETINIC, 1);
+	/* SP_FS_OBJ_START_REG */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_SP_FS_FLAT_SHAD_MODE_REG_0);
+	/* SP_FS_FLAT_SHAD_MODE_REG_0 */
+	*cmds++ = 0x00000000;
+	/* SP_FS_FLAT_SHAD_MODE_REG_1 */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_SP_FS_OUTPUT_REG);
+	/* SP_FS_OUTPUT_REG */
+	*cmds++ = _SET(SP_IMAGEOUTPUTREG_PAD0, SP_PIXEL_BASED);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
+	*cmds++ = CP_REG(A3XX_SP_FS_MRT_REG_0);
+	/* SP_FS_MRT_REG_0 */
+	*cmds++ = _SET(SP_FSMRTREG_REGID, 1);
+	/* SP_FS_MRT_REG_1 */
+	*cmds++ = 0x00000000;
+	/* SP_FS_MRT_REG_2 */
+	*cmds++ = 0x00000000;
+	/* SP_FS_MRT_REG_3 */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 11);
+	*cmds++ = CP_REG(A3XX_VPC_ATTR);
+	/* VPC_ATTR */
+	*cmds++ = _SET(VPC_VPCATTR_THRHDASSIGN, 1) |
+		_SET(VPC_VPCATTR_LMSIZE, 1);
+	/* VPC_PACK */
+	*cmds++ = 0x00000000;
+	/* VPC_VARRYING_INTERUPT_MODE_0 */
+	*cmds++ = 0x00000000;
+	/* VPC_VARRYING_INTERUPT_MODE_1 */
+	*cmds++ = 0x00000000;
+	/* VPC_VARRYING_INTERUPT_MODE_2 */
+	*cmds++ = 0x00000000;
+	/* VPC_VARRYING_INTERUPT_MODE_3 */
+	*cmds++ = 0x00000000;
+	/* VPC_VARYING_PS_REPL_MODE_0 */
+	*cmds++ = 0x00000000;
+	/* VPC_VARYING_PS_REPL_MODE_1 */
+	*cmds++ = 0x00000000;
+	/* VPC_VARYING_PS_REPL_MODE_2 */
+	*cmds++ = 0x00000000;
+	/* VPC_VARYING_PS_REPL_MODE_3 */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_LOAD_STATE, 10);
+	*cmds++ = (0 << CP_LOADSTATE_DSTOFFSET_SHIFT)
+		| (HLSQ_DIRECT << CP_LOADSTATE_STATESRC_SHIFT)
+		| (HLSQ_BLOCK_ID_SP_VS << CP_LOADSTATE_STATEBLOCKID_SHIFT)
+		| (1 << CP_LOADSTATE_NUMOFUNITS_SHIFT);
+	*cmds++ = (HLSQ_SP_VS_INSTR << CP_LOADSTATE_STATETYPE_SHIFT)
+		| (0 << CP_LOADSTATE_EXTSRCADDR_SHIFT);
+
+	/* (sy)(rpt3)mov.f32f32 r0.y, (r)r1.y; */
+	*cmds++ = 0x00000005; *cmds++ = 0x30044b01;
+	/* end; */
+	*cmds++ = 0x00000000; *cmds++ = 0x03000000;
+	/* nop; */
+	*cmds++ = 0x00000000; *cmds++ = 0x00000000;
+	/* nop; */
+	*cmds++ = 0x00000000; *cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_LOAD_STATE, 10);
+	*cmds++ = (0 << CP_LOADSTATE_DSTOFFSET_SHIFT)
+		| (HLSQ_DIRECT << CP_LOADSTATE_STATESRC_SHIFT)
+		| (HLSQ_BLOCK_ID_SP_FS << CP_LOADSTATE_STATEBLOCKID_SHIFT)
+		| (1 << CP_LOADSTATE_NUMOFUNITS_SHIFT);
+	*cmds++ = (HLSQ_SP_FS_INSTR << CP_LOADSTATE_STATETYPE_SHIFT)
+		| (0 << CP_LOADSTATE_EXTSRCADDR_SHIFT);
+
+	/* (sy)(rpt3)mov.f32f32 r0.y, (r)c0.x; */
+	*cmds++ = 0x00000000; *cmds++ = 0x30244b01;
+	/* end; */
+	*cmds++ = 0x00000000; *cmds++ = 0x03000000;
+	/* nop; */
+	*cmds++ = 0x00000000; *cmds++ = 0x00000000;
+	/* nop; */
+	*cmds++ = 0x00000000; *cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_RB_MSAA_CONTROL);
+	/* RB_MSAA_CONTROL */
+	*cmds++ = _SET(RB_MSAACONTROL_MSAA_DISABLE, 1) |
+		_SET(RB_MSAACONTROL_SAMPLE_MASK, 0xFFFF);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_RB_DEPTH_CONTROL);
+	/* RB_DEPTH_CONTROL */
+	*cmds++ = _SET(RB_DEPTHCONTROL_Z_TEST_FUNC, RB_FRAG_NEVER);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_RB_MRT_CONTROL0);
+	/* RB_MRT_CONTROL0 */
+	*cmds++ = _SET(RB_MRTCONTROL_READ_DEST_ENABLE, 1) |
+		_SET(RB_MRTCONTROL_ROP_CODE, 12) |
+		_SET(RB_MRTCONTROL_DITHER_MODE, RB_DITHER_ALWAYS) |
+		_SET(RB_MRTCONTROL_COMPONENT_ENABLE, 0xF);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_RB_MRT_BLEND_CONTROL0);
+	/* RB_MRT_BLEND_CONTROL0 */
+	*cmds++ = _SET(RB_MRTBLENDCONTROL_RGB_SRC_FACTOR, RB_FACTOR_ONE) |
+		_SET(RB_MRTBLENDCONTROL_RGB_BLEND_OPCODE, RB_BLEND_OP_ADD) |
+		_SET(RB_MRTBLENDCONTROL_RGB_DEST_FACTOR, RB_FACTOR_ZERO) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_SRC_FACTOR, RB_FACTOR_ONE) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_DEST_FACTOR, RB_FACTOR_ZERO) |
+		_SET(RB_MRTBLENDCONTROL_CLAMP_ENABLE, 1);
+	/* RB_MRT_CONTROL1 */
+	*cmds++ = _SET(RB_MRTCONTROL_READ_DEST_ENABLE, 1) |
+		_SET(RB_MRTCONTROL_DITHER_MODE, RB_DITHER_DISABLE) |
+		_SET(RB_MRTCONTROL_COMPONENT_ENABLE, 0xF);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_RB_MRT_BLEND_CONTROL1);
+	/* RB_MRT_BLEND_CONTROL1 */
+	*cmds++ = _SET(RB_MRTBLENDCONTROL_RGB_SRC_FACTOR, RB_FACTOR_ONE) |
+		_SET(RB_MRTBLENDCONTROL_RGB_BLEND_OPCODE, RB_BLEND_OP_ADD) |
+		_SET(RB_MRTBLENDCONTROL_RGB_DEST_FACTOR, RB_FACTOR_ZERO) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_SRC_FACTOR, RB_FACTOR_ONE) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_DEST_FACTOR, RB_FACTOR_ZERO) |
+		_SET(RB_MRTBLENDCONTROL_CLAMP_ENABLE, 1);
+	/* RB_MRT_CONTROL2 */
+	*cmds++ = _SET(RB_MRTCONTROL_READ_DEST_ENABLE, 1) |
+		_SET(RB_MRTCONTROL_DITHER_MODE, RB_DITHER_DISABLE) |
+		_SET(RB_MRTCONTROL_COMPONENT_ENABLE, 0xF);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_RB_MRT_BLEND_CONTROL2);
+	/* RB_MRT_BLEND_CONTROL2 */
+	*cmds++ = _SET(RB_MRTBLENDCONTROL_RGB_SRC_FACTOR, RB_FACTOR_ONE) |
+		_SET(RB_MRTBLENDCONTROL_RGB_BLEND_OPCODE, RB_BLEND_OP_ADD) |
+		_SET(RB_MRTBLENDCONTROL_RGB_DEST_FACTOR, RB_FACTOR_ZERO) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_SRC_FACTOR, RB_FACTOR_ONE) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_DEST_FACTOR, RB_FACTOR_ZERO) |
+		_SET(RB_MRTBLENDCONTROL_CLAMP_ENABLE, 1);
+	/* RB_MRT_CONTROL3 */
+	*cmds++ = _SET(RB_MRTCONTROL_READ_DEST_ENABLE, 1) |
+		_SET(RB_MRTCONTROL_DITHER_MODE, RB_DITHER_DISABLE) |
+		_SET(RB_MRTCONTROL_COMPONENT_ENABLE, 0xF);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_RB_MRT_BLEND_CONTROL3);
+	/* RB_MRT_BLEND_CONTROL3 */
+	*cmds++ = _SET(RB_MRTBLENDCONTROL_RGB_SRC_FACTOR, RB_FACTOR_ONE) |
+		_SET(RB_MRTBLENDCONTROL_RGB_BLEND_OPCODE, RB_BLEND_OP_ADD) |
+		_SET(RB_MRTBLENDCONTROL_RGB_DEST_FACTOR, RB_FACTOR_ZERO) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_SRC_FACTOR, RB_FACTOR_ONE) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_DEST_FACTOR, RB_FACTOR_ZERO) |
+		_SET(RB_MRTBLENDCONTROL_CLAMP_ENABLE, 1);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
+	*cmds++ = CP_REG(A3XX_VFD_INDEX_MIN);
+	/* VFD_INDEX_MIN */
+	*cmds++ = 0x00000000;
+	/* VFD_INDEX_MAX */
+	*cmds++ = 0xFFFFFFFF;
+	/* VFD_INSTANCEID_OFFSET */
+	*cmds++ = 0x00000000;
+	/* VFD_INDEX_OFFSET */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_VFD_VS_THREADING_THRESHOLD);
+	/* VFD_VS_THREADING_THRESHOLD */
+	*cmds++ = _SET(VFD_THREADINGTHRESHOLD_RESERVED6, 12) |
+		_SET(VFD_THREADINGTHRESHOLD_REGID_VTXCNT, 252);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_TPL1_TP_VS_TEX_OFFSET);
+	/* TPL1_TP_VS_TEX_OFFSET */
+	*cmds++ = 0;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_TPL1_TP_FS_TEX_OFFSET);
+	/* TPL1_TP_FS_TEX_OFFSET */
+	*cmds++ = _SET(TPL1_TPTEXOFFSETREG_SAMPLEROFFSET, 16) |
+		_SET(TPL1_TPTEXOFFSETREG_MEMOBJOFFSET, 16) |
+		_SET(TPL1_TPTEXOFFSETREG_BASETABLEPTR, 224);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_PC_PRIM_VTX_CNTL);
+	/* PC_PRIM_VTX_CNTL */
+	*cmds++ = _SET(PC_PRIM_VTX_CONTROL_POLYMODE_FRONT_PTYPE,
+		PC_DRAW_TRIANGLES) |
+		_SET(PC_PRIM_VTX_CONTROL_POLYMODE_BACK_PTYPE,
+		PC_DRAW_TRIANGLES) |
+		_SET(PC_PRIM_VTX_CONTROL_PROVOKING_VTX_LAST, 1);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_GRAS_SC_WINDOW_SCISSOR_TL);
+	/* GRAS_SC_WINDOW_SCISSOR_TL */
+	*cmds++ = 0x00000000;
+	/* GRAS_SC_WINDOW_SCISSOR_BR */
+	*cmds++ = _SET(GRAS_SC_WINDOW_SCISSOR_BR_BR_X, shadow->width - 1) |
+		_SET(GRAS_SC_WINDOW_SCISSOR_BR_BR_Y, shadow->height - 1);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_GRAS_SC_SCREEN_SCISSOR_TL);
+	/* GRAS_SC_SCREEN_SCISSOR_TL */
+	*cmds++ = 0x00000000;
+	/* GRAS_SC_SCREEN_SCISSOR_BR */
+	*cmds++ = _SET(GRAS_SC_SCREEN_SCISSOR_BR_BR_X, shadow->width - 1) |
+		_SET(GRAS_SC_SCREEN_SCISSOR_BR_BR_Y, shadow->height - 1);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
+	*cmds++ = CP_REG(A3XX_GRAS_CL_VPORT_XOFFSET);
+	/* GRAS_CL_VPORT_XOFFSET */
+	*cmds++ = 0x00000000;
+	/* GRAS_CL_VPORT_XSCALE */
+	*cmds++ = _SET(GRAS_CL_VPORT_XSCALE_VPORT_XSCALE, 0x3f800000);
+	/* GRAS_CL_VPORT_YOFFSET */
+	*cmds++ = 0x00000000;
+	/* GRAS_CL_VPORT_YSCALE */
+	*cmds++ = _SET(GRAS_CL_VPORT_YSCALE_VPORT_YSCALE, 0x3f800000);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_GRAS_CL_VPORT_ZOFFSET);
+	/* GRAS_CL_VPORT_ZOFFSET */
+	*cmds++ = 0x00000000;
+	/* GRAS_CL_VPORT_ZSCALE */
+	*cmds++ = _SET(GRAS_CL_VPORT_ZSCALE_VPORT_ZSCALE, 0x3f800000);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_GRAS_CL_CLIP_CNTL);
+	/* GRAS_CL_CLIP_CNTL */
+	*cmds++ = _SET(GRAS_CL_CLIP_CNTL_CLIP_DISABLE, 1) |
+		_SET(GRAS_CL_CLIP_CNTL_ZFAR_CLIP_DISABLE, 1) |
+		_SET(GRAS_CL_CLIP_CNTL_VP_CLIP_CODE_IGNORE, 1) |
+		_SET(GRAS_CL_CLIP_CNTL_VP_XFORM_DISABLE, 1) |
+		_SET(GRAS_CL_CLIP_CNTL_PERSP_DIVISION_DISABLE, 1);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_GRAS_CL_GB_CLIP_ADJ);
+	/* GRAS_CL_GB_CLIP_ADJ */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+	*cmds++ = 0x00000000;
+
+	/*
+	 * Resolve using two draw calls with a dummy register
+	 * write in between. This is a HLM workaround
+	 * that should be removed later.
+	 */
+	*cmds++ = cp_type3_packet(CP_DRAW_INDX_2, 6);
+	*cmds++ = 0x00000000; /* Viz query info */
+	*cmds++ = BUILD_PC_DRAW_INITIATOR(PC_DI_PT_TRILIST,
+					  PC_DI_SRC_SEL_IMMEDIATE,
+					  PC_DI_INDEX_SIZE_32_BIT,
+					  PC_DI_IGNORE_VISIBILITY);
+	*cmds++ = 0x00000003; /* Num indices */
+	*cmds++ = 0x00000000; /* Index 0 */
+	*cmds++ = 0x00000001; /* Index 1 */
+	*cmds++ = 0x00000002; /* Index 2 */
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_HLSQ_CL_CONTROL_0_REG);
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_DRAW_INDX_2, 6);
+	*cmds++ = 0x00000000; /* Viz query info */
+	*cmds++ = BUILD_PC_DRAW_INITIATOR(PC_DI_PT_TRILIST,
+					  PC_DI_SRC_SEL_IMMEDIATE,
+					  PC_DI_INDEX_SIZE_32_BIT,
+					  PC_DI_IGNORE_VISIBILITY);
+	*cmds++ = 0x00000003; /* Num indices */
+	*cmds++ = 0x00000002; /* Index 0 */
+	*cmds++ = 0x00000001; /* Index 1 */
+	*cmds++ = 0x00000003; /* Index 2 */
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_HLSQ_CL_CONTROL_0_REG);
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+	*cmds++ = 0x00000000;
+
+	/* Create indirect buffer command for above command sequence */
+	create_ib1(drawctxt, shadow->gmem_save, start, cmds);
+
+	return cmds;
+}
+
+static void build_shader_save_cmds(struct adreno_device *adreno_dev,
+				   struct adreno_context *drawctxt)
+{
+	unsigned int *cmd = tmp_ctx.cmd;
+	unsigned int *start;
+
+	/* Reserve space for boolean values used for COND_EXEC packet */
+	drawctxt->cond_execs[0].hostptr = cmd;
+	drawctxt->cond_execs[0].gpuaddr = virt2gpu(cmd, &drawctxt->gpustate);
+	*cmd++ = 0;
+	drawctxt->cond_execs[1].hostptr = cmd;
+	drawctxt->cond_execs[1].gpuaddr = virt2gpu(cmd, &drawctxt->gpustate);
+	*cmd++ = 0;
+
+	drawctxt->shader_save_commands[0].hostptr = cmd;
+	drawctxt->shader_save_commands[0].gpuaddr =
+	    virt2gpu(cmd, &drawctxt->gpustate);
+	*cmd++ = 0;
+	drawctxt->shader_save_commands[1].hostptr = cmd;
+	drawctxt->shader_save_commands[1].gpuaddr =
+	    virt2gpu(cmd, &drawctxt->gpustate);
+	*cmd++ = 0;
+
+	start = cmd;
+
+	/* Save vertex shader */
+
+	*cmd++ = cp_type3_packet(CP_COND_EXEC, 4);
+	*cmd++ = drawctxt->cond_execs[0].gpuaddr >> 2;
+	*cmd++ = drawctxt->cond_execs[0].gpuaddr >> 2;
+	*cmd++ = 0x0000FFFF;
+	*cmd++ = 3;		/* EXEC_COUNT */
+
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	drawctxt->shader_save_commands[2].hostptr = cmd;
+	drawctxt->shader_save_commands[2].gpuaddr =
+	    virt2gpu(cmd, &drawctxt->gpustate);
+	/*
+	   From fixup:
+
+	   dwords = SP_VS_CTRL_REG0.VS_LENGTH * 8
+
+	   From regspec:
+	   SP_VS_CTRL_REG0.VS_LENGTH [31:24]: VS length, unit = 256bits.
+	   If bit31 is 1, it means overflow
+	   or any long shader.
+
+	   src = (HLSQ_SHADOW_BASE + 0x1000)/4
+	 */
+	*cmd++ = 0;	/*(dwords << REG_TO_MEM_LOOP_COUNT_SHIFT) | src */
+	*cmd++ = (drawctxt->gpustate.gpuaddr + SHADER_OFFSET) & 0xfffffffc;
+
+	/* Save fragment shader */
+	*cmd++ = cp_type3_packet(CP_COND_EXEC, 4);
+	*cmd++ = drawctxt->cond_execs[1].gpuaddr >> 2;
+	*cmd++ = drawctxt->cond_execs[1].gpuaddr >> 2;
+	*cmd++ = 0x0000FFFF;
+	*cmd++ = 3;		/* EXEC_COUNT */
+
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	drawctxt->shader_save_commands[3].hostptr = cmd;
+	drawctxt->shader_save_commands[3].gpuaddr =
+	    virt2gpu(cmd, &drawctxt->gpustate);
+	/*
+	   From fixup:
+
+	   dwords = SP_FS_CTRL_REG0.FS_LENGTH * 8
+
+	   From regspec:
+	   SP_FS_CTRL_REG0.FS_LENGTH [31:24]: FS length, unit = 256bits.
+	   If bit31 is 1, it means overflow
+	   or any long shader.
+
+	   fs_offset = SP_FS_OBJ_OFFSET_REG.SHADEROBJOFFSETINIC * 32
+	   From regspec:
+
+	   SP_FS_OBJ_OFFSET_REG.SHADEROBJOFFSETINIC [31:25]:
+	   First instruction of the whole shader will be stored from
+	   the offset in instruction cache, unit = 256bits, a cache line.
+	   It can start from 0 if no VS available.
+
+	   src = (HLSQ_SHADOW_BASE + 0x1000 + SSIZE + fs_offset)/4
+	 */
+	*cmd++ = 0;	/*(dwords << REG_TO_MEM_LOOP_COUNT_SHIFT) | src */
+	*cmd++ = (drawctxt->gpustate.gpuaddr + SHADER_OFFSET
+		  + (SHADER_SHADOW_SIZE / 2)) & 0xfffffffc;
+
+	/* Create indirect buffer command for above command sequence */
+	create_ib1(drawctxt, drawctxt->shader_save, start, cmd);
+
+	tmp_ctx.cmd = cmd;
+}
+
+/*
+ * Make an IB to modify context save IBs with the correct shader instruction
+ * and constant sizes and offsets.
+ */
+
+static void build_save_fixup_cmds(struct adreno_device *adreno_dev,
+				  struct adreno_context *drawctxt)
+{
+	unsigned int *cmd = tmp_ctx.cmd;
+	unsigned int *start = cmd;
+
+	/* Flush HLSQ lazy updates */
+	*cmd++ = cp_type3_packet(CP_EVENT_WRITE, 1);
+	*cmd++ = 0x7;		/* HLSQ_FLUSH */
+	*cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+	*cmd++ = 0;
+
+	*cmd++ = cp_type0_packet(A3XX_UCHE_CACHE_INVALIDATE0_REG, 2);
+	*cmd++ = 0x00000000; /* No start addr for full invalidate */
+	*cmd++ = (unsigned int)
+		UCHE_ENTIRE_CACHE << UCHE_INVALIDATE1REG_ALLORPORTION |
+		UCHE_OP_INVALIDATE << UCHE_INVALIDATE1REG_OPCODE |
+		0; /* No end addr for full invalidate */
+
+	/* Make sure registers are flushed */
+	*cmd++ = cp_type3_packet(CP_CONTEXT_UPDATE, 1);
+	*cmd++ = 0;
+
+#ifdef GSL_CONTEXT_SWITCH_CPU_SYNC
+
+	/* Save shader sizes */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ = A3XX_SP_VS_CTRL_REG0;
+	*cmd++ = drawctxt->shader_save_commands[2].gpuaddr;
+
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ = A3XX_SP_FS_CTRL_REG0;
+	*cmd++ = drawctxt->shader_save_commands[3].gpuaddr;
+
+	/* Save shader offsets */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ = A3XX_SP_FS_OBJ_OFFSET_REG;
+	*cmd++ = drawctxt->shader_save_commands[1].gpuaddr;
+
+	/* Save constant sizes */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ = A3XX_SP_VS_CTRL_REG1;
+	*cmd++ = drawctxt->constant_save_commands[1].gpuaddr;
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ = A3XX_SP_FS_CTRL_REG1;
+	*cmd++ = drawctxt->constant_save_commands[2].gpuaddr;
+
+	/* Save FS constant offset */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ = A3XX_SP_FS_OBJ_OFFSET_REG;
+	*cmd++ = drawctxt->constant_save_commands[0].gpuaddr;
+
+
+	/* Save VS instruction store mode */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ = A3XX_SP_VS_CTRL_REG0;
+	*cmd++ = drawctxt->cond_execs[0].gpuaddr;
+
+	/* Save FS instruction store mode */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ = A3XX_SP_FS_CTRL_REG0;
+	*cmd++ = drawctxt->cond_execs[1].gpuaddr;
+#else
+
+	/* Shader save */
+	cmd = rmw_regtomem(cmd, A3XX_SP_VS_CTRL_REG0, 0x7f000000,
+			11+REG_TO_MEM_LOOP_COUNT_SHIFT,
+			(HLSQ_SHADOW_BASE + 0x1000) / 4,
+			drawctxt->shader_save_commands[2].gpuaddr);
+
+	/* CP_SCRATCH_REG2 = (CP_SCRATCH_REG2 & 0x00000000) | SP_FS_CTRL_REG0 */
+	*cmd++ = cp_type3_packet(CP_REG_RMW, 3);
+	*cmd++ = (1 << 30) | A3XX_CP_SCRATCH_REG2;
+	*cmd++ = 0x00000000;	/* AND value */
+	*cmd++ = A3XX_SP_FS_CTRL_REG0;	/* OR address */
+	/* CP_SCRATCH_REG2 = ( (CP_SCRATCH_REG2 & 0x7f000000) >> 21 )
+	   |  ((HLSQ_SHADOW_BASE+0x1000+SSIZE)/4) */
+	*cmd++ = cp_type3_packet(CP_REG_RMW, 3);
+	*cmd++ = ((11 + REG_TO_MEM_LOOP_COUNT_SHIFT) << 24) |
+		A3XX_CP_SCRATCH_REG2;
+	*cmd++ = 0x7f000000;	/* AND value */
+	*cmd++ = (HLSQ_SHADOW_BASE + 0x1000 + SSIZE) / 4;	/* OR value */
+
+	/*
+	 * CP_SCRATCH_REG3 = (CP_SCRATCH_REG3 & 0x00000000) |
+	 * SP_FS_OBJ_OFFSET_REG
+	 */
+
+	*cmd++ = cp_type3_packet(CP_REG_RMW, 3);
+	*cmd++ = (1 << 30) | A3XX_CP_SCRATCH_REG3;
+	*cmd++ = 0x00000000;	/* AND value */
+	*cmd++ = A3XX_SP_FS_OBJ_OFFSET_REG;	/* OR address */
+	/*
+	 * CP_SCRATCH_REG3 = ( (CP_SCRATCH_REG3 & 0xfe000000) >> 25 ) |
+	 * 0x00000000
+	 */
+	*cmd++ = cp_type3_packet(CP_REG_RMW, 3);
+	*cmd++ = A3XX_CP_SCRATCH_REG3;
+	*cmd++ = 0xfe000000;	/* AND value */
+	*cmd++ = 0x00000000;	/* OR value */
+	/*
+	 * CP_SCRATCH_REG2 =  (CP_SCRATCH_REG2 & 0xffffffff) | CP_SCRATCH_REG3
+	 */
+	*cmd++ = cp_type3_packet(CP_REG_RMW, 3);
+	*cmd++ = (1 << 30) | A3XX_CP_SCRATCH_REG2;
+	*cmd++ = 0xffffffff;	/* AND value */
+	*cmd++ = A3XX_CP_SCRATCH_REG3;	/* OR address */
+
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ = A3XX_CP_SCRATCH_REG2;
+	*cmd++ = drawctxt->shader_save_commands[3].gpuaddr;
+
+	/* Constant save */
+	cmd = rmw_regtomem(cmd, A3XX_SP_VS_CTRL_REG1, 0x000003ff,
+			   17, (HLSQ_SHADOW_BASE + 0x2000) / 4,
+			   drawctxt->constant_save_commands[1].gpuaddr);
+
+	cmd = rmw_regtomem(cmd, A3XX_SP_FS_CTRL_REG1, 0x000003ff,
+			   17, (HLSQ_SHADOW_BASE + 0x2000 + SSIZE) / 4,
+			   drawctxt->constant_save_commands[2].gpuaddr);
+
+	cmd = rmw_regtomem(cmd, A3XX_SP_FS_OBJ_OFFSET_REG, 0x00ff0000,
+			   18, drawctxt->gpustate.gpuaddr & 0xfffffe00,
+			   drawctxt->constant_save_commands[2].gpuaddr
+			   + sizeof(unsigned int));
+
+	/* Modify constant save conditionals */
+	cmd = rmw_regtomem(cmd, A3XX_SP_VS_CTRL_REG1, 0x000003ff,
+		0, 0, drawctxt->cond_execs[2].gpuaddr);
+
+	cmd = rmw_regtomem(cmd, A3XX_SP_FS_CTRL_REG1, 0x000003ff,
+		0, 0, drawctxt->cond_execs[3].gpuaddr);
+
+	/* Save VS instruction store mode */
+
+	cmd = rmw_regtomem(cmd, A3XX_SP_VS_CTRL_REG0, 0x00000002,
+			   31, 0, drawctxt->cond_execs[0].gpuaddr);
+
+	/* Save FS instruction store mode */
+	cmd = rmw_regtomem(cmd, A3XX_SP_FS_CTRL_REG0, 0x00000002,
+			   31, 0, drawctxt->cond_execs[1].gpuaddr);
+
+#endif
+
+	create_ib1(drawctxt, drawctxt->save_fixup, start, cmd);
+
+	tmp_ctx.cmd = cmd;
+}
+
+/****************************************************************************/
+/* Functions to build context restore IBs                                   */
+/****************************************************************************/
+
+static unsigned int *build_sys2gmem_cmds(struct adreno_device *adreno_dev,
+					 struct adreno_context *drawctxt,
+					 struct gmem_shadow_t *shadow)
+{
+	unsigned int *cmds = tmp_ctx.cmd;
+	unsigned int *start = cmds;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
+	*cmds++ = CP_REG(A3XX_HLSQ_CONTROL_0_REG);
+	/* HLSQ_CONTROL_0_REG */
+	*cmds++ = _SET(HLSQ_CTRL0REG_FSTHREADSIZE, HLSQ_FOUR_PIX_QUADS) |
+		_SET(HLSQ_CTRL0REG_SPSHADERRESTART, 1) |
+		_SET(HLSQ_CTRL0REG_CHUNKDISABLE, 1) |
+		_SET(HLSQ_CTRL0REG_SPCONSTFULLUPDATE, 1) |
+		_SET(HLSQ_CTRL0REG_TPFULLUPDATE, 1);
+	/* HLSQ_CONTROL_1_REG */
+	*cmds++ = _SET(HLSQ_CTRL1REG_VSTHREADSIZE, HLSQ_TWO_VTX_QUADS);
+	/* HLSQ_CONTROL_2_REG */
+	*cmds++ = _SET(HLSQ_CTRL2REG_PRIMALLOCTHRESHOLD, 31);
+	/* HLSQ_CONTROL3_REG */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_RB_MRT_BUF_INFO0);
+	/* RB_MRT_BUF_INFO0 */
+	*cmds++ = _SET(RB_MRTBUFINFO_COLOR_FORMAT, RB_R8G8B8A8_UNORM) |
+		_SET(RB_MRTBUFINFO_COLOR_TILE_MODE, RB_TILINGMODE_32X32) |
+		_SET(RB_MRTBUFINFO_COLOR_BUF_PITCH,
+		(shadow->gmem_pitch * 4 * 8) / 256);
+	/* RB_MRT_BUF_BASE0 */
+	*cmds++ = _SET(RB_MRTBUFBASE_COLOR_BUF_BASE, tmp_ctx.gmem_base >> 5);
+
+	/* Texture samplers */
+	*cmds++ = cp_type3_packet(CP_LOAD_STATE, 4);
+	*cmds++ = (16 << CP_LOADSTATE_DSTOFFSET_SHIFT)
+		| (HLSQ_DIRECT << CP_LOADSTATE_STATESRC_SHIFT)
+		| (HLSQ_BLOCK_ID_TP_TEX << CP_LOADSTATE_STATEBLOCKID_SHIFT)
+		| (1 << CP_LOADSTATE_NUMOFUNITS_SHIFT);
+	*cmds++ = (HLSQ_TP_TEX_SAMPLERS << CP_LOADSTATE_STATETYPE_SHIFT)
+		| (0 << CP_LOADSTATE_EXTSRCADDR_SHIFT);
+	*cmds++ = 0x00000240;
+	*cmds++ = 0x00000000;
+
+	/* Texture memobjs */
+	*cmds++ = cp_type3_packet(CP_LOAD_STATE, 6);
+	*cmds++ = (16 << CP_LOADSTATE_DSTOFFSET_SHIFT)
+		| (HLSQ_DIRECT << CP_LOADSTATE_STATESRC_SHIFT)
+		| (HLSQ_BLOCK_ID_TP_TEX << CP_LOADSTATE_STATEBLOCKID_SHIFT)
+		| (1 << CP_LOADSTATE_NUMOFUNITS_SHIFT);
+	*cmds++ = (HLSQ_TP_TEX_MEMOBJ << CP_LOADSTATE_STATETYPE_SHIFT)
+		| (0 << CP_LOADSTATE_EXTSRCADDR_SHIFT);
+	*cmds++ = 0x4cc06880;
+	*cmds++ = shadow->height | (shadow->width << 14);
+	*cmds++ = (shadow->pitch*4*8) << 9;
+	*cmds++ = 0x00000000;
+
+	/* Mipmap bases */
+	*cmds++ = cp_type3_packet(CP_LOAD_STATE, 16);
+	*cmds++ = (224 << CP_LOADSTATE_DSTOFFSET_SHIFT)
+		| (HLSQ_DIRECT << CP_LOADSTATE_STATESRC_SHIFT)
+		| (HLSQ_BLOCK_ID_TP_MIPMAP << CP_LOADSTATE_STATEBLOCKID_SHIFT)
+		| (14 << CP_LOADSTATE_NUMOFUNITS_SHIFT);
+	*cmds++ = (HLSQ_TP_MIPMAP_BASE << CP_LOADSTATE_STATETYPE_SHIFT)
+		| (0 << CP_LOADSTATE_EXTSRCADDR_SHIFT);
+	*cmds++ = shadow->gmemshadow.gpuaddr;
+	*cmds++ = 0x00000000;
+	*cmds++ = 0x00000000;
+	*cmds++ = 0x00000000;
+	*cmds++ = 0x00000000;
+	*cmds++ = 0x00000000;
+	*cmds++ = 0x00000000;
+	*cmds++ = 0x00000000;
+	*cmds++ = 0x00000000;
+	*cmds++ = 0x00000000;
+	*cmds++ = 0x00000000;
+	*cmds++ = 0x00000000;
+	*cmds++ = 0x00000000;
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
+	*cmds++ = CP_REG(A3XX_HLSQ_VS_CONTROL_REG);
+	/* HLSQ_VS_CONTROL_REG */
+	*cmds++ = _SET(HLSQ_VSCTRLREG_VSINSTRLENGTH, 1);
+	/* HLSQ_FS_CONTROL_REG */
+	*cmds++ = _SET(HLSQ_FSCTRLREG_FSCONSTLENGTH, 1) |
+		_SET(HLSQ_FSCTRLREG_FSCONSTSTARTOFFSET, 128) |
+		_SET(HLSQ_FSCTRLREG_FSINSTRLENGTH, 2);
+	/* HLSQ_CONST_VSPRESV_RANGE_REG */
+	*cmds++ = 0x00000000;
+	/* HLSQ_CONST_FSPRESV_RANGE_REG */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_SP_FS_LENGTH_REG);
+	/* SP_FS_LENGTH_REG */
+	*cmds++ = _SET(SP_SHADERLENGTH_LEN, 2);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 12);
+	*cmds++ = CP_REG(A3XX_SP_VS_CTRL_REG0);
+	/* SP_VS_CTRL_REG0 */
+	*cmds++ = _SET(SP_VSCTRLREG0_VSTHREADMODE, SP_MULTI) |
+		_SET(SP_VSCTRLREG0_VSINSTRBUFFERMODE, SP_BUFFER_MODE) |
+		_SET(SP_VSCTRLREG0_VSICACHEINVALID, 1) |
+		_SET(SP_VSCTRLREG0_VSFULLREGFOOTPRINT, 2) |
+		_SET(SP_VSCTRLREG0_VSTHREADSIZE, SP_TWO_VTX_QUADS) |
+		_SET(SP_VSCTRLREG0_VSLENGTH, 1);
+	/* SP_VS_CTRL_REG1 */
+	*cmds++ = _SET(SP_VSCTRLREG1_VSINITIALOUTSTANDING, 8);
+	/* SP_VS_PARAM_REG */
+	*cmds++ = _SET(SP_VSPARAMREG_POSREGID, 4) |
+		_SET(SP_VSPARAMREG_PSIZEREGID, 252) |
+		_SET(SP_VSPARAMREG_TOTALVSOUTVAR, 1);
+	/* SP_VS_OUT_REG0 */
+	*cmds++ = _SET(SP_VSOUTREG_COMPMASK0, 3);
+	/* SP_VS_OUT_REG1 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OUT_REG2 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OUT_REG3 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OUT_REG4 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OUT_REG5 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OUT_REG6 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OUT_REG7 */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 7);
+	*cmds++ = CP_REG(A3XX_SP_VS_VPC_DST_REG_0);
+	/* SP_VS_VPC_DST_REG0 */
+	*cmds++ = _SET(SP_VSVPCDSTREG_OUTLOC0, 8);
+	/* SP_VS_VPC_DST_REG1 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_VPC_DST_REG2 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_VPC_DST_REG3 */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OBJ_OFFSET_REG */
+	*cmds++ = 0x00000000;
+	/* SP_VS_OBJ_START_REG */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 6);
+	*cmds++ = CP_REG(A3XX_SP_VS_LENGTH_REG);
+	/* SP_VS_LENGTH_REG */
+	*cmds++ = _SET(SP_SHADERLENGTH_LEN, 1);
+	/* SP_FS_CTRL_REG0 */
+	*cmds++ = _SET(SP_FSCTRLREG0_FSTHREADMODE, SP_MULTI) |
+		_SET(SP_FSCTRLREG0_FSINSTRBUFFERMODE, SP_BUFFER_MODE) |
+		_SET(SP_FSCTRLREG0_FSICACHEINVALID, 1) |
+		_SET(SP_FSCTRLREG0_FSFULLREGFOOTPRINT, 2) |
+		_SET(SP_FSCTRLREG0_FSINOUTREGOVERLAP, 1) |
+		_SET(SP_FSCTRLREG0_FSTHREADSIZE, SP_FOUR_PIX_QUADS) |
+		_SET(SP_FSCTRLREG0_PIXLODENABLE, 1) |
+		_SET(SP_FSCTRLREG0_FSLENGTH, 2);
+	/* SP_FS_CTRL_REG1 */
+	*cmds++ = _SET(SP_FSCTRLREG1_FSCONSTLENGTH, 1) |
+		_SET(SP_FSCTRLREG1_FSINITIALOUTSTANDING, 2) |
+		_SET(SP_FSCTRLREG1_HALFPRECVAROFFSET, 63);
+	/* SP_FS_OBJ_OFFSET_REG */
+	*cmds++ = _SET(SP_OBJOFFSETREG_CONSTOBJECTSTARTOFFSET, 128);
+	/* SP_FS_OBJ_START_REG */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_SP_FS_FLAT_SHAD_MODE_REG_0);
+	/* SP_FS_FLAT_SHAD_MODE_REG0 */
+	*cmds++ = 0x00000000;
+	/* SP_FS_FLAT_SHAD_MODE_REG1 */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_SP_FS_OUTPUT_REG);
+	/* SP_FS_OUT_REG */
+	*cmds++ = _SET(SP_FSOUTREG_PAD0, SP_PIXEL_BASED);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_SP_FS_MRT_REG_0);
+	/* SP_FS_MRT_REG0 */
+	*cmds++ = _SET(SP_FSMRTREG_REGID, 4);
+	/* SP_FS_MRT_REG1 */
+	*cmds++ = 0;
+	/* SP_FS_MRT_REG2 */
+	*cmds++ = 0;
+	/* SP_FS_MRT_REG3 */
+	*cmds++ = 0;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 11);
+	*cmds++ = CP_REG(A3XX_VPC_ATTR);
+	/* VPC_ATTR */
+	*cmds++ = _SET(VPC_VPCATTR_TOTALATTR, 2) |
+		_SET(VPC_VPCATTR_THRHDASSIGN, 1) |
+		_SET(VPC_VPCATTR_LMSIZE, 1);
+	/* VPC_PACK */
+	*cmds++ = _SET(VPC_VPCPACK_NUMFPNONPOSVAR, 2) |
+		_SET(VPC_VPCPACK_NUMNONPOSVSVAR, 2);
+	/* VPC_VARYING_INTERP_MODE_0 */
+	*cmds++ = 0x00000000;
+	/* VPC_VARYING_INTERP_MODE1 */
+	*cmds++ = 0x00000000;
+	/* VPC_VARYING_INTERP_MODE2 */
+	*cmds++ = 0x00000000;
+	/* VPC_VARYING_IINTERP_MODE3 */
+	*cmds++ = 0x00000000;
+	/* VPC_VARRYING_PS_REPL_MODE_0 */
+	*cmds++ = _SET(VPC_VPCVARPSREPLMODE_COMPONENT08, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT09, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0A,	1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0B, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0C, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0D, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0E, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0F, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT10, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT11, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT12, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT13, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT14, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT15, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT16, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT17, 2);
+	/* VPC_VARRYING_PS_REPL_MODE_1 */
+	*cmds++ = _SET(VPC_VPCVARPSREPLMODE_COMPONENT08, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT09, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0A,	1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0B, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0C, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0D, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0E, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0F, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT10, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT11, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT12, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT13, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT14, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT15, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT16, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT17, 2);
+	/* VPC_VARRYING_PS_REPL_MODE_2 */
+	*cmds++ = _SET(VPC_VPCVARPSREPLMODE_COMPONENT08, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT09, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0A,	1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0B, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0C, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0D, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0E, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0F, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT10, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT11, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT12, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT13, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT14, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT15, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT16, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT17, 2);
+	/* VPC_VARRYING_PS_REPL_MODE_3 */
+	*cmds++ = _SET(VPC_VPCVARPSREPLMODE_COMPONENT08, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT09, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0A,	1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0B, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0C, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0D, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0E, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT0F, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT10, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT11, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT12, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT13, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT14, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT15, 2) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT16, 1) |
+		_SET(VPC_VPCVARPSREPLMODE_COMPONENT17, 2);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 11);
+	*cmds++ = CP_REG(A3XX_SP_SP_CTRL_REG);
+	/* SP_SP_CTRL_REG */
+	*cmds++ = _SET(SP_SPCTRLREG_SLEEPMODE, 1);
+
+	/* Load vertex shader */
+	*cmds++ = cp_type3_packet(CP_LOAD_STATE, 10);
+	*cmds++ = (0 << CP_LOADSTATE_DSTOFFSET_SHIFT)
+		| (HLSQ_DIRECT << CP_LOADSTATE_STATESRC_SHIFT)
+		| (HLSQ_BLOCK_ID_SP_VS << CP_LOADSTATE_STATEBLOCKID_SHIFT)
+		| (1 << CP_LOADSTATE_NUMOFUNITS_SHIFT);
+	*cmds++ = (HLSQ_SP_VS_INSTR << CP_LOADSTATE_STATETYPE_SHIFT)
+		| (0 << CP_LOADSTATE_EXTSRCADDR_SHIFT);
+	/* (sy)end; */
+	*cmds++ = 0x00000000; *cmds++ = 0x13000000;
+	/* nop; */
+	*cmds++ = 0x00000000; *cmds++ = 0x00000000;
+	/* nop; */
+	*cmds++ = 0x00000000; *cmds++ = 0x00000000;
+	/* nop; */
+	*cmds++ = 0x00000000; *cmds++ = 0x00000000;
+
+	/* Load fragment shader */
+	*cmds++ = cp_type3_packet(CP_LOAD_STATE, 18);
+	*cmds++ = (0 << CP_LOADSTATE_DSTOFFSET_SHIFT)
+		| (HLSQ_DIRECT << CP_LOADSTATE_STATESRC_SHIFT)
+		| (HLSQ_BLOCK_ID_SP_FS << CP_LOADSTATE_STATEBLOCKID_SHIFT)
+		| (2 << CP_LOADSTATE_NUMOFUNITS_SHIFT);
+	*cmds++ = (HLSQ_SP_FS_INSTR << CP_LOADSTATE_STATETYPE_SHIFT)
+		| (0 << CP_LOADSTATE_EXTSRCADDR_SHIFT);
+	/* (sy)(rpt1)bary.f (ei)r0.z, (r)0, r0.x; */
+	*cmds++ = 0x00002000; *cmds++ = 0x57368902;
+	/* (rpt5)nop; */
+	*cmds++ = 0x00000000; *cmds++ = 0x00000500;
+	/* sam (f32)r0.xyzw, r0.z, s#0, t#0; */
+	*cmds++ = 0x00000005; *cmds++ = 0xa0c01f00;
+	/* (sy)mov.f32f32 r1.x, r0.x; */
+	*cmds++ = 0x00000000; *cmds++ = 0x30044004;
+	/* mov.f32f32 r1.y, r0.y; */
+	*cmds++ = 0x00000001; *cmds++ = 0x20044005;
+	/* mov.f32f32 r1.z, r0.z; */
+	*cmds++ = 0x00000002; *cmds++ = 0x20044006;
+	/* mov.f32f32 r1.w, r0.w; */
+	*cmds++ = 0x00000003; *cmds++ = 0x20044007;
+	/* end; */
+	*cmds++ = 0x00000000; *cmds++ = 0x03000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_VFD_CONTROL_0);
+	/* VFD_CONTROL_0 */
+	*cmds++ = _SET(VFD_CTRLREG0_TOTALATTRTOVS, 8) |
+		_SET(VFD_CTRLREG0_PACKETSIZE, 2) |
+		_SET(VFD_CTRLREG0_STRMDECINSTRCNT, 2) |
+		_SET(VFD_CTRLREG0_STRMFETCHINSTRCNT, 2);
+	/* VFD_CONTROL_1 */
+	*cmds++ =  _SET(VFD_CTRLREG1_MAXSTORAGE, 2) |
+		_SET(VFD_CTRLREG1_REGID4VTX, 252) |
+		_SET(VFD_CTRLREG1_REGID4INST, 252);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
+	*cmds++ = CP_REG(A3XX_VFD_FETCH_INSTR_0_0);
+	/* VFD_FETCH_INSTR_0_0 */
+	*cmds++ = _SET(VFD_FETCHINSTRUCTIONS_FETCHSIZE, 7) |
+		_SET(VFD_FETCHINSTRUCTIONS_BUFSTRIDE, 8) |
+		_SET(VFD_FETCHINSTRUCTIONS_SWITCHNEXT, 1) |
+		_SET(VFD_FETCHINSTRUCTIONS_STEPRATE, 1);
+	/* VFD_FETCH_INSTR_1_0 */
+	*cmds++ = _SET(VFD_BASEADDR_BASEADDR,
+		shadow->quad_vertices_restore.gpuaddr);
+	/* VFD_FETCH_INSTR_0_1 */
+	*cmds++ = _SET(VFD_FETCHINSTRUCTIONS_FETCHSIZE, 11) |
+		_SET(VFD_FETCHINSTRUCTIONS_BUFSTRIDE, 12) |
+		_SET(VFD_FETCHINSTRUCTIONS_INDEXDECODE, 1) |
+		_SET(VFD_FETCHINSTRUCTIONS_STEPRATE, 1);
+	/* VFD_FETCH_INSTR_1_1 */
+	*cmds++ = _SET(VFD_BASEADDR_BASEADDR,
+		shadow->quad_vertices_restore.gpuaddr + 16);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_VFD_DECODE_INSTR_0);
+	/* VFD_DECODE_INSTR_0 */
+	*cmds++ = _SET(VFD_DECODEINSTRUCTIONS_WRITEMASK, 0x0F) |
+		_SET(VFD_DECODEINSTRUCTIONS_CONSTFILL, 1) |
+		_SET(VFD_DECODEINSTRUCTIONS_FORMAT, 1) |
+		_SET(VFD_DECODEINSTRUCTIONS_SHIFTCNT, 8) |
+		_SET(VFD_DECODEINSTRUCTIONS_LASTCOMPVALID, 1) |
+		_SET(VFD_DECODEINSTRUCTIONS_SWITCHNEXT, 1);
+	/* VFD_DECODE_INSTR_1 */
+	*cmds++ = _SET(VFD_DECODEINSTRUCTIONS_WRITEMASK, 0x0F) |
+		_SET(VFD_DECODEINSTRUCTIONS_CONSTFILL, 1) |
+		_SET(VFD_DECODEINSTRUCTIONS_FORMAT, 2) |
+		_SET(VFD_DECODEINSTRUCTIONS_REGID, 4) |
+		_SET(VFD_DECODEINSTRUCTIONS_SHIFTCNT, 12) |
+		_SET(VFD_DECODEINSTRUCTIONS_LASTCOMPVALID, 1);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_RB_DEPTH_CONTROL);
+	/* RB_DEPTH_CONTROL */
+	*cmds++ = _SET(RB_DEPTHCONTROL_Z_TEST_FUNC, RB_FRAG_NEVER);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_RB_STENCIL_CONTROL);
+	/* RB_STENCIL_CONTROL */
+	*cmds++ = _SET(RB_STENCILCONTROL_STENCIL_FUNC, RB_REF_NEVER) |
+		_SET(RB_STENCILCONTROL_STENCIL_FAIL, RB_STENCIL_KEEP) |
+		_SET(RB_STENCILCONTROL_STENCIL_ZPASS, RB_STENCIL_KEEP) |
+		_SET(RB_STENCILCONTROL_STENCIL_ZFAIL, RB_STENCIL_KEEP) |
+		_SET(RB_STENCILCONTROL_STENCIL_FUNC_BF, RB_REF_NEVER) |
+		_SET(RB_STENCILCONTROL_STENCIL_FAIL_BF, RB_STENCIL_KEEP) |
+		_SET(RB_STENCILCONTROL_STENCIL_ZPASS_BF, RB_STENCIL_KEEP) |
+		_SET(RB_STENCILCONTROL_STENCIL_ZFAIL_BF, RB_STENCIL_KEEP);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_RB_MODE_CONTROL);
+	/* RB_MODE_CONTROL */
+	*cmds++ = _SET(RB_MODECONTROL_RENDER_MODE, RB_RENDERING_PASS) |
+		_SET(RB_MODECONTROL_MARB_CACHE_SPLIT_MODE, 1);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_RB_RENDER_CONTROL);
+	/* RB_RENDER_CONTROL */
+	*cmds++ = _SET(RB_RENDERCONTROL_BIN_WIDTH, shadow->width >> 5) |
+		_SET(RB_RENDERCONTROL_ALPHA_TEST_FUNC, 7);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_RB_MSAA_CONTROL);
+	/* RB_MSAA_CONTROL */
+	*cmds++ = _SET(RB_MSAACONTROL_MSAA_DISABLE, 1) |
+		_SET(RB_MSAACONTROL_SAMPLE_MASK, 0xFFFF);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_RB_MRT_CONTROL0);
+	/* RB_MRT_CONTROL0 */
+	*cmds++ = _SET(RB_MRTCONTROL_READ_DEST_ENABLE, 1) |
+		_SET(RB_MRTCONTROL_ROP_CODE, 12) |
+		_SET(RB_MRTCONTROL_DITHER_MODE, RB_DITHER_ALWAYS) |
+		_SET(RB_MRTCONTROL_COMPONENT_ENABLE, 0xF);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_RB_MRT_BLEND_CONTROL0);
+	/* RB_MRT_BLENDCONTROL0 */
+	*cmds++ = _SET(RB_MRTBLENDCONTROL_RGB_SRC_FACTOR, RB_FACTOR_ONE) |
+		_SET(RB_MRTBLENDCONTROL_RGB_BLEND_OPCODE, RB_BLEND_OP_ADD) |
+		_SET(RB_MRTBLENDCONTROL_RGB_DEST_FACTOR, RB_FACTOR_ZERO) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_SRC_FACTOR, RB_FACTOR_ONE) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_BLEND_OPCODE, RB_BLEND_OP_ADD) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_DEST_FACTOR, RB_FACTOR_ZERO) |
+		_SET(RB_MRTBLENDCONTROL_CLAMP_ENABLE, 1);
+	/* RB_MRT_CONTROL1 */
+	*cmds++ = _SET(RB_MRTCONTROL_READ_DEST_ENABLE, 1) |
+		_SET(RB_MRTCONTROL_DITHER_MODE, RB_DITHER_DISABLE) |
+		_SET(RB_MRTCONTROL_COMPONENT_ENABLE, 0xF);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_RB_MRT_BLEND_CONTROL1);
+	/* RB_MRT_BLENDCONTROL1 */
+	*cmds++ = _SET(RB_MRTBLENDCONTROL_RGB_SRC_FACTOR, RB_FACTOR_ONE) |
+		_SET(RB_MRTBLENDCONTROL_RGB_BLEND_OPCODE, RB_BLEND_OP_ADD) |
+		_SET(RB_MRTBLENDCONTROL_RGB_DEST_FACTOR, RB_FACTOR_ZERO) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_SRC_FACTOR, RB_FACTOR_ONE) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_BLEND_OPCODE, RB_BLEND_OP_ADD) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_DEST_FACTOR, RB_FACTOR_ZERO) |
+		_SET(RB_MRTBLENDCONTROL_CLAMP_ENABLE, 1);
+	/* RB_MRT_CONTROL2 */
+	*cmds++ = _SET(RB_MRTCONTROL_READ_DEST_ENABLE, 1) |
+		_SET(RB_MRTCONTROL_DITHER_MODE, RB_DITHER_DISABLE) |
+		_SET(RB_MRTCONTROL_COMPONENT_ENABLE, 0xF);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_RB_MRT_BLEND_CONTROL2);
+	/* RB_MRT_BLENDCONTROL2 */
+	*cmds++ = _SET(RB_MRTBLENDCONTROL_RGB_SRC_FACTOR, RB_FACTOR_ONE) |
+		_SET(RB_MRTBLENDCONTROL_RGB_BLEND_OPCODE, RB_BLEND_OP_ADD) |
+		_SET(RB_MRTBLENDCONTROL_RGB_DEST_FACTOR, RB_FACTOR_ZERO) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_SRC_FACTOR, RB_FACTOR_ONE) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_BLEND_OPCODE, RB_BLEND_OP_ADD) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_DEST_FACTOR, RB_FACTOR_ZERO) |
+		_SET(RB_MRTBLENDCONTROL_CLAMP_ENABLE, 1);
+	/* RB_MRT_CONTROL3 */
+	*cmds++ = _SET(RB_MRTCONTROL_READ_DEST_ENABLE, 1) |
+		_SET(RB_MRTCONTROL_DITHER_MODE, RB_DITHER_DISABLE) |
+		_SET(RB_MRTCONTROL_COMPONENT_ENABLE, 0xF);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_RB_MRT_BLEND_CONTROL3);
+	/* RB_MRT_BLENDCONTROL3 */
+	*cmds++ = _SET(RB_MRTBLENDCONTROL_RGB_SRC_FACTOR, RB_FACTOR_ONE) |
+		_SET(RB_MRTBLENDCONTROL_RGB_BLEND_OPCODE, RB_BLEND_OP_ADD) |
+		_SET(RB_MRTBLENDCONTROL_RGB_DEST_FACTOR, RB_FACTOR_ZERO) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_SRC_FACTOR, RB_FACTOR_ONE) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_BLEND_OPCODE, RB_BLEND_OP_ADD) |
+		_SET(RB_MRTBLENDCONTROL_ALPHA_DEST_FACTOR, RB_FACTOR_ZERO) |
+		_SET(RB_MRTBLENDCONTROL_CLAMP_ENABLE, 1);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
+	*cmds++ = CP_REG(A3XX_VFD_INDEX_MIN);
+	/* VFD_INDEX_MIN */
+	*cmds++ = 0x00000000;
+	/* VFD_INDEX_MAX */
+	*cmds++ = 0xFFFFFFFF;
+	/* VFD_INDEX_OFFSET */
+	*cmds++ = 0x00000000;
+	/* TPL1_TP_VS_TEX_OFFSET */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_VFD_VS_THREADING_THRESHOLD);
+	/* VFD_VS_THREADING_THRESHOLD */
+	*cmds++ = _SET(VFD_THREADINGTHRESHOLD_RESERVED6, 12) |
+		_SET(VFD_THREADINGTHRESHOLD_REGID_VTXCNT, 252);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_TPL1_TP_VS_TEX_OFFSET);
+	/* TPL1_TP_VS_TEX_OFFSET */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_TPL1_TP_FS_TEX_OFFSET);
+	/* TPL1_TP_FS_TEX_OFFSET */
+	*cmds++ = _SET(TPL1_TPTEXOFFSETREG_SAMPLEROFFSET, 16) |
+		_SET(TPL1_TPTEXOFFSETREG_MEMOBJOFFSET, 16) |
+		_SET(TPL1_TPTEXOFFSETREG_BASETABLEPTR, 224);
+
+	*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++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_GRAS_SU_MODE_CONTROL);
+	/* GRAS_SU_MODE_CONTROL */
+	*cmds++ = 0x00000000;
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_GRAS_SC_WINDOW_SCISSOR_TL);
+	/* GRAS_SC_WINDOW_SCISSOR_TL */
+	*cmds++ = 0x00000000;
+	/* GRAS_SC_WINDOW_SCISSOR_BR */
+	*cmds++ = _SET(GRAS_SC_WINDOW_SCISSOR_BR_BR_X, shadow->width - 1) |
+		_SET(GRAS_SC_WINDOW_SCISSOR_BR_BR_Y, shadow->height - 1);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_GRAS_SC_SCREEN_SCISSOR_TL);
+	/* GRAS_SC_SCREEN_SCISSOR_TL */
+	*cmds++ = 0x00000000;
+	/* GRAS_SC_SCREEN_SCISSOR_BR */
+	*cmds++ = _SET(GRAS_SC_SCREEN_SCISSOR_BR_BR_X, shadow->width - 1) |
+		_SET(GRAS_SC_SCREEN_SCISSOR_BR_BR_Y, shadow->height - 1);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
+	*cmds++ = CP_REG(A3XX_GRAS_CL_VPORT_XOFFSET);
+	/* GRAS_CL_VPORT_XOFFSET */
+	*cmds++ = 0x00000000;
+	/* GRAS_CL_VPORT_XSCALE */
+	*cmds++ = _SET(GRAS_CL_VPORT_XSCALE_VPORT_XSCALE, 0x3F800000);
+	/* GRAS_CL_VPORT_YOFFSET */
+	*cmds++ = 0x00000000;
+	/* GRAS_CL_VPORT_YSCALE */
+	*cmds++ = _SET(GRAS_CL_VPORT_YSCALE_VPORT_YSCALE, 0x3F800000);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
+	*cmds++ = CP_REG(A3XX_GRAS_CL_VPORT_ZOFFSET);
+	/* GRAS_CL_VPORT_ZOFFSET */
+	*cmds++ = 0x00000000;
+	/* GRAS_CL_VPORT_ZSCALE */
+	*cmds++ = _SET(GRAS_CL_VPORT_ZSCALE_VPORT_ZSCALE, 0x3F800000);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_GRAS_CL_CLIP_CNTL);
+	/* GRAS_CL_CLIP_CNTL */
+	*cmds++ = _SET(GRAS_CL_CLIP_CNTL_IJ_PERSP_CENTER, 1);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_SP_FS_IMAGE_OUTPUT_REG_0);
+	/* SP_FS_IMAGE_OUTPUT_REG_0 */
+	*cmds++ = _SET(SP_IMAGEOUTPUTREG_MRTFORMAT, SP_R8G8B8A8_UNORM);
+
+	*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmds++ = CP_REG(A3XX_PC_PRIM_VTX_CNTL);
+	/* PC_PRIM_VTX_CONTROL */
+	*cmds++ = _SET(PC_PRIM_VTX_CONTROL_STRIDE_IN_VPC, 2) |
+		_SET(PC_PRIM_VTX_CONTROL_POLYMODE_FRONT_PTYPE,
+		PC_DRAW_TRIANGLES) |
+		_SET(PC_PRIM_VTX_CONTROL_POLYMODE_BACK_PTYPE,
+		PC_DRAW_TRIANGLES) |
+		_SET(PC_PRIM_VTX_CONTROL_PROVOKING_VTX_LAST, 1);
+
+	*cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
+	*cmds++ = 0x00000000; /* Viz query info */
+	*cmds++ = BUILD_PC_DRAW_INITIATOR(PC_DI_PT_RECTLIST,
+					  PC_DI_SRC_SEL_AUTO_INDEX,
+					  PC_DI_INDEX_SIZE_16_BIT,
+					  PC_DI_IGNORE_VISIBILITY);
+	*cmds++ = 0x00000002; /* Num indices */
+
+	/* Create indirect buffer command for above command sequence */
+	create_ib1(drawctxt, shadow->gmem_restore, start, cmds);
+
+	return cmds;
+}
+
+static void build_regrestore_cmds(struct adreno_device *adreno_dev,
+				  struct adreno_context *drawctxt)
+{
+	unsigned int *start = tmp_ctx.cmd;
+	unsigned int *cmd = start;
+	unsigned int *lcc_start;
+
+	int i;
+
+	/* Flush HLSQ lazy updates */
+	*cmd++ = cp_type3_packet(CP_EVENT_WRITE, 1);
+	*cmd++ = 0x7;		/* HLSQ_FLUSH */
+	*cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+	*cmd++ = 0;
+
+	*cmd++ = cp_type0_packet(A3XX_UCHE_CACHE_INVALIDATE0_REG, 2);
+	*cmd++ = 0x00000000;    /* No start addr for full invalidate */
+	*cmd++ = (unsigned int)
+		UCHE_ENTIRE_CACHE << UCHE_INVALIDATE1REG_ALLORPORTION |
+		UCHE_OP_INVALIDATE << UCHE_INVALIDATE1REG_OPCODE |
+		0;  /* No end addr for full invalidate */
+
+	lcc_start = cmd;
+
+	/* deferred cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, ???); */
+	cmd++;
+
+#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
+	/* Force mismatch */
+	*cmd++ = ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) | 1;
+#else
+	*cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
+#endif
+
+	for (i = 0; i < ARRAY_SIZE(context_register_ranges) / 2; i++) {
+		cmd = reg_range(cmd, context_register_ranges[i * 2],
+				context_register_ranges[i * 2 + 1]);
+	}
+
+	lcc_start[0] = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT,
+					(cmd - lcc_start) - 1);
+
+#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
+	lcc_start[2] |= (0 << 24) | (4 << 16);	/* Disable shadowing. */
+#else
+	lcc_start[2] |= (1 << 24) | (4 << 16);
+#endif
+
+	for (i = 0; i < ARRAY_SIZE(global_registers); i++) {
+		*cmd++ = cp_type0_packet(global_registers[i], 1);
+		tmp_ctx.reg_values[i] = virt2gpu(cmd, &drawctxt->gpustate);
+		*cmd++ = 0x00000000;
+	}
+
+	create_ib1(drawctxt, drawctxt->reg_restore, start, cmd);
+	tmp_ctx.cmd = cmd;
+}
+
+static void build_constantrestore_cmds(struct adreno_device *adreno_dev,
+				       struct adreno_context *drawctxt)
+{
+	unsigned int *cmd = tmp_ctx.cmd;
+	unsigned int *start = cmd;
+	unsigned int mode = 4;	/* Indirect mode */
+	unsigned int stateblock;
+	unsigned int numunits;
+	unsigned int statetype;
+
+	drawctxt->cond_execs[2].hostptr = cmd;
+	drawctxt->cond_execs[2].gpuaddr = virt2gpu(cmd, &drawctxt->gpustate);
+	*cmd++ = 0;
+	drawctxt->cond_execs[3].hostptr = cmd;
+	drawctxt->cond_execs[3].gpuaddr = virt2gpu(cmd, &drawctxt->gpustate);
+	*cmd++ = 0;
+
+#ifndef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
+	*cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
+	*cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
+	*cmd++ = 4 << 16;
+	*cmd++ = 0x0;
+#endif
+	/* HLSQ full update */
+	*cmd++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmd++ = CP_REG(A3XX_HLSQ_CONTROL_0_REG);
+	*cmd++ = 0x68000240;	/* A3XX_HLSQ_CONTROL_0_REG */
+
+#ifndef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
+	/* Re-enable shadowing */
+	*cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
+	*cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
+	*cmd++ = (4 << 16) | (1 << 24);
+	*cmd++ = 0x0;
+#endif
+
+	/* Load vertex shader constants */
+	*cmd++ = cp_type3_packet(CP_COND_EXEC, 4);
+	*cmd++ = drawctxt->cond_execs[2].gpuaddr >> 2;
+	*cmd++ = drawctxt->cond_execs[2].gpuaddr >> 2;
+	*cmd++ = 0x0000ffff;
+	*cmd++ = 3; /* EXEC_COUNT */
+	*cmd++ = cp_type3_packet(CP_LOAD_STATE, 2);
+	drawctxt->constant_load_commands[0].hostptr = cmd;
+	drawctxt->constant_load_commands[0].gpuaddr = virt2gpu(cmd,
+		&drawctxt->gpustate);
+
+	/*
+	   From fixup:
+
+	   mode = 4 (indirect)
+	   stateblock = 4 (Vertex constants)
+	   numunits = SP_VS_CTRL_REG1.VSCONSTLENGTH * 2; (256bit units)
+
+	   From register spec:
+	   SP_VS_CTRL_REG1.VSCONSTLENGTH [09:00]: 0-512, unit = 128bits.
+
+	   ord1 = (numunits<<22) | (stateblock<<19) | (mode<<16);
+	 */
+
+	*cmd++ = 0;		/* ord1 */
+	*cmd++ = ((drawctxt->gpustate.gpuaddr) & 0xfffffffc) | 1;
+
+	/* Load fragment shader constants */
+	*cmd++ = cp_type3_packet(CP_COND_EXEC, 4);
+	*cmd++ = drawctxt->cond_execs[3].gpuaddr >> 2;
+	*cmd++ = drawctxt->cond_execs[3].gpuaddr >> 2;
+	*cmd++ = 0x0000ffff;
+	*cmd++ = 3; /* EXEC_COUNT */
+	*cmd++ = cp_type3_packet(CP_LOAD_STATE, 2);
+	drawctxt->constant_load_commands[1].hostptr = cmd;
+	drawctxt->constant_load_commands[1].gpuaddr =
+	    virt2gpu(cmd, &drawctxt->gpustate);
+	/*
+	   From fixup:
+
+	   mode = 4 (indirect)
+	   stateblock = 6 (Fragment constants)
+	   numunits = SP_FS_CTRL_REG1.FSCONSTLENGTH * 2; (256bit units)
+
+	   From register spec:
+	   SP_FS_CTRL_REG1.FSCONSTLENGTH [09:00]: 0-512, unit = 128bits.
+
+	   ord1 = (numunits<<22) | (stateblock<<19) | (mode<<16);
+	 */
+
+	*cmd++ = 0;		/* ord1 */
+	drawctxt->constant_load_commands[2].hostptr = cmd;
+	drawctxt->constant_load_commands[2].gpuaddr =
+	    virt2gpu(cmd, &drawctxt->gpustate);
+	/*
+	   From fixup:
+	   base = drawctxt->gpustate.gpuaddr (ALU constant shadow base)
+	   offset = SP_FS_OBJ_OFFSET_REG.CONSTOBJECTSTARTOFFSET
+
+	   From register spec:
+	   SP_FS_OBJ_OFFSET_REG.CONSTOBJECTSTARTOFFSET [16:24]: Constant object
+	   start offset in on chip RAM,
+	   128bit aligned
+
+	   ord2 = base + offset | 1
+	   Because of the base alignment we can use
+	   ord2 = base | offset | 1
+	 */
+	*cmd++ = 0;		/* ord2 */
+
+	/* Restore VS texture memory objects */
+	stateblock = 0;
+	statetype = 1;
+	numunits = (TEX_SIZE_MEM_OBJECTS / 7) / 4;
+
+	*cmd++ = cp_type3_packet(CP_LOAD_STATE, 2);
+	*cmd++ = (numunits << 22) | (stateblock << 19) | (mode << 16);
+	*cmd++ = ((drawctxt->gpustate.gpuaddr + VS_TEX_OFFSET_MEM_OBJECTS)
+	    & 0xfffffffc) | statetype;
+
+	/* Restore VS texture mipmap addresses */
+	stateblock = 1;
+	statetype = 1;
+	numunits = TEX_SIZE_MIPMAP / 4;
+	*cmd++ = cp_type3_packet(CP_LOAD_STATE, 2);
+	*cmd++ = (numunits << 22) | (stateblock << 19) | (mode << 16);
+	*cmd++ = ((drawctxt->gpustate.gpuaddr + VS_TEX_OFFSET_MIPMAP)
+	    & 0xfffffffc) | statetype;
+
+	/* Restore VS texture sampler objects */
+	stateblock = 0;
+	statetype = 0;
+	numunits = (TEX_SIZE_SAMPLER_OBJ / 2) / 4;
+	*cmd++ = cp_type3_packet(CP_LOAD_STATE, 2);
+	*cmd++ = (numunits << 22) | (stateblock << 19) | (mode << 16);
+	*cmd++ = ((drawctxt->gpustate.gpuaddr + VS_TEX_OFFSET_SAMPLER_OBJ)
+	    & 0xfffffffc) | statetype;
+
+	/* Restore FS texture memory objects */
+	stateblock = 2;
+	statetype = 1;
+	numunits = (TEX_SIZE_MEM_OBJECTS / 7) / 4;
+	*cmd++ = cp_type3_packet(CP_LOAD_STATE, 2);
+	*cmd++ = (numunits << 22) | (stateblock << 19) | (mode << 16);
+	*cmd++ = ((drawctxt->gpustate.gpuaddr + FS_TEX_OFFSET_MEM_OBJECTS)
+	    & 0xfffffffc) | statetype;
+
+	/* Restore FS texture mipmap addresses */
+	stateblock = 3;
+	statetype = 1;
+	numunits = TEX_SIZE_MIPMAP / 4;
+	*cmd++ = cp_type3_packet(CP_LOAD_STATE, 2);
+	*cmd++ = (numunits << 22) | (stateblock << 19) | (mode << 16);
+	*cmd++ = ((drawctxt->gpustate.gpuaddr + FS_TEX_OFFSET_MIPMAP)
+	    & 0xfffffffc) | statetype;
+
+	/* Restore FS texture sampler objects */
+	stateblock = 2;
+	statetype = 0;
+	numunits = (TEX_SIZE_SAMPLER_OBJ / 2) / 4;
+	*cmd++ = cp_type3_packet(CP_LOAD_STATE, 2);
+	*cmd++ = (numunits << 22) | (stateblock << 19) | (mode << 16);
+	*cmd++ = ((drawctxt->gpustate.gpuaddr + FS_TEX_OFFSET_SAMPLER_OBJ)
+	    & 0xfffffffc) | statetype;
+
+	create_ib1(drawctxt, drawctxt->constant_restore, start, cmd);
+	tmp_ctx.cmd = cmd;
+}
+
+static void build_shader_restore_cmds(struct adreno_device *adreno_dev,
+				      struct adreno_context *drawctxt)
+{
+	unsigned int *cmd = tmp_ctx.cmd;
+	unsigned int *start = cmd;
+
+	/* Vertex shader */
+	*cmd++ = cp_type3_packet(CP_COND_EXEC, 4);
+	*cmd++ = drawctxt->cond_execs[0].gpuaddr >> 2;
+	*cmd++ = drawctxt->cond_execs[0].gpuaddr >> 2;
+	*cmd++ = 1;
+	*cmd++ = 3;		/* EXEC_COUNT */
+
+	*cmd++ = cp_type3_packet(CP_LOAD_STATE, 2);
+	drawctxt->shader_load_commands[0].hostptr = cmd;
+	drawctxt->shader_load_commands[0].gpuaddr =
+	    virt2gpu(cmd, &drawctxt->gpustate);
+	/*
+	   From fixup:
+
+	   mode = 4 (indirect)
+	   stateblock = 4 (Vertex shader)
+	   numunits = SP_VS_CTRL_REG0.VS_LENGTH
+
+	   From regspec:
+	   SP_VS_CTRL_REG0.VS_LENGTH [31:24]: VS length, unit = 256bits.
+	   If bit31 is 1, it means overflow
+	   or any long shader.
+
+	   ord1 = (numunits<<22) | (stateblock<<19) | (mode<<11)
+	 */
+	*cmd++ = 0;		/*ord1 */
+	*cmd++ = (drawctxt->gpustate.gpuaddr + SHADER_OFFSET) & 0xfffffffc;
+
+	/* Fragment shader */
+	*cmd++ = cp_type3_packet(CP_COND_EXEC, 4);
+	*cmd++ = drawctxt->cond_execs[1].gpuaddr >> 2;
+	*cmd++ = drawctxt->cond_execs[1].gpuaddr >> 2;
+	*cmd++ = 1;
+	*cmd++ = 3;		/* EXEC_COUNT */
+
+	*cmd++ = cp_type3_packet(CP_LOAD_STATE, 2);
+	drawctxt->shader_load_commands[1].hostptr = cmd;
+	drawctxt->shader_load_commands[1].gpuaddr =
+	    virt2gpu(cmd, &drawctxt->gpustate);
+	/*
+	   From fixup:
+
+	   mode = 4 (indirect)
+	   stateblock = 6 (Fragment shader)
+	   numunits = SP_FS_CTRL_REG0.FS_LENGTH
+
+	   From regspec:
+	   SP_FS_CTRL_REG0.FS_LENGTH [31:24]: FS length, unit = 256bits.
+	   If bit31 is 1, it means overflow
+	   or any long shader.
+
+	   ord1 = (numunits<<22) | (stateblock<<19) | (mode<<11)
+	 */
+	*cmd++ = 0;		/*ord1 */
+	*cmd++ = (drawctxt->gpustate.gpuaddr + SHADER_OFFSET
+		  + (SHADER_SHADOW_SIZE / 2)) & 0xfffffffc;
+
+	create_ib1(drawctxt, drawctxt->shader_restore, start, cmd);
+	tmp_ctx.cmd = cmd;
+}
+
+static void build_hlsqcontrol_restore_cmds(struct adreno_device *adreno_dev,
+					   struct adreno_context *drawctxt)
+{
+	unsigned int *cmd = tmp_ctx.cmd;
+	unsigned int *start = cmd;
+
+	*cmd++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+	*cmd++ = CP_REG(A3XX_HLSQ_CONTROL_0_REG);
+	drawctxt->hlsqcontrol_restore_commands[0].hostptr = cmd;
+	drawctxt->hlsqcontrol_restore_commands[0].gpuaddr
+	    = virt2gpu(cmd, &drawctxt->gpustate);
+	*cmd++ = 0;
+
+	/* Create indirect buffer command for above command sequence */
+	create_ib1(drawctxt, drawctxt->hlsqcontrol_restore, start, cmd);
+
+	tmp_ctx.cmd = cmd;
+}
+
+/* IB that modifies the shader and constant sizes and offsets in restore IBs. */
+static void build_restore_fixup_cmds(struct adreno_device *adreno_dev,
+				     struct adreno_context *drawctxt)
+{
+	unsigned int *cmd = tmp_ctx.cmd;
+	unsigned int *start = cmd;
+
+#ifdef GSL_CONTEXT_SWITCH_CPU_SYNC
+	/* Save shader sizes */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ = A3XX_SP_VS_CTRL_REG0;
+	*cmd++ = drawctxt->shader_load_commands[0].gpuaddr;
+
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ = A3XX_SP_FS_CTRL_REG0;
+	*cmd++ = drawctxt->shader_load_commands[1].gpuaddr;
+
+	/* Save constant sizes */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ = A3XX_SP_VS_CTRL_REG1;
+	*cmd++ = drawctxt->constant_load_commands[0].gpuaddr;
+
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ = A3XX_SP_FS_CTRL_REG1;
+	*cmd++ = drawctxt->constant_load_commands[1].gpuaddr;
+
+	/* Save constant offsets */
+	*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
+	*cmd++ = A3XX_SP_FS_OBJ_OFFSET_REG;
+	*cmd++ = drawctxt->constant_load_commands[2].gpuaddr;
+#else
+	/* Save shader sizes */
+	cmd = rmw_regtomem(cmd, A3XX_SP_VS_CTRL_REG0, 0x7f000000,
+			   30, (4 << 19) | (4 << 16),
+			   drawctxt->shader_load_commands[0].gpuaddr);
+
+	cmd = rmw_regtomem(cmd, A3XX_SP_FS_CTRL_REG0, 0x7f000000,
+			   30, (6 << 19) | (4 << 16),
+			   drawctxt->shader_load_commands[1].gpuaddr);
+
+	/* Save constant sizes */
+	cmd = rmw_regtomem(cmd, A3XX_SP_VS_CTRL_REG1, 0x000003ff,
+			   23, (4 << 19) | (4 << 16),
+			   drawctxt->constant_load_commands[0].gpuaddr);
+
+	cmd = rmw_regtomem(cmd, A3XX_SP_FS_CTRL_REG1, 0x000003ff,
+			   23, (6 << 19) | (4 << 16),
+			   drawctxt->constant_load_commands[1].gpuaddr);
+
+	/* Modify constant restore conditionals */
+	cmd = rmw_regtomem(cmd, A3XX_SP_VS_CTRL_REG1, 0x000003ff,
+			0, 0, drawctxt->cond_execs[2].gpuaddr);
+
+	cmd = rmw_regtomem(cmd, A3XX_SP_FS_CTRL_REG1, 0x000003ff,
+			0, 0, drawctxt->cond_execs[3].gpuaddr);
+
+	/* Save fragment constant shadow offset */
+	cmd = rmw_regtomem(cmd, A3XX_SP_FS_OBJ_OFFSET_REG, 0x00ff0000,
+			   18, (drawctxt->gpustate.gpuaddr & 0xfffffe00) | 1,
+			   drawctxt->constant_load_commands[2].gpuaddr);
+#endif
+
+	/* Use mask value to avoid flushing HLSQ which would cause the HW to
+	   discard all the shader data */
+
+	cmd = rmw_regtomem(cmd,  A3XX_HLSQ_CONTROL_0_REG, 0x9ffffdff,
+		0, 0, drawctxt->hlsqcontrol_restore_commands[0].gpuaddr);
+
+	create_ib1(drawctxt, drawctxt->restore_fixup, start, cmd);
+
+	tmp_ctx.cmd = cmd;
+}
+
+static int a3xx_create_gpustate_shadow(struct adreno_device *adreno_dev,
+				     struct adreno_context *drawctxt)
+{
+	drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW;
+
+	build_regrestore_cmds(adreno_dev, drawctxt);
+	build_constantrestore_cmds(adreno_dev, drawctxt);
+	build_hlsqcontrol_restore_cmds(adreno_dev, drawctxt);
+	build_regconstantsave_cmds(adreno_dev, drawctxt);
+	build_shader_save_cmds(adreno_dev, drawctxt);
+	build_shader_restore_cmds(adreno_dev, drawctxt);
+	build_restore_fixup_cmds(adreno_dev, drawctxt);
+	build_save_fixup_cmds(adreno_dev, drawctxt);
+
+	return 0;
+}
+
+/* create buffers for saving/restoring registers, constants, & GMEM */
+static int a3xx_create_gmem_shadow(struct adreno_device *adreno_dev,
+				 struct adreno_context *drawctxt)
+{
+	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);
+
+		if (result)
+			return result;
+	} else {
+		memset(&drawctxt->context_gmem_shadow.gmemshadow, 0,
+		       sizeof(drawctxt->context_gmem_shadow.gmemshadow));
+
+		return 0;
+	}
+
+	build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow,
+		&tmp_ctx.cmd);
+
+	/* Dow we need to idle? */
+	/* adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT); */
+
+	tmp_ctx.cmd = build_gmem2sys_cmds(adreno_dev, drawctxt,
+		&drawctxt->context_gmem_shadow);
+	tmp_ctx.cmd = build_sys2gmem_cmds(adreno_dev, drawctxt,
+		&drawctxt->context_gmem_shadow);
+
+	kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
+		KGSL_CACHE_OP_FLUSH);
+
+	return 0;
+}
+
+static int a3xx_drawctxt_create(struct adreno_device *adreno_dev,
+	struct adreno_context *drawctxt)
+{
+	int ret;
+
+	/*
+	 * Allocate memory for the GPU state and the context commands.
+	 * Despite the name, this is much more then just storage for
+	 * the gpustate.  This contains command space for gmem save
+	 * and texture and vertex buffer storage too
+	 */
+
+	ret = kgsl_allocate(&drawctxt->gpustate,
+		drawctxt->pagetable, CONTEXT_SIZE);
+
+	if (ret)
+		return ret;
+
+	kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0, CONTEXT_SIZE);
+	tmp_ctx.cmd = drawctxt->gpustate.hostptr + CMD_OFFSET;
+
+	if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
+		ret = a3xx_create_gpustate_shadow(adreno_dev, drawctxt);
+		if (ret)
+			goto done;
+
+		drawctxt->flags |= CTXT_FLAGS_SHADER_SAVE;
+	}
+
+	if (!(drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC))
+		ret = a3xx_create_gmem_shadow(adreno_dev, drawctxt);
+
+done:
+	if (ret)
+		kgsl_sharedmem_free(&drawctxt->gpustate);
+
+	return ret;
+}
+
+static void a3xx_drawctxt_save(struct adreno_device *adreno_dev,
+			   struct adreno_context *context)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+
+	if (context == NULL)
+		return;
+
+	if (context->flags & CTXT_FLAGS_GPU_HANG)
+		KGSL_CTXT_WARN(device,
+			       "Current active context has caused gpu hang\n");
+
+	if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
+		/* Fixup self modifying IBs for save operations */
+		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+			context->save_fixup, 3);
+
+		/* save registers and constants. */
+		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+			context->regconstant_save, 3);
+
+		if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
+			/* Save shader instructions */
+			adreno_ringbuffer_issuecmds(device,
+				KGSL_CMD_FLAGS_PMODE, context->shader_save, 3);
+
+			context->flags |= CTXT_FLAGS_SHADER_RESTORE;
+		}
+	}
+
+	if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
+	    (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
+		/*
+		 * Save GMEM (note: changes shader. shader must
+		 * already be saved.)
+		 */
+
+		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
+					    context->context_gmem_shadow.
+					    gmem_save, 3);
+		context->flags |= CTXT_FLAGS_GMEM_RESTORE;
+	}
+}
+
+static void a3xx_drawctxt_restore(struct adreno_device *adreno_dev,
+			      struct adreno_context *context)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+	unsigned int cmds[5];
+
+	if (context == NULL) {
+		/* No context - set the default pagetable and thats it */
+		kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
+		return;
+	}
+
+	KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
+
+	cmds[0] = cp_nop_packet(1);
+	cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
+	cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
+	cmds[3] = device->memstore.gpuaddr +
+	    KGSL_DEVICE_MEMSTORE_OFFSET(current_context);
+	cmds[4] = (unsigned int)context;
+	adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE, cmds, 5);
+	kgsl_mmu_setstate(device, context->pagetable);
+
+	/*
+	 * Restore GMEM.  (note: changes shader.
+	 * Shader must not already be restored.)
+	 */
+
+	if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
+		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
+					    context->context_gmem_shadow.
+					    gmem_restore, 3);
+		context->flags &= ~CTXT_FLAGS_GMEM_RESTORE;
+	}
+
+	if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
+		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+			context->reg_restore, 3);
+
+		/* Fixup self modifying IBs for restore operations */
+		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+			context->restore_fixup, 3);
+
+		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+			context->constant_restore, 3);
+
+		if (context->flags & CTXT_FLAGS_SHADER_RESTORE)
+			adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+				context->shader_restore, 3);
+
+		/* Restore HLSQ_CONTROL_0 register */
+		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+			context->hlsqcontrol_restore, 3);
+	}
+}
+
+static void a3xx_rb_init(struct adreno_device *adreno_dev,
+			 struct adreno_ringbuffer *rb)
+{
+	unsigned int *cmds, cmds_gpu;
+	cmds = adreno_ringbuffer_allocspace(rb, 18);
+	cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint) * (rb->wptr - 18);
+
+	GSL_RB_WRITE(cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT, 17));
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x000003f7);
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000080);
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000100);
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000180);
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00006600);
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000150);
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x0000014e);
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000154);
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000001);
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+	/* Protected mode control - turned off for A3XX */
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+
+	adreno_ringbuffer_submit(rb);
+}
+
+static void a3xx_err_callback(struct adreno_device *adreno_dev, int bit)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+	const char *err = "";
+
+	switch (bit) {
+	case A3XX_INT_RBBM_AHB_ERROR: {
+		unsigned int reg;
+
+		adreno_regread(device, A3XX_RBBM_AHB_ERROR_STATUS, &reg);
+
+		/*
+		 * Return the word address of the erroring register so that it
+		 * matches the register specification
+		 */
+
+		KGSL_DRV_CRIT(device,
+			"RBBM | AHB bus error | %s | addr=%x | ports=%x:%x\n",
+			reg & (1 << 28) ? "WRITE" : "READ",
+			(reg & 0xFFFFF) >> 2, (reg >> 20) & 0x3,
+			(reg >> 24) & 0x3);
+
+		/* Clear the error */
+		adreno_regwrite(device, A3XX_RBBM_AHB_CMD, (1 << 3));
+		return;
+	}
+	case A3XX_INT_RBBM_REG_TIMEOUT:
+		err = "RBBM: AHB register timeout";
+		break;
+	case A3XX_INT_RBBM_ME_MS_TIMEOUT:
+		err = "RBBM: ME master split timeout";
+		break;
+	case A3XX_INT_RBBM_PFP_MS_TIMEOUT:
+		err = "RBBM: PFP master split timeout";
+		break;
+	case A3XX_INT_RBBM_ATB_BUS_OVERFLOW:
+		err = "RBBM: ATB bus oveflow";
+		break;
+	case A3XX_INT_VFD_ERROR:
+		err = "VFD: Out of bounds access";
+		break;
+	case A3XX_INT_CP_T0_PACKET_IN_IB:
+		err = "ringbuffer TO packet in IB interrupt";
+		break;
+	case A3XX_INT_CP_OPCODE_ERROR:
+		err = "ringbuffer opcode error interrupt";
+		break;
+	case A3XX_INT_CP_RESERVED_BIT_ERROR:
+		err = "ringbuffer reserved bit error interrupt";
+		break;
+	case A3XX_INT_CP_HW_FAULT:
+		err = "ringbuffer hardware fault";
+		break;
+	case A3XX_INT_CP_REG_PROTECT_FAULT:
+		err = "ringbuffer protected mode error interrupt";
+		break;
+	case A3XX_INT_CP_AHB_ERROR_HALT:
+		err = "ringbuffer AHB error interrupt";
+		break;
+	case A3XX_INT_MISC_HANG_DETECT:
+		err = "MISC: GPU hang detected";
+		break;
+	case A3XX_INT_UCHE_OOB_ACCESS:
+		err = "UCHE:  Out of bounds access";
+		break;
+	}
+
+	KGSL_DRV_CRIT(device, "%s\n", err);
+	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
+}
+
+static void a3xx_cp_callback(struct adreno_device *adreno_dev, int irq)
+{
+	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
+
+	if (irq == A3XX_INT_CP_RB_INT) {
+		kgsl_sharedmem_writel(&rb->device->memstore,
+			KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable), 0);
+		wmb();
+		KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
+	}
+
+	wake_up_interruptible_all(&rb->device->wait_queue);
+
+	/* Schedule work to free mem and issue ibs */
+	queue_work(rb->device->work_queue, &rb->device->ts_expired_ws);
+
+	atomic_notifier_call_chain(&rb->device->ts_notifier_list,
+				   rb->device->id, NULL);
+}
+
+#define A3XX_IRQ_CALLBACK(_c) { .func = _c }
+
+#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) | \
+	 (1 << A3XX_INT_CP_HW_FAULT) |           \
+	 (1 << A3XX_INT_CP_IB1_INT) |            \
+	 (1 << A3XX_INT_CP_IB2_INT) |            \
+	 (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 {
+	void (*func)(struct adreno_device *, int);
+} a3xx_irq_funcs[] = {
+	A3XX_IRQ_CALLBACK(NULL),               /* 0 - RBBM_GPU_IDLE */
+	A3XX_IRQ_CALLBACK(a3xx_err_callback),  /* 1 - RBBM_AHB_ERROR */
+	A3XX_IRQ_CALLBACK(a3xx_err_callback),  /* 2 - RBBM_REG_TIMEOUT */
+	A3XX_IRQ_CALLBACK(a3xx_err_callback),  /* 3 - RBBM_ME_MS_TIMEOUT */
+	A3XX_IRQ_CALLBACK(a3xx_err_callback),  /* 4 - RBBM_PFP_MS_TIMEOUT */
+	A3XX_IRQ_CALLBACK(a3xx_err_callback),  /* 5 - RBBM_ATB_BUS_OVERFLOW */
+	A3XX_IRQ_CALLBACK(a3xx_err_callback),  /* 6 - RBBM_VFD_ERROR */
+	A3XX_IRQ_CALLBACK(NULL),	       /* 7 - CP_SW */
+	A3XX_IRQ_CALLBACK(a3xx_err_callback),  /* 8 - CP_T0_PACKET_IN_IB */
+	A3XX_IRQ_CALLBACK(a3xx_err_callback),  /* 9 - CP_OPCODE_ERROR */
+	A3XX_IRQ_CALLBACK(a3xx_err_callback),  /* 10 - CP_RESERVED_BIT_ERROR */
+	A3XX_IRQ_CALLBACK(a3xx_err_callback),  /* 11 - CP_HW_FAULT */
+	A3XX_IRQ_CALLBACK(NULL),	       /* 12 - CP_DMA */
+	A3XX_IRQ_CALLBACK(a3xx_cp_callback),   /* 13 - CP_IB2_INT */
+	A3XX_IRQ_CALLBACK(a3xx_cp_callback),   /* 14 - CP_IB1_INT */
+	A3XX_IRQ_CALLBACK(a3xx_cp_callback),   /* 15 - CP_RB_INT */
+	A3XX_IRQ_CALLBACK(a3xx_err_callback),  /* 16 - CP_REG_PROTECT_FAULT */
+	A3XX_IRQ_CALLBACK(NULL),	       /* 17 - CP_RB_DONE_TS */
+	A3XX_IRQ_CALLBACK(NULL),	       /* 18 - CP_VS_DONE_TS */
+	A3XX_IRQ_CALLBACK(NULL),	       /* 19 - CP_PS_DONE_TS */
+	A3XX_IRQ_CALLBACK(NULL),	       /* 20 - CP_CACHE_FLUSH_TS */
+	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(a3xx_err_callback),  /* 25 - UCHE_OOB_ACCESS */
+	/* 26 to 31 - Unused */
+};
+
+static irqreturn_t a3xx_irq_handler(struct adreno_device *adreno_dev)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+	irqreturn_t ret = IRQ_NONE;
+	unsigned int status, tmp;
+	int i;
+
+	adreno_regread(&adreno_dev->dev, A3XX_RBBM_INT_0_STATUS, &status);
+
+	for (tmp = status, i = 0; tmp && i < ARRAY_SIZE(a3xx_irq_funcs); i++) {
+		if (tmp & 1) {
+			if (a3xx_irq_funcs[i].func != NULL) {
+				a3xx_irq_funcs[i].func(adreno_dev, i);
+				ret = IRQ_HANDLED;
+			} else {
+				KGSL_DRV_CRIT(device,
+					"Unhandled interrupt bit %x\n", i);
+			}
+		}
+
+		tmp >>= 1;
+	}
+
+	if (status)
+		adreno_regwrite(&adreno_dev->dev, A3XX_RBBM_INT_CLEAR_CMD,
+			status);
+	return ret;
+}
+
+static void a3xx_irq_control(struct adreno_device *adreno_dev, int state)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+
+	if (state)
+		adreno_regwrite(device, A3XX_RBBM_INT_0_MASK, A3XX_INT_MASK);
+	else
+		adreno_regwrite(device, A3XX_RBBM_INT_0_MASK, 0);
+}
+
+static unsigned int a3xx_busy_cycles(struct adreno_device *adreno_dev)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+	unsigned int reg, val;
+
+	/* Freeze the counter */
+	adreno_regread(device, A3XX_RBBM_RBBM_CTL, &reg);
+	reg &= ~RBBM_RBBM_CTL_ENABLE_PWR_CTR1;
+	adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, reg);
+
+	/* Read the value */
+	adreno_regread(device, A3XX_RBBM_PERFCTR_PWR_1_LO, &val);
+
+	/* Reset the counter */
+	reg |= RBBM_RBBM_CTL_RESET_PWR_CTR1;
+	adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, reg);
+
+	/* Re-enable the counter */
+	reg &= ~RBBM_RBBM_CTL_RESET_PWR_CTR1;
+	reg |= RBBM_RBBM_CTL_ENABLE_PWR_CTR1;
+	adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, reg);
+
+	return val;
+}
+
+static void a3xx_start(struct adreno_device *adreno_dev)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+
+	/* Reset the core */
+	adreno_regwrite(device, A3XX_RBBM_SW_RESET_CMD,
+		0x00000001);
+	msleep(20);
+
+	/*
+	 * enable fixed master AXI port of 0x0 for all clients to keep
+	 * traffic from going to random places
+	 */
+
+	adreno_regwrite(device, A3XX_VBIF_FIXED_SORT_EN, 0x0001003F);
+	adreno_regwrite(device, A3XX_VBIF_FIXED_SORT_SEL0, 0x00000000);
+	adreno_regwrite(device, A3XX_VBIF_FIXED_SORT_SEL1, 0x00000000);
+
+	/* Make all blocks contribute to the GPU BUSY perf counter */
+	adreno_regwrite(device, A3XX_RBBM_GPU_BUSY_MASKED, 0xFFFFFFFF);
+
+	/* Enable the RBBM error reporting bits.  This lets us get
+	   useful information on failure */
+
+	adreno_regwrite(device, A3XX_RBBM_AHB_CTL0, 0x00000001);
+
+	/* Enable AHB error reporting */
+	adreno_regwrite(device, A3XX_RBBM_AHB_CTL1, 0xA6FFFFFF);
+
+	/* Turn on the power counters */
+	adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, 0x00003000);
+}
+
+/* Defined in adreno_a3xx_snapshot.c */
+void *a3xx_snapshot(struct adreno_device *adreno_dev, void *snapshot,
+	int *remain, int hang);
+
+struct adreno_gpudev adreno_a3xx_gpudev = {
+	.reg_rbbm_status = A3XX_RBBM_STATUS,
+	.reg_cp_pfp_ucode_addr = A3XX_CP_PFP_UCODE_ADDR,
+	.reg_cp_pfp_ucode_data = A3XX_CP_PFP_UCODE_DATA,
+
+	.ctxt_create = a3xx_drawctxt_create,
+	.ctxt_save = a3xx_drawctxt_save,
+	.ctxt_restore = a3xx_drawctxt_restore,
+	.rb_init = a3xx_rb_init,
+	.irq_control = a3xx_irq_control,
+	.irq_handler = a3xx_irq_handler,
+	.busy_cycles = a3xx_busy_cycles,
+	.start = a3xx_start,
+	.snapshot = a3xx_snapshot,
+};
diff --git a/drivers/gpu/msm/adreno_a3xx_snapshot.c b/drivers/gpu/msm/adreno_a3xx_snapshot.c
new file mode 100644
index 0000000..aade50c
--- /dev/null
+++ b/drivers/gpu/msm/adreno_a3xx_snapshot.c
@@ -0,0 +1,296 @@
+/* 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 "kgsl.h"
+#include "adreno.h"
+#include "kgsl_snapshot.h"
+#include "a3xx_reg.h"
+
+#define DEBUG_SECTION_SZ(_dwords) (((_dwords) * sizeof(unsigned int)) \
+		+ sizeof(struct kgsl_snapshot_debug))
+
+#define VPC_MEMORY_BANKS 4
+#define VPC_MEMORY_SIZE 512
+
+static int a3xx_snapshot_vpc_memory(struct kgsl_device *device, void *snapshot,
+		int remain, void *priv)
+{
+	struct kgsl_snapshot_debug *header = snapshot;
+	unsigned int *data = snapshot + sizeof(*header);
+	int size = VPC_MEMORY_BANKS * VPC_MEMORY_SIZE;
+	int bank, addr, i = 0;
+
+	if (remain < DEBUG_SECTION_SZ(size)) {
+		SNAPSHOT_ERR_NOMEM(device, "VPC MEMORY");
+		return 0;
+	}
+
+	header->type = SNAPSHOT_DEBUG_VPC_MEMORY;
+	header->size = size;
+
+	for (bank = 0; bank < VPC_MEMORY_BANKS; bank++) {
+		for (addr = 0; addr < VPC_MEMORY_SIZE; addr++) {
+			unsigned int val = bank | (addr << 4);
+			adreno_regwrite(device,
+				A3XX_VPC_VPC_DEBUG_RAM_SEL, val);
+			adreno_regread(device,
+				A3XX_VPC_VPC_DEBUG_RAM_READ, &data[i++]);
+		}
+	}
+
+	return DEBUG_SECTION_SZ(size);
+}
+
+#define CP_MEQ_SIZE 16
+static int a3xx_snapshot_cp_meq(struct kgsl_device *device, void *snapshot,
+		int remain, void *priv)
+{
+	struct kgsl_snapshot_debug *header = snapshot;
+	unsigned int *data = snapshot + sizeof(*header);
+	int i;
+
+	if (remain < DEBUG_SECTION_SZ(CP_MEQ_SIZE)) {
+		SNAPSHOT_ERR_NOMEM(device, "CP MEQ DEBUG");
+		return 0;
+	}
+
+	header->type = SNAPSHOT_DEBUG_CP_MEQ;
+	header->size = CP_MEQ_SIZE;
+
+	adreno_regwrite(device, A3XX_CP_MEQ_ADDR, 0x0);
+	for (i = 0; i < CP_MEQ_SIZE; i++)
+		adreno_regread(device, A3XX_CP_MEQ_DATA, &data[i]);
+
+	return DEBUG_SECTION_SZ(CP_MEQ_SIZE);
+}
+
+static int a3xx_snapshot_cp_pm4_ram(struct kgsl_device *device, void *snapshot,
+		int remain, void *priv)
+{
+	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;
+
+	if (remain < DEBUG_SECTION_SZ(size)) {
+		SNAPSHOT_ERR_NOMEM(device, "CP PM4 RAM DEBUG");
+		return 0;
+	}
+
+	header->type = SNAPSHOT_DEBUG_CP_PM4_RAM;
+	header->size = size;
+
+	/*
+	 * Read the firmware from the GPU rather than use our cache in order to
+	 * try to catch mis-programming or corruption in the hardware.  We do
+	 * use the cached version of the size, however, instead of trying to
+	 * maintain always changing hardcoded constants
+	 */
+
+	adreno_regwrite(device, REG_CP_ME_RAM_RADDR, 0x0);
+	for (i = 0; i < adreno_dev->pm4_fw_size >> 2; i++)
+		adreno_regread(device, REG_CP_ME_RAM_DATA, &data[i]);
+
+	return DEBUG_SECTION_SZ(size);
+}
+
+static int a3xx_snapshot_cp_pfp_ram(struct kgsl_device *device, void *snapshot,
+		int remain, void *priv)
+{
+	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;
+
+	if (remain < DEBUG_SECTION_SZ(size)) {
+		SNAPSHOT_ERR_NOMEM(device, "CP PFP RAM DEBUG");
+		return 0;
+	}
+
+	header->type = SNAPSHOT_DEBUG_CP_PFP_RAM;
+	header->size = size;
+
+	/*
+	 * Read the firmware from the GPU rather than use our cache in order to
+	 * try to catch mis-programming or corruption in the hardware.  We do
+	 * use the cached version of the size, however, instead of trying to
+	 * 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++)
+		adreno_regread(device, A3XX_CP_PFP_UCODE_DATA, &data[i]);
+
+	return DEBUG_SECTION_SZ(size);
+}
+
+#define CP_ROQ_SIZE 128
+
+static int a3xx_snapshot_cp_roq(struct kgsl_device *device, void *snapshot,
+		int remain, void *priv)
+{
+	struct kgsl_snapshot_debug *header = snapshot;
+	unsigned int *data = snapshot + sizeof(*header);
+	int i;
+
+	if (remain < DEBUG_SECTION_SZ(CP_ROQ_SIZE)) {
+		SNAPSHOT_ERR_NOMEM(device, "CP ROQ DEBUG");
+		return 0;
+	}
+
+	header->type = SNAPSHOT_DEBUG_CP_ROQ;
+	header->size = CP_ROQ_SIZE;
+
+	adreno_regwrite(device, A3XX_CP_ROQ_ADDR, 0x0);
+	for (i = 0; i < CP_ROQ_SIZE; i++)
+		adreno_regread(device, A3XX_CP_ROQ_DATA, &data[i]);
+
+	return DEBUG_SECTION_SZ(CP_ROQ_SIZE);
+}
+
+#define DEBUGFS_BLOCK_SIZE 0x40
+
+static int a3xx_snapshot_debugbus_block(struct kgsl_device *device,
+	void *snapshot, int remain, void *priv)
+{
+	struct kgsl_snapshot_debugbus *header = snapshot;
+	unsigned int id = (unsigned int) priv;
+	unsigned int val;
+	int i;
+	unsigned int *data = snapshot + sizeof(*header);
+	int size =
+		(DEBUGFS_BLOCK_SIZE * sizeof(unsigned int)) + sizeof(*header);
+
+	if (remain < size) {
+		SNAPSHOT_ERR_NOMEM(device, "DEBUGBUS");
+		return 0;
+	}
+
+	val = (id << 0x06) | (1 << 0x10);
+
+	header->id = id;
+	header->count = DEBUGFS_BLOCK_SIZE;
+
+	for (i = 0; i < DEBUGFS_BLOCK_SIZE; i++) {
+		adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, val | i);
+		adreno_regread(device, A3XX_RBBM_DEBUG_BUS_DATA_STATUS,
+			&data[i]);
+	}
+
+	return size;
+}
+
+static unsigned int debugbus_blocks[] = {
+	RBBM_BLOCK_ID_CP,
+	RBBM_BLOCK_ID_RBBM,
+	RBBM_BLOCK_ID_VBIF,
+	RBBM_BLOCK_ID_HLSQ,
+	RBBM_BLOCK_ID_UCHE,
+	RBBM_BLOCK_ID_PC,
+	RBBM_BLOCK_ID_VFD,
+	RBBM_BLOCK_ID_VPC,
+	RBBM_BLOCK_ID_TSE,
+	RBBM_BLOCK_ID_RAS,
+	RBBM_BLOCK_ID_VSC,
+	RBBM_BLOCK_ID_SP_0,
+	RBBM_BLOCK_ID_SP_1,
+	RBBM_BLOCK_ID_SP_2,
+	RBBM_BLOCK_ID_SP_3,
+	RBBM_BLOCK_ID_TPL1_0,
+	RBBM_BLOCK_ID_TPL1_1,
+	RBBM_BLOCK_ID_TPL1_2,
+	RBBM_BLOCK_ID_TPL1_3,
+	RBBM_BLOCK_ID_RB_0,
+	RBBM_BLOCK_ID_RB_1,
+	RBBM_BLOCK_ID_RB_2,
+	RBBM_BLOCK_ID_RB_3,
+	RBBM_BLOCK_ID_MARB_0,
+	RBBM_BLOCK_ID_MARB_1,
+	RBBM_BLOCK_ID_MARB_2,
+	RBBM_BLOCK_ID_MARB_3,
+};
+
+static void *a3xx_snapshot_debugbus(struct kgsl_device *device,
+	void *snapshot, int *remain)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(debugbus_blocks); i++) {
+		snapshot = kgsl_snapshot_add_section(device,
+			KGSL_SNAPSHOT_SECTION_DEBUGBUS, snapshot, remain,
+			a3xx_snapshot_debugbus_block,
+			(void *) debugbus_blocks[i]);
+	}
+
+	return snapshot;
+}
+
+/* A3XX GPU snapshot function - this is where all of the A3XX specific
+ * bits and pieces are grabbed into the snapshot memory
+ */
+
+void *a3xx_snapshot(struct adreno_device *adreno_dev, void *snapshot,
+	int *remain, int hang)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+	struct kgsl_snapshot_registers regs;
+
+	regs.regs = (unsigned int *) a3xx_registers;
+	regs.count = a3xx_registers_count;
+
+	/* Master set of (non debug) registers */
+	snapshot = kgsl_snapshot_add_section(device,
+		KGSL_SNAPSHOT_SECTION_REGS, snapshot, remain,
+		kgsl_snapshot_dump_regs, &regs);
+
+	/* CP_STATE_DEBUG indexed registers */
+	snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
+			remain, REG_CP_STATE_DEBUG_INDEX,
+			REG_CP_STATE_DEBUG_DATA, 0x0, 0x14);
+
+	/* CP_ME indexed registers */
+	snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
+			remain, REG_CP_ME_CNTL, REG_CP_ME_STATUS,
+			64, 44);
+
+	/* VPC memory */
+	snapshot = kgsl_snapshot_add_section(device,
+			KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
+			a3xx_snapshot_vpc_memory, NULL);
+
+	/* CP MEQ */
+	snapshot = kgsl_snapshot_add_section(device,
+			KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
+			a3xx_snapshot_cp_meq, NULL);
+
+	/* CP PFP and PM4 */
+	/* Reading these will hang the GPU if it isn't already hung */
+
+	if (hang) {
+		snapshot = kgsl_snapshot_add_section(device,
+			KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
+			a3xx_snapshot_cp_pfp_ram, NULL);
+
+		snapshot = kgsl_snapshot_add_section(device,
+			KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
+			a3xx_snapshot_cp_pm4_ram, NULL);
+	}
+
+	/* CP ROQ */
+	snapshot = kgsl_snapshot_add_section(device,
+			KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
+			a3xx_snapshot_cp_roq, NULL);
+
+	snapshot = a3xx_snapshot_debugbus(device, snapshot, remain);
+
+	return snapshot;
+}
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index b7b0ea4..9bf85cf 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -19,6 +19,7 @@
 
 /* quad for copying GMEM to context shadow */
 #define QUAD_LEN 12
+#define QUAD_RESTORE_LEN 14
 
 static unsigned int gmem_copy_quad[QUAD_LEN] = {
 	0x00000000, 0x00000000, 0x3f800000,
@@ -27,6 +28,14 @@
 	0x00000000, 0x00000000, 0x3f800000
 };
 
+static unsigned int gmem_restore_quad[QUAD_RESTORE_LEN] = {
+	0x00000000, 0x3f800000, 0x3f800000,
+	0x00000000, 0x00000000, 0x00000000,
+	0x3f800000, 0x00000000, 0x00000000,
+	0x3f800000, 0x00000000, 0x00000000,
+	0x3f800000, 0x3f800000,
+};
+
 #define TEXCOORD_LEN 8
 
 static unsigned int gmem_copy_texcoord[TEXCOORD_LEN] = {
@@ -73,12 +82,12 @@
 	gmem_copy_quad[4] = uint2float(shadow->height);
 	gmem_copy_quad[9] = uint2float(shadow->width);
 
-	gmem_copy_quad[0] = 0;
-	gmem_copy_quad[6] = 0;
-	gmem_copy_quad[7] = 0;
-	gmem_copy_quad[10] = 0;
+	gmem_restore_quad[5] = uint2float(shadow->height);
+	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,
+		QUAD_RESTORE_LEN << 2);
 
 	memcpy(shadow->quad_texcoords.hostptr, gmem_copy_texcoord,
 		TEXCOORD_LEN << 2);
@@ -103,6 +112,13 @@
 
 	cmd += QUAD_LEN;
 
+	/* Used by A3XX, but define for both to make the code easier */
+	shadow->quad_vertices_restore.hostptr = cmd;
+	shadow->quad_vertices_restore.gpuaddr =
+		virt2gpu(cmd, &drawctxt->gpustate);
+
+	cmd += QUAD_RESTORE_LEN;
+
 	/* tex coord buffer location (in GPU space) */
 	shadow->quad_texcoords.hostptr = cmd;
 	shadow->quad_texcoords.gpuaddr = virt2gpu(cmd, &drawctxt->gpustate);
@@ -139,27 +155,19 @@
 	drawctxt->pagetable = pagetable;
 	drawctxt->bin_base_offset = 0;
 
-	/* FIXME: Deal with preambles */
+	if (flags & KGSL_CONTEXT_PREAMBLE)
+		drawctxt->flags |= CTXT_FLAGS_PREAMBLE;
 
-	ret = adreno_dev->gpudev->ctxt_gpustate_shadow(adreno_dev, drawctxt);
+	if (flags & KGSL_CONTEXT_NO_GMEM_ALLOC)
+		drawctxt->flags |= CTXT_FLAGS_NOGMEMALLOC;
+
+	ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt);
 	if (ret)
 		goto err;
 
-	/* Save the shader instruction memory on context switching */
-	drawctxt->flags |= CTXT_FLAGS_SHADER_SAVE;
-
-	if (!(flags & KGSL_CONTEXT_NO_GMEM_ALLOC)) {
-		/* create gmem shadow */
-		ret = adreno_dev->gpudev->ctxt_gmem_shadow(adreno_dev,
-			drawctxt);
-		if (ret != 0)
-			goto err;
-	}
-
 	context->devctxt = drawctxt;
 	return 0;
 err:
-	kgsl_sharedmem_free(&drawctxt->gpustate);
 	kfree(drawctxt);
 	return ret;
 }
diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h
index 3c3a853..9a7ae3f 100644
--- a/drivers/gpu/msm/adreno_drawctxt.h
+++ b/drivers/gpu/msm/adreno_drawctxt.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -30,12 +30,16 @@
 #define CTXT_FLAGS_GMEM_SAVE		0x00000200
 /* gmem can be restored from shadow */
 #define CTXT_FLAGS_GMEM_RESTORE		0x00000400
+/* preamble packed in cmdbuffer for context switching */
+#define CTXT_FLAGS_PREAMBLE		0x00000800
 /* shader must be copied to shadow */
 #define CTXT_FLAGS_SHADER_SAVE		0x00002000
 /* shader can be restored from shadow */
 #define CTXT_FLAGS_SHADER_RESTORE	0x00004000
 /* Context has caused a GPU hang */
 #define CTXT_FLAGS_GPU_HANG		0x00008000
+/* Specifies there is no need to save GMEM */
+#define CTXT_FLAGS_NOGMEMALLOC          0x00010000
 
 struct kgsl_device;
 struct adreno_device;
@@ -46,37 +50,56 @@
 struct gmem_shadow_t {
 	struct kgsl_memdesc gmemshadow;	/* Shadow buffer address */
 
-	/* 256 KB GMEM surface = 4 bytes-per-pixel x 256 pixels/row x
-	* 256 rows. */
-	/* width & height must be a multiples of 32, in case tiled textures
-	 * are used. */
-	enum COLORFORMATX format;
+	/*
+	 * 256 KB GMEM surface = 4 bytes-per-pixel x 256 pixels/row x
+	 * 256 rows. Width & height must be multiples of 32 in case tiled
+	 * textures are used
+	*/
+
+	enum COLORFORMATX format; /* Unused on A3XX */
 	unsigned int size;	/* Size of surface used to store GMEM */
 	unsigned int width;	/* Width of surface used to store GMEM */
 	unsigned int height;	/* Height of surface used to store GMEM */
 	unsigned int pitch;	/* Pitch of surface used to store GMEM */
 	unsigned int gmem_pitch;	/* Pitch value used for GMEM */
-	unsigned int *gmem_save_commands;
-	unsigned int *gmem_restore_commands;
+	unsigned int *gmem_save_commands;    /* Unused on A3XX */
+	unsigned int *gmem_restore_commands; /* Unused on A3XX */
 	unsigned int gmem_save[3];
 	unsigned int gmem_restore[3];
 	struct kgsl_memdesc quad_vertices;
 	struct kgsl_memdesc quad_texcoords;
+	struct kgsl_memdesc quad_vertices_restore;
 };
 
 struct adreno_context {
 	uint32_t flags;
 	struct kgsl_pagetable *pagetable;
 	struct kgsl_memdesc gpustate;
-	unsigned int reg_save[3];
 	unsigned int reg_restore[3];
 	unsigned int shader_save[3];
-	unsigned int shader_fixup[3];
 	unsigned int shader_restore[3];
-	unsigned int chicken_restore[3];
-	unsigned int bin_base_offset;
+
 	/* Information of the GMEM shadow that is created in context create */
 	struct gmem_shadow_t context_gmem_shadow;
+
+	/* A2XX specific items */
+	unsigned int reg_save[3];
+	unsigned int shader_fixup[3];
+	unsigned int chicken_restore[3];
+	unsigned int bin_base_offset;
+
+	/* A3XX specific items */
+	unsigned int regconstant_save[3];
+	unsigned int constant_restore[3];
+	unsigned int hlsqcontrol_restore[3];
+	unsigned int save_fixup[3];
+	unsigned int restore_fixup[3];
+	struct kgsl_memdesc shader_load_commands[2];
+	struct kgsl_memdesc shader_save_commands[4];
+	struct kgsl_memdesc constant_save_commands[3];
+	struct kgsl_memdesc constant_load_commands[3];
+	struct kgsl_memdesc cond_execs[4];
+	struct kgsl_memdesc hlsqcontrol_restore_commands[1];
 };
 
 int adreno_drawctxt_create(struct kgsl_device *device,
@@ -91,7 +114,7 @@
 				struct adreno_context *drawctxt,
 				unsigned int flags);
 void adreno_drawctxt_set_bin_base_offset(struct kgsl_device *device,
-				      struct kgsl_context *context,
+					struct kgsl_context *context,
 					unsigned int offset);
 
 /* GPU context switch helper functions */
diff --git a/drivers/gpu/msm/adreno_pm4types.h b/drivers/gpu/msm/adreno_pm4types.h
index 8aea58c..1dffc32 100644
--- a/drivers/gpu/msm/adreno_pm4types.h
+++ b/drivers/gpu/msm/adreno_pm4types.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -157,6 +157,18 @@
 
 #define CP_SET_PROTECTED_MODE  0x5f /* sets the register protection mode */
 
+/*
+ * for a3xx
+ */
+
+#define CP_LOAD_STATE 0x30 /* load high level sequencer command */
+
+#define CP_LOADSTATE_DSTOFFSET_SHIFT 0x00000000
+#define CP_LOADSTATE_STATESRC_SHIFT 0x00000010
+#define CP_LOADSTATE_STATEBLOCKID_SHIFT 0x00000013
+#define CP_LOADSTATE_NUMOFUNITS_SHIFT 0x00000016
+#define CP_LOADSTATE_STATETYPE_SHIFT 0x00000000
+#define CP_LOADSTATE_EXTSRCADDR_SHIFT 0x00000002
 
 /* packet header building macros */
 #define cp_type0_packet(regindx, cnt) \
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 7f054b1..98e3810 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -24,6 +24,7 @@
 #include "kgsl_pwrctrl.h"
 
 #include "a2xx_reg.h"
+#include "a3xx_reg.h"
 
 #define INVALID_RB_CMD 0xaaaaaaaa
 #define NUM_DWORDS_OF_RINGBUFFER_HISTORY 100
@@ -362,29 +363,160 @@
 	}
 }
 
-static int adreno_dump(struct kgsl_device *device)
+static void adreno_dump_a3xx(struct kgsl_device *device)
 {
 	unsigned int r1, r2, r3, rbbm_status;
-	unsigned int cp_ib1_base, cp_ib1_bufsz, cp_stat;
-	unsigned int cp_ib2_base, cp_ib2_bufsz;
-	unsigned int pt_base, cur_pt_base;
-	unsigned int cp_rb_base, rb_count;
-	unsigned int cp_rb_wptr, cp_rb_rptr;
-	unsigned int i;
-	int result = 0;
-	uint32_t *rb_copy;
-	const uint32_t *rb_vaddr;
-	int num_item = 0;
-	int read_idx, write_idx;
-	unsigned int ts_processed;
-
-	static struct ib_list ib_list;
-
+	unsigned int cp_stat, rb_count;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 
-	mb();
+	kgsl_regread(device, adreno_dev->gpudev->reg_rbbm_status, &rbbm_status);
+	KGSL_LOG_DUMP(device, "RBBM:   STATUS   = %08X\n", rbbm_status);
 
-	kgsl_regread(device, REG_RBBM_STATUS, &rbbm_status);
+	{
+		struct log_field lines[] = {
+			{rbbm_status & BIT(0),  "HI busy     "},
+			{rbbm_status & BIT(1),  "CP ME busy  "},
+			{rbbm_status & BIT(2),  "CP PFP busy "},
+			{rbbm_status & BIT(14), "CP NRT busy "},
+			{rbbm_status & BIT(15), "VBIF busy   "},
+			{rbbm_status & BIT(16), "TSE busy    "},
+			{rbbm_status & BIT(17), "RAS busy    "},
+			{rbbm_status & BIT(18), "RB busy     "},
+			{rbbm_status & BIT(19), "PC DCALL bsy"},
+			{rbbm_status & BIT(20), "PC VSD busy "},
+			{rbbm_status & BIT(21), "VFD busy    "},
+			{rbbm_status & BIT(22), "VPC busy    "},
+			{rbbm_status & BIT(23), "UCHE busy   "},
+			{rbbm_status & BIT(24), "SP busy     "},
+			{rbbm_status & BIT(25), "TPL1 busy   "},
+			{rbbm_status & BIT(26), "MARB busy   "},
+			{rbbm_status & BIT(27), "VSC busy    "},
+			{rbbm_status & BIT(28), "ARB busy    "},
+			{rbbm_status & BIT(29), "HLSQ busy   "},
+			{rbbm_status & BIT(30), "GPU bsy noHC"},
+			{rbbm_status & BIT(31), "GPU busy    "},
+			};
+		adreno_dump_fields(device, " STATUS=", lines,
+				ARRAY_SIZE(lines));
+	}
+
+	kgsl_regread(device, REG_CP_RB_BASE, &r1);
+	kgsl_regread(device, REG_CP_RB_CNTL, &r2);
+	rb_count = 2 << (r2 & (BIT(6) - 1));
+	kgsl_regread(device, REG_CP_RB_RPTR_ADDR, &r3);
+	KGSL_LOG_DUMP(device,
+		"CP_RB:  BASE = %08X | CNTL   = %08X | RPTR_ADDR = %08X"
+		"| rb_count = %08X\n", r1, r2, r3, rb_count);
+
+	kgsl_regread(device, REG_CP_RB_RPTR, &r1);
+	kgsl_regread(device, REG_CP_RB_WPTR, &r2);
+	kgsl_regread(device, REG_CP_RB_RPTR_WR, &r3);
+	KGSL_LOG_DUMP(device,
+		"        RPTR = %08X | WPTR   = %08X | RPTR_WR   = %08X"
+		"\n", r1, r2, r3);
+
+	kgsl_regread(device, REG_CP_IB1_BASE, &r1);
+	kgsl_regread(device, REG_CP_IB1_BUFSZ, &r2);
+	KGSL_LOG_DUMP(device, "CP_IB1: BASE = %08X | BUFSZ  = %d\n", r1, r2);
+
+	kgsl_regread(device, REG_CP_ME_CNTL, &r1);
+	kgsl_regread(device, REG_CP_ME_STATUS, &r2);
+	KGSL_LOG_DUMP(device, "CP_ME:  CNTL = %08X | STATUS = %08X\n", r1, r2);
+
+	kgsl_regread(device, REG_CP_STAT, &cp_stat);
+	KGSL_LOG_DUMP(device, "CP_STAT      = %08X\n", cp_stat);
+#ifndef CONFIG_MSM_KGSL_PSTMRTMDMP_CP_STAT_NO_DETAIL
+	{
+		struct log_field lns[] = {
+			{cp_stat & BIT(0), "WR_BSY     0"},
+			{cp_stat & BIT(1), "RD_RQ_BSY  1"},
+			{cp_stat & BIT(2), "RD_RTN_BSY 2"},
+		};
+		adreno_dump_fields(device, "    MIU=", lns, ARRAY_SIZE(lns));
+	}
+	{
+		struct log_field lns[] = {
+			{cp_stat & BIT(5), "RING_BUSY  5"},
+			{cp_stat & BIT(6), "NDRCTS_BSY 6"},
+			{cp_stat & BIT(7), "NDRCT2_BSY 7"},
+			{cp_stat & BIT(9), "ST_BUSY    9"},
+			{cp_stat & BIT(10), "BUSY      10"},
+		};
+		adreno_dump_fields(device, "    CSF=", lns, ARRAY_SIZE(lns));
+	}
+	{
+		struct log_field lns[] = {
+			{cp_stat & BIT(11), "RNG_Q_BSY 11"},
+			{cp_stat & BIT(12), "NDRCTS_Q_B12"},
+			{cp_stat & BIT(13), "NDRCT2_Q_B13"},
+			{cp_stat & BIT(16), "ST_QUEUE_B16"},
+			{cp_stat & BIT(17), "PFP_BUSY  17"},
+		};
+		adreno_dump_fields(device, "   RING=", lns, ARRAY_SIZE(lns));
+	}
+	{
+		struct log_field lns[] = {
+			{cp_stat & BIT(3), "RBIU_BUSY  3"},
+			{cp_stat & BIT(4), "RCIU_BUSY  4"},
+			{cp_stat & BIT(8), "EVENT_BUSY 8"},
+			{cp_stat & BIT(18), "MQ_RG_BSY 18"},
+			{cp_stat & BIT(19), "MQ_NDRS_BS19"},
+			{cp_stat & BIT(20), "MQ_NDR2_BS20"},
+			{cp_stat & BIT(21), "MIU_WC_STL21"},
+			{cp_stat & BIT(22), "CP_NRT_BSY22"},
+			{cp_stat & BIT(23), "3D_BUSY   23"},
+			{cp_stat & BIT(26), "ME_BUSY   26"},
+			{cp_stat & BIT(27), "RB_FFO_BSY27"},
+			{cp_stat & BIT(28), "CF_FFO_BSY28"},
+			{cp_stat & BIT(29), "PS_FFO_BSY29"},
+			{cp_stat & BIT(30), "VS_FFO_BSY30"},
+			{cp_stat & BIT(31), "CP_BUSY   31"},
+		};
+		adreno_dump_fields(device, " CP_STT=", lns, ARRAY_SIZE(lns));
+	}
+#endif
+
+	kgsl_regread(device, A3XX_RBBM_INT_0_STATUS, &r1);
+	KGSL_LOG_DUMP(device, "MSTR_INT_SGNL = %08X\n", r1);
+	{
+		struct log_field ints[] = {
+			{r1 & BIT(0),  "RBBM_GPU_IDLE 0"},
+			{r1 & BIT(1),  "RBBM_AHB_ERROR 1"},
+			{r1 & BIT(2),  "RBBM_REG_TIMEOUT 2"},
+			{r1 & BIT(3),  "RBBM_ME_MS_TIMEOUT 3"},
+			{r1 & BIT(4),  "RBBM_PFP_MS_TIMEOUT 4"},
+			{r1 & BIT(5),  "RBBM_ATB_BUS_OVERFLOW 5"},
+			{r1 & BIT(6),  "VFD_ERROR 6"},
+			{r1 & BIT(7),  "CP_SW_INT 7"},
+			{r1 & BIT(8),  "CP_T0_PACKET_IN_IB 8"},
+			{r1 & BIT(9),  "CP_OPCODE_ERROR 9"},
+			{r1 & BIT(10), "CP_RESERVED_BIT_ERROR 10"},
+			{r1 & BIT(11), "CP_HW_FAULT 11"},
+			{r1 & BIT(12), "CP_DMA 12"},
+			{r1 & BIT(13), "CP_IB2_INT 13"},
+			{r1 & BIT(14), "CP_IB1_INT 14"},
+			{r1 & BIT(15), "CP_RB_INT 15"},
+			{r1 & BIT(16), "CP_REG_PROTECT_FAULT 16"},
+			{r1 & BIT(17), "CP_RB_DONE_TS 17"},
+			{r1 & BIT(18), "CP_VS_DONE_TS 18"},
+			{r1 & BIT(19), "CP_PS_DONE_TS 19"},
+			{r1 & BIT(20), "CACHE_FLUSH_TS 20"},
+			{r1 & BIT(21), "CP_AHB_ERROR_HALT 21"},
+			{r1 & BIT(24), "MISC_HANG_DETECT 24"},
+			{r1 & BIT(25), "UCHE_OOB_ACCESS 25"},
+		};
+		adreno_dump_fields(device, "INT_SGNL=", ints, ARRAY_SIZE(ints));
+	}
+}
+
+static void adreno_dump_a2xx(struct kgsl_device *device)
+{
+	unsigned int r1, r2, r3, rbbm_status;
+	unsigned int cp_stat, rb_count;
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+
+	kgsl_regread(device, adreno_dev->gpudev->reg_rbbm_status, &rbbm_status);
+
 	kgsl_regread(device, REG_RBBM_PM_OVERRIDE1, &r2);
 	kgsl_regread(device, REG_RBBM_PM_OVERRIDE2, &r3);
 	KGSL_LOG_DUMP(device, "RBBM:   STATUS   = %08X | PM_OVERRIDE1 = %08X | "
@@ -426,37 +558,33 @@
 				ARRAY_SIZE(lines));
 	}
 
-	kgsl_regread(device, REG_CP_RB_BASE, &cp_rb_base);
+	kgsl_regread(device, REG_CP_RB_BASE, &r1);
 	kgsl_regread(device, REG_CP_RB_CNTL, &r2);
 	rb_count = 2 << (r2 & (BIT(6)-1));
 	kgsl_regread(device, REG_CP_RB_RPTR_ADDR, &r3);
 	KGSL_LOG_DUMP(device,
 		"CP_RB:  BASE = %08X | CNTL   = %08X | RPTR_ADDR = %08X"
-		" | rb_count = %08X\n", cp_rb_base, r2, r3, rb_count);
+		"| rb_count = %08X\n", r1, r2, r3, rb_count);
 	{
 		struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 		if (rb->sizedwords != rb_count)
 			rb_count = rb->sizedwords;
 	}
 
-	kgsl_regread(device, REG_CP_RB_RPTR, &cp_rb_rptr);
-	kgsl_regread(device, REG_CP_RB_WPTR, &cp_rb_wptr);
+	kgsl_regread(device, REG_CP_RB_RPTR, &r1);
+	kgsl_regread(device, REG_CP_RB_WPTR, &r2);
 	kgsl_regread(device, REG_CP_RB_RPTR_WR, &r3);
 	KGSL_LOG_DUMP(device,
 		"        RPTR = %08X | WPTR   = %08X | RPTR_WR   = %08X"
-		"\n", cp_rb_rptr, cp_rb_wptr, r3);
+		"\n", r1, r2, r3);
 
-	kgsl_regread(device, REG_CP_IB1_BASE, &cp_ib1_base);
-	kgsl_regread(device, REG_CP_IB1_BUFSZ, &cp_ib1_bufsz);
-	KGSL_LOG_DUMP(device,
-		"CP_IB1: BASE = %08X | BUFSZ  = %d\n", cp_ib1_base,
-		cp_ib1_bufsz);
+	kgsl_regread(device, REG_CP_IB1_BASE, &r1);
+	kgsl_regread(device, REG_CP_IB1_BUFSZ, &r2);
+	KGSL_LOG_DUMP(device, "CP_IB1: BASE = %08X | BUFSZ  = %d\n", r1, r2);
 
-	kgsl_regread(device, REG_CP_IB2_BASE, &cp_ib2_base);
-	kgsl_regread(device, REG_CP_IB2_BUFSZ, &cp_ib2_bufsz);
-	KGSL_LOG_DUMP(device,
-		"CP_IB2: BASE = %08X | BUFSZ  = %d\n", cp_ib2_base,
-		cp_ib2_bufsz);
+	kgsl_regread(device, REG_CP_IB2_BASE, &r1);
+	kgsl_regread(device, REG_CP_IB2_BUFSZ, &r2);
+	KGSL_LOG_DUMP(device, "CP_IB2: BASE = %08X | BUFSZ  = %d\n", r1, r2);
 
 	kgsl_regread(device, REG_CP_INT_CNTL, &r1);
 	kgsl_regread(device, REG_CP_INT_STATUS, &r2);
@@ -541,11 +669,10 @@
 
 	kgsl_regread(device, MH_MMU_MPU_END, &r1);
 	kgsl_regread(device, MH_MMU_VA_RANGE, &r2);
-	pt_base = kgsl_mmu_get_current_ptbase(device);
+	r3 = kgsl_mmu_get_current_ptbase(device);
 	KGSL_LOG_DUMP(device,
 		"        MPU_END    = %08X | VA_RANGE = %08X | PT_BASE  ="
-		" %08X\n", r1, r2, pt_base);
-	cur_pt_base = pt_base;
+		" %08X\n", r1, r2, r3);
 
 	KGSL_LOG_DUMP(device, "PAGETABLE SIZE: %08X ", KGSL_PAGETABLE_SIZE);
 
@@ -556,6 +683,46 @@
 	kgsl_regread(device, MH_INTERRUPT_STATUS, &r2);
 	KGSL_LOG_DUMP(device,
 		"MH_INTERRUPT: MASK = %08X | STATUS   = %08X\n", r1, r2);
+}
+
+static int adreno_dump(struct kgsl_device *device)
+{
+	unsigned int cp_ib1_base, cp_ib1_bufsz;
+	unsigned int cp_ib2_base, cp_ib2_bufsz;
+	unsigned int pt_base, cur_pt_base;
+	unsigned int cp_rb_base, cp_rb_ctrl, rb_count;
+	unsigned int cp_rb_wptr, cp_rb_rptr;
+	unsigned int i;
+	int result = 0;
+	uint32_t *rb_copy;
+	const uint32_t *rb_vaddr;
+	int num_item = 0;
+	int read_idx, write_idx;
+	unsigned int ts_processed;
+
+	static struct ib_list ib_list;
+
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+
+	mb();
+
+	if (adreno_is_a2xx(adreno_dev))
+		adreno_dump_a2xx(device);
+	else if (adreno_is_a3xx(adreno_dev))
+		adreno_dump_a3xx(device);
+
+	pt_base = kgsl_mmu_get_current_ptbase(device);
+	cur_pt_base = pt_base;
+
+	kgsl_regread(device, REG_CP_RB_BASE, &cp_rb_base);
+	kgsl_regread(device, REG_CP_RB_CNTL, &cp_rb_ctrl);
+	rb_count = 2 << (cp_rb_ctrl & (BIT(6) - 1));
+	kgsl_regread(device, REG_CP_RB_RPTR, &cp_rb_rptr);
+	kgsl_regread(device, REG_CP_RB_WPTR, &cp_rb_wptr);
+	kgsl_regread(device, REG_CP_IB1_BASE, &cp_ib1_base);
+	kgsl_regread(device, REG_CP_IB1_BUFSZ, &cp_ib1_bufsz);
+	kgsl_regread(device, REG_CP_IB2_BASE, &cp_ib2_base);
+	kgsl_regread(device, REG_CP_IB2_BUFSZ, &cp_ib2_bufsz);
 
 	ts_processed = device->ftbl->readtimestamp(device,
 		KGSL_TIMESTAMP_RETIRED);
@@ -689,6 +856,9 @@
 	else if (adreno_is_a22x(adreno_dev))
 		adreno_dump_regs(device, a220_registers,
 			a220_registers_count);
+	else if (adreno_is_a3xx(adreno_dev))
+		adreno_dump_regs(device, a3xx_registers,
+			a3xx_registers_count);
 
 error_vfree:
 	vfree(rb_copy);
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 7ace67a..a5c20dc 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -24,28 +24,11 @@
 #include "adreno_ringbuffer.h"
 
 #include "a2xx_reg.h"
+#include "a3xx_reg.h"
 
 #define GSL_RB_NOP_SIZEDWORDS				2
-/* protected mode error checking below register address 0x800
-*  note: if CP_INTERRUPT packet is used then checking needs
-*  to change to below register address 0x7C8
-*/
-#define GSL_RB_PROTECTED_MODE_CONTROL		0x200001F2
 
-/* Firmware file names
- * Legacy names must remain but replacing macro names to
- * match current kgsl model.
- * a200 is yamato
- * a220 is leia
- */
-#define A200_PFP_FW "yamato_pfp.fw"
-#define A200_PM4_FW "yamato_pm4.fw"
-#define A220_PFP_470_FW "leia_pfp_470.fw"
-#define A220_PM4_470_FW "leia_pm4_470.fw"
-#define A225_PFP_FW "a225_pfp.fw"
-#define A225_PM4_FW "a225_pm4.fw"
-
-static void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb)
+void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb)
 {
 	BUG_ON(rb->wptr == 0);
 
@@ -104,8 +87,7 @@
 	} while ((freecmds != 0) && (freecmds <= numcmds));
 }
 
-
-static unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb,
+unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb,
 					     unsigned int numcmds)
 {
 	unsigned int	*ptr = NULL;
@@ -231,10 +213,11 @@
 	KGSL_DRV_INFO(device, "loading pfp ucode version: %d\n",
 		adreno_dev->pfp_fw[0]);
 
-	adreno_regwrite(device, REG_CP_PFP_UCODE_ADDR, 0);
+	adreno_regwrite(device, adreno_dev->gpudev->reg_cp_pfp_ucode_addr, 0);
 	for (i = 1; i < adreno_dev->pfp_fw_size; i++)
-		adreno_regwrite(device, REG_CP_PFP_UCODE_DATA,
-				     adreno_dev->pfp_fw[i]);
+		adreno_regwrite(device,
+			adreno_dev->gpudev->reg_cp_pfp_ucode_data,
+			adreno_dev->pfp_fw[i]);
 err:
 	return ret;
 }
@@ -244,10 +227,9 @@
 	int status;
 	/*cp_rb_cntl_u cp_rb_cntl; */
 	union reg_cp_rb_cntl cp_rb_cntl;
-	unsigned int *cmds, rb_cntl;
+	unsigned int rb_cntl;
 	struct kgsl_device *device = rb->device;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	uint cmds_gpu;
 
 	if (rb->flags & KGSL_FLAGS_STARTED)
 		return 0;
@@ -263,12 +245,15 @@
 	kgsl_sharedmem_set(&rb->buffer_desc, 0, 0xAA,
 			   (rb->sizedwords << 2));
 
-	adreno_regwrite(device, REG_CP_RB_WPTR_BASE,
-			     (rb->memptrs_desc.gpuaddr
-			      + GSL_RB_MEMPTRS_WPTRPOLL_OFFSET));
+	if (adreno_is_a2xx(adreno_dev)) {
+		adreno_regwrite(device, REG_CP_RB_WPTR_BASE,
+			(rb->memptrs_desc.gpuaddr
+			+ GSL_RB_MEMPTRS_WPTRPOLL_OFFSET));
 
-	/* setup WPTR delay */
-	adreno_regwrite(device, REG_CP_RB_WPTR_DELAY, 0 /*0x70000010 */);
+		/* setup WPTR delay */
+		adreno_regwrite(device, REG_CP_RB_WPTR_DELAY,
+			0 /*0x70000010 */);
+	}
 
 	/*setup REG_CP_RB_CNTL */
 	adreno_regread(device, REG_CP_RB_CNTL, &rb_cntl);
@@ -287,7 +272,11 @@
 	*/
 	cp_rb_cntl.f.rb_blksz = ilog2(KGSL_RB_BLKSIZE >> 3);
 
-	cp_rb_cntl.f.rb_poll_en = GSL_RB_CNTL_POLL_EN; /* WPTR polling */
+	if (adreno_is_a2xx(adreno_dev)) {
+		/* WPTR polling */
+		cp_rb_cntl.f.rb_poll_en = GSL_RB_CNTL_POLL_EN;
+	}
+
 	/* mem RPTR writebacks */
 	cp_rb_cntl.f.rb_no_update =  GSL_RB_CNTL_NO_UPDATE;
 
@@ -299,8 +288,36 @@
 			     rb->memptrs_desc.gpuaddr +
 			     GSL_RB_MEMPTRS_RPTR_OFFSET);
 
-	/* explicitly clear all cp interrupts */
-	adreno_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF);
+	if (adreno_is_a3xx(adreno_dev)) {
+		/* enable access protection to privileged registers */
+		adreno_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007);
+
+		/* RBBM registers */
+		adreno_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040);
+		adreno_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080);
+		adreno_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC);
+		adreno_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108);
+		adreno_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140);
+		adreno_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400);
+
+		/* CP registers */
+		adreno_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700);
+		adreno_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8);
+		adreno_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0);
+		adreno_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178);
+		adreno_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180);
+
+		/* RB registers */
+		adreno_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300);
+
+		/* VBIF registers */
+		adreno_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000);
+	}
+
+	if (adreno_is_a2xx(adreno_dev)) {
+		/* explicitly clear all cp interrupts */
+		adreno_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF);
+	}
 
 	/* setup scratch/timestamp */
 	adreno_regwrite(device, REG_SCRATCH_ADDR,
@@ -329,55 +346,8 @@
 	/* clear ME_HALT to start micro engine */
 	adreno_regwrite(device, REG_CP_ME_CNTL, 0);
 
-	/* ME_INIT */
-	cmds = adreno_ringbuffer_allocspace(rb, 19);
-	cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*(rb->wptr-19);
-
-	GSL_RB_WRITE(cmds, cmds_gpu, CP_HDR_ME_INIT);
-	/* All fields present (bits 9:0) */
-	GSL_RB_WRITE(cmds, cmds_gpu, 0x000003ff);
-	/* Disable/Enable Real-Time Stream processing (present but ignored) */
-	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
-	/* Enable (2D <-> 3D) implicit synchronization (present but ignored) */
-	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
-
-	GSL_RB_WRITE(cmds, cmds_gpu,
-		SUBBLOCK_OFFSET(REG_RB_SURFACE_INFO));
-	GSL_RB_WRITE(cmds, cmds_gpu,
-		SUBBLOCK_OFFSET(REG_PA_SC_WINDOW_OFFSET));
-	GSL_RB_WRITE(cmds, cmds_gpu,
-		SUBBLOCK_OFFSET(REG_VGT_MAX_VTX_INDX));
-	GSL_RB_WRITE(cmds, cmds_gpu,
-		SUBBLOCK_OFFSET(REG_SQ_PROGRAM_CNTL));
-	GSL_RB_WRITE(cmds, cmds_gpu,
-		SUBBLOCK_OFFSET(REG_RB_DEPTHCONTROL));
-	GSL_RB_WRITE(cmds, cmds_gpu,
-		SUBBLOCK_OFFSET(REG_PA_SU_POINT_SIZE));
-	GSL_RB_WRITE(cmds, cmds_gpu,
-		SUBBLOCK_OFFSET(REG_PA_SC_LINE_CNTL));
-	GSL_RB_WRITE(cmds, cmds_gpu,
-		SUBBLOCK_OFFSET(REG_PA_SU_POLY_OFFSET_FRONT_SCALE));
-
-	/* Instruction memory size: */
-	GSL_RB_WRITE(cmds, cmds_gpu,
-		     (adreno_encode_istore_size(adreno_dev)
-		      | adreno_dev->pix_shader_start));
-	/* Maximum Contexts */
-	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000001);
-	/* Write Confirm Interval and The CP will wait the
-	* wait_interval * 16 clocks between polling  */
-	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
-
-	/* NQ and External Memory Swap */
-	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
-	/* Protected mode error checking */
-	GSL_RB_WRITE(cmds, cmds_gpu, GSL_RB_PROTECTED_MODE_CONTROL);
-	/* Disable header dumping and Header dump address */
-	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
-	/* Header dump size */
-	GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
-
-	adreno_ringbuffer_submit(rb);
+	/* ME init is GPU specific, so jump into the sub-function */
+	adreno_dev->gpudev->rb_init(adreno_dev, rb);
 
 	/* idle device to validate ME INIT */
 	status = adreno_idle(device, KGSL_TIMEOUT_DEFAULT);
@@ -458,6 +428,7 @@
 				unsigned int flags, unsigned int *cmds,
 				int sizedwords)
 {
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
 	unsigned int *ringcmds;
 	unsigned int timestamp;
 	unsigned int total_sizedwords = sizedwords + 6;
@@ -471,6 +442,9 @@
 	total_sizedwords += !(flags & KGSL_CMD_FLAGS_NO_TS_CMP) ? 7 : 0;
 	total_sizedwords += !(flags & KGSL_CMD_FLAGS_NOT_KERNEL_CMD) ? 2 : 0;
 
+	if (adreno_is_a3xx(adreno_dev))
+		total_sizedwords += 7;
+
 	ringcmds = adreno_ringbuffer_allocspace(rb, total_sizedwords);
 	rcmd_gpu = rb->buffer_desc.gpuaddr
 		+ sizeof(uint)*(rb->wptr-total_sizedwords);
@@ -504,6 +478,21 @@
 	/* start-of-pipeline and end-of-pipeline timestamps */
 	GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type0_packet(REG_CP_TIMESTAMP, 1));
 	GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp);
+
+	if (adreno_is_a3xx(adreno_dev)) {
+		/*
+		 * FLush HLSQ lazy updates to make sure there are no
+		 * rsources pending for indirect loads after the timestamp
+		 */
+
+		GSL_RB_WRITE(ringcmds, rcmd_gpu,
+			cp_type3_packet(CP_EVENT_WRITE, 1));
+		GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x07); /* HLSQ_FLUSH */
+		GSL_RB_WRITE(ringcmds, rcmd_gpu,
+			cp_type3_packet(CP_WAIT_FOR_IDLE, 1));
+		GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00);
+	}
+
 	GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 3));
 	GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
 	GSL_RB_WRITE(ringcmds, rcmd_gpu,
@@ -527,6 +516,15 @@
 		GSL_RB_WRITE(ringcmds, rcmd_gpu, CP_INT_CNTL__RB_INT_MASK);
 	}
 
+	if (adreno_is_a3xx(adreno_dev)) {
+		/* Dummy set-constant to trigger context rollover */
+		GSL_RB_WRITE(ringcmds, rcmd_gpu,
+			cp_type3_packet(CP_SET_CONSTANT, 2));
+		GSL_RB_WRITE(ringcmds, rcmd_gpu,
+			(0x4<<16)|(A3XX_HLSQ_CL_KERNEL_GROUP_X_REG - 0x2000));
+		GSL_RB_WRITE(ringcmds, rcmd_gpu, 0);
+	}
+
 	adreno_ringbuffer_submit(rb);
 
 	/* return timestamp of issued coREG_ands */
@@ -561,6 +559,7 @@
 	unsigned int *cmds;
 	unsigned int i;
 	struct adreno_context *drawctxt;
+	unsigned int start_index = 0;
 
 	if (device->state & KGSL_STATE_HUNG)
 		return -EBUSY;
@@ -583,7 +582,16 @@
 			" submission, size %x\n", numibs * 3);
 		return -ENOMEM;
 	}
-	for (i = 0; i < numibs; i++) {
+
+	/*When preamble is enabled, the preamble buffer with state restoration
+	commands are stored in the first node of the IB chain. We can skip that
+	if a context switch hasn't occured */
+
+	if (drawctxt->flags & CTXT_FLAGS_PREAMBLE &&
+		adreno_dev->drawctxt_active == drawctxt)
+		start_index = 1;
+
+	for (i = start_index; i < numibs; i++) {
 		(void)kgsl_cffdump_parse_ibs(dev_priv, NULL,
 			ibdesc[i].gpuaddr, ibdesc[i].sizedwords, false);
 
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index a90b0cb..caedf26 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -105,6 +105,13 @@
 
 #define GSL_RB_CNTL_POLL_EN 0x0 /* disable */
 
+/*
+ * protected mode error checking below register address 0x800
+ * note: if CP_INTERRUPT packet is used then checking needs
+ * to change to below register address 0x7C8
+ */
+#define GSL_RB_PROTECTED_MODE_CONTROL		0x200001F2
+
 int adreno_ringbuffer_issueibcmds(struct kgsl_device_private *dev_priv,
 				struct kgsl_context *context,
 				struct kgsl_ibdesc *ibdesc,
@@ -126,6 +133,8 @@
 					unsigned int *cmdaddr,
 					int sizedwords);
 
+void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb);
+
 void kgsl_cp_intrcallback(struct kgsl_device *device);
 
 int adreno_ringbuffer_extract(struct adreno_ringbuffer *rb,
@@ -136,6 +145,9 @@
 adreno_ringbuffer_restore(struct adreno_ringbuffer *rb, unsigned int *rb_buff,
 			int num_rb_contents);
 
+unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb,
+					     unsigned int numcmds);
+
 static inline int adreno_ringbuffer_count(struct adreno_ringbuffer *rb,
 	unsigned int rptr)
 {
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 72df148b..de39ee4 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -139,7 +139,7 @@
  * register
  */
 
-int kgsl_snapshot_dump_indexed_regs(struct kgsl_device *device,
+static int kgsl_snapshot_dump_indexed_regs(struct kgsl_device *device,
 	void *snapshot, int remain, void *priv)
 {
 	struct kgsl_snapshot_indexed_registers *iregs = priv;
@@ -164,7 +164,6 @@
 
 	return (iregs->count * 4) + sizeof(*header);
 }
-EXPORT_SYMBOL(kgsl_snapshot_dump_indexed_regs);
 
 /*
  * kgsl_snapshot_dump_regs - helper function to dump device registers
@@ -220,6 +219,23 @@
 }
 EXPORT_SYMBOL(kgsl_snapshot_dump_regs);
 
+void *kgsl_snapshot_indexed_registers(struct kgsl_device *device,
+		void *snapshot, int *remain,
+		unsigned int index, unsigned int data, unsigned int start,
+		unsigned int count)
+{
+	struct kgsl_snapshot_indexed_registers iregs;
+	iregs.index = index;
+	iregs.data = data;
+	iregs.start = start;
+	iregs.count = count;
+
+	return kgsl_snapshot_add_section(device,
+		 KGSL_SNAPSHOT_SECTION_INDEXED_REGS, snapshot,
+		 remain, kgsl_snapshot_dump_indexed_regs, &iregs);
+}
+EXPORT_SYMBOL(kgsl_snapshot_indexed_registers);
+
 /*
  * kgsl_snapshot - construct a device snapshot
  * @device - device to snapshot
diff --git a/drivers/gpu/msm/kgsl_snapshot.h b/drivers/gpu/msm/kgsl_snapshot.h
index 4fdc8a1..3b72b0f 100644
--- a/drivers/gpu/msm/kgsl_snapshot.h
+++ b/drivers/gpu/msm/kgsl_snapshot.h
@@ -47,6 +47,7 @@
 #define KGSL_SNAPSHOT_SECTION_INDEXED_REGS 0x0501
 #define KGSL_SNAPSHOT_SECTION_ISTORE       0x0801
 #define KGSL_SNAPSHOT_SECTION_DEBUG        0x0901
+#define KGSL_SNAPSHOT_SECTION_DEBUGBUS     0x0A01
 #define KGSL_SNAPSHOT_SECTION_END          0xFFFF
 
 /* OS sub-section header */
@@ -124,15 +125,28 @@
 
 /* Debug data sub-section header */
 
+/* A2XX debug sections */
 #define SNAPSHOT_DEBUG_SX         1
 #define SNAPSHOT_DEBUG_CP         2
 #define SNAPSHOT_DEBUG_SQ         3
 #define SNAPSHOT_DEBUG_SQTHREAD   4
 #define SNAPSHOT_DEBUG_MIU        5
 
+/* A3XX debug sections */
+#define SNAPSHOT_DEBUG_VPC_MEMORY 6
+#define SNAPSHOT_DEBUG_CP_MEQ     7
+#define SNAPSHOT_DEBUG_CP_PM4_RAM 8
+#define SNAPSHOT_DEBUG_CP_PFP_RAM 9
+#define SNAPSHOT_DEBUG_CP_ROQ     10
+
 struct kgsl_snapshot_debug {
 	int type;    /* Type identifier for the attached tata */
-	int size;   /* Size of the section in bytes */
+	int size;   /* Size of the section in dwords */
+} __packed;
+
+struct kgsl_snapshot_debugbus {
+	int id;	   /* Debug bus ID */
+	int count; /* Number of dwords in the dump */
 } __packed;
 
 #ifdef __KERNEL__
@@ -252,8 +266,12 @@
 	unsigned int count; /* Number of values to read from the pair */
 };
 
-int kgsl_snapshot_dump_indexed_regs(struct kgsl_device *device,
-	void *snapshot, int remain, void *priv);
+/* Helper function to snapshot a section of indexed registers */
+
+void *kgsl_snapshot_indexed_registers(struct kgsl_device *device,
+	void *snapshot, int *remain, unsigned int index,
+	unsigned int data, unsigned int start, unsigned int count);
+
 
 #endif
 #endif
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 71bdcde..d2a8879 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -303,6 +303,8 @@
 	struct mxt_info info;
 	struct mxt_finger finger[MXT_MAX_FINGER];
 	unsigned int irq;
+	unsigned int touch_x_size;
+	unsigned int touch_y_size;
 	struct regulator *vcc_ana;
 	struct regulator *vcc_dig;
 	struct regulator *vcc_i2c;
@@ -667,9 +669,9 @@
 
 	x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
 	y = (message->message[2] << 4) | ((message->message[3] & 0xf));
-	if (data->pdata->x_size < 1024)
+	if (data->touch_x_size < 1024)
 		x = x >> 2;
-	if (data->pdata->y_size < 1024)
+	if (data->touch_y_size < 1024)
 		y = y >> 2;
 
 	area = message->message[4];
@@ -1362,6 +1364,12 @@
 
 }
 
+static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
+{
+	return (regulator_count_voltages(reg) > 0) ?
+		regulator_set_optimum_mode(reg, load_uA) : 0;
+}
+
 static int mxt_power_on(struct mxt_data *data, bool on)
 {
 	int rc;
@@ -1369,7 +1377,7 @@
 	if (on == false)
 		goto power_off;
 
-	rc = regulator_set_optimum_mode(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
+	rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
 	if (rc < 0) {
 		dev_err(&data->client->dev,
 			"Regulator vcc_ana set_opt failed rc=%d\n", rc);
@@ -1384,8 +1392,8 @@
 	}
 
 	if (data->pdata->digital_pwr_regulator) {
-		rc = regulator_set_optimum_mode(data->vcc_dig,
-						MXT_ACTIVE_LOAD_DIG_UA);
+		rc = reg_set_optimum_mode_check(data->vcc_dig,
+					MXT_ACTIVE_LOAD_DIG_UA);
 		if (rc < 0) {
 			dev_err(&data->client->dev,
 				"Regulator vcc_dig set_opt failed rc=%d\n",
@@ -1402,7 +1410,7 @@
 	}
 
 	if (data->pdata->i2c_pull_up) {
-		rc = regulator_set_optimum_mode(data->vcc_i2c, MXT_I2C_LOAD_UA);
+		rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
 		if (rc < 0) {
 			dev_err(&data->client->dev,
 				"Regulator vcc_i2c set_opt failed rc=%d\n", rc);
@@ -1423,28 +1431,28 @@
 
 error_reg_en_vcc_i2c:
 	if (data->pdata->i2c_pull_up)
-		regulator_set_optimum_mode(data->vcc_i2c, 0);
+		reg_set_optimum_mode_check(data->vcc_i2c, 0);
 error_reg_opt_i2c:
 	if (data->pdata->digital_pwr_regulator)
 		regulator_disable(data->vcc_dig);
 error_reg_en_vcc_dig:
 	if (data->pdata->digital_pwr_regulator)
-		regulator_set_optimum_mode(data->vcc_dig, 0);
+		reg_set_optimum_mode_check(data->vcc_dig, 0);
 error_reg_opt_vcc_dig:
 	regulator_disable(data->vcc_ana);
 error_reg_en_vcc_ana:
-	regulator_set_optimum_mode(data->vcc_ana, 0);
+	reg_set_optimum_mode_check(data->vcc_ana, 0);
 	return rc;
 
 power_off:
-	regulator_set_optimum_mode(data->vcc_ana, 0);
+	reg_set_optimum_mode_check(data->vcc_ana, 0);
 	regulator_disable(data->vcc_ana);
 	if (data->pdata->digital_pwr_regulator) {
-		regulator_set_optimum_mode(data->vcc_dig, 0);
+		reg_set_optimum_mode_check(data->vcc_dig, 0);
 		regulator_disable(data->vcc_dig);
 	}
 	if (data->pdata->i2c_pull_up) {
-		regulator_set_optimum_mode(data->vcc_i2c, 0);
+		reg_set_optimum_mode_check(data->vcc_i2c, 0);
 		regulator_disable(data->vcc_i2c);
 	}
 	msleep(50);
@@ -1560,7 +1568,7 @@
 	if (on == false)
 		goto regulator_hpm;
 
-	rc = regulator_set_optimum_mode(data->vcc_ana, MXT_LPM_LOAD_UA);
+	rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
 	if (rc < 0) {
 		dev_err(&data->client->dev,
 			"Regulator vcc_ana set_opt failed rc=%d\n", rc);
@@ -1568,7 +1576,7 @@
 	}
 
 	if (data->pdata->digital_pwr_regulator) {
-		rc = regulator_set_optimum_mode(data->vcc_dig,
+		rc = reg_set_optimum_mode_check(data->vcc_dig,
 						MXT_LPM_LOAD_DIG_UA);
 		if (rc < 0) {
 			dev_err(&data->client->dev,
@@ -1578,7 +1586,7 @@
 	}
 
 	if (data->pdata->i2c_pull_up) {
-		rc = regulator_set_optimum_mode(data->vcc_i2c,
+		rc = reg_set_optimum_mode_check(data->vcc_i2c,
 						MXT_I2C_LPM_LOAD_UA);
 		if (rc < 0) {
 			dev_err(&data->client->dev,
@@ -1591,7 +1599,7 @@
 
 regulator_hpm:
 
-	rc = regulator_set_optimum_mode(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
+	rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
 	if (rc < 0) {
 		dev_err(&data->client->dev,
 			"Regulator vcc_ana set_opt failed rc=%d\n", rc);
@@ -1599,7 +1607,7 @@
 	}
 
 	if (data->pdata->digital_pwr_regulator) {
-		rc = regulator_set_optimum_mode(data->vcc_dig,
+		rc = reg_set_optimum_mode_check(data->vcc_dig,
 						 MXT_ACTIVE_LOAD_DIG_UA);
 		if (rc < 0) {
 			dev_err(&data->client->dev,
@@ -1609,7 +1617,7 @@
 	}
 
 	if (data->pdata->i2c_pull_up) {
-		rc = regulator_set_optimum_mode(data->vcc_i2c, MXT_I2C_LOAD_UA);
+		rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
 		if (rc < 0) {
 			dev_err(&data->client->dev,
 				"Regulator vcc_i2c set_opt failed rc=%d\n", rc);
@@ -1620,21 +1628,21 @@
 	return 0;
 
 fail_regulator_lpm:
-	regulator_set_optimum_mode(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
+	reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
 	if (data->pdata->digital_pwr_regulator)
-		regulator_set_optimum_mode(data->vcc_dig,
-						MXT_ACTIVE_LOAD_DIG_UA);
+		reg_set_optimum_mode_check(data->vcc_dig,
+					MXT_ACTIVE_LOAD_DIG_UA);
 	if (data->pdata->i2c_pull_up)
-		regulator_set_optimum_mode(data->vcc_i2c, MXT_I2C_LOAD_UA);
+		reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
 
 	return rc;
 
 fail_regulator_hpm:
-	regulator_set_optimum_mode(data->vcc_ana, MXT_LPM_LOAD_UA);
+	reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
 	if (data->pdata->digital_pwr_regulator)
-		regulator_set_optimum_mode(data->vcc_dig, MXT_LPM_LOAD_DIG_UA);
+		reg_set_optimum_mode_check(data->vcc_dig, MXT_LPM_LOAD_DIG_UA);
 	if (data->pdata->i2c_pull_up)
-		regulator_set_optimum_mode(data->vcc_i2c, MXT_I2C_LPM_LOAD_UA);
+		reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LPM_LOAD_UA);
 
 	return rc;
 }
@@ -1809,7 +1817,7 @@
 		goto err_free_mem;
 	}
 
-	input_dev->name = "Atmel maXTouch Touchscreen";
+	input_dev->name = "atmel_mxt_ts";
 	input_dev->id.bustype = BUS_I2C;
 	input_dev->dev.parent = &client->dev;
 	input_dev->open = mxt_input_open;
@@ -1842,6 +1850,16 @@
 	input_set_abs_params(input_dev, ABS_MT_PRESSURE,
 			     0, 255, 0, 0);
 
+	if (pdata->touch_x_size)
+		data->touch_x_size = pdata->touch_x_size;
+	else
+		data->touch_x_size = pdata->x_size;
+
+	if (pdata->touch_y_size)
+		data->touch_y_size = pdata->touch_y_size;
+	else
+		data->touch_y_size = pdata->y_size;
+
 	/* set key array supported keys */
 	if (pdata->key_codes) {
 		for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 57c418e..5508c3d 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -226,13 +226,13 @@
 	   To compile this driver as a module, choose M here: the module will
 	   be called rc_loopback.
 
-config IR_TSOP_CIR
-	tristate "TSOP IR remote control"
+config IR_GPIO_CIR
+	tristate "GPIO IR remote control"
 	depends on RC_CORE
 	---help---
-	   Say Y if you want to use GPIO based TSOP IR Receiver.
+	   Say Y if you want to use GPIO based IR Receiver.
 
 	   To compile this driver as a module, choose M here: the module will
-	   be called tsop-ir.
+	   be called gpio-ir-recv.
 
 endif #RC_CORE
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index d5c1a33..523fcd0 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -23,4 +23,4 @@
 obj-$(CONFIG_IR_STREAMZAP) += streamzap.o
 obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o
 obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o
-obj-$(CONFIG_IR_TSOP_CIR) += tsop-ir.o
+obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.o
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
new file mode 100644
index 0000000..a9b8e40
--- /dev/null
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -0,0 +1,199 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <media/rc-core.h>
+#include <media/gpio-ir-recv.h>
+
+#define TSOP_DRIVER_NAME	"gpio-rc-recv"
+#define TSOP_DEVICE_NAME	"gpio_ir_recv"
+
+struct gpio_rc_dev {
+	struct rc_dev *rcdev;
+	struct mutex lock;
+	unsigned int gpio_nr;
+	bool active_low;
+	bool can_wakeup;
+	struct work_struct work;
+};
+
+static void ir_decoder_work(struct work_struct *work)
+{
+	struct gpio_rc_dev *gpio_dev = container_of(work,
+			struct gpio_rc_dev, work);
+	unsigned int gval;
+	int rc = 0;
+	enum raw_event_type type = IR_SPACE;
+
+	mutex_lock(&gpio_dev->lock);
+	gval = gpio_get_value_cansleep(gpio_dev->gpio_nr);
+
+	if (gval < 0)
+		goto err_get_value;
+
+	if (gpio_dev->active_low)
+		gval = !gval;
+
+	if (gval == 1)
+		type = IR_PULSE;
+
+	rc = ir_raw_event_store_edge(gpio_dev->rcdev, type);
+	if (rc < 0)
+		goto err_get_value;
+
+	ir_raw_event_handle(gpio_dev->rcdev);
+
+err_get_value:
+	mutex_unlock(&gpio_dev->lock);
+}
+
+static irqreturn_t gpio_ir_recv_irq_handler(int irq, void *data)
+{
+	struct gpio_rc_dev *gpio_dev = data;
+
+	schedule_work(&gpio_dev->work);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit gpio_ir_recv_probe(struct platform_device *pdev)
+{
+	struct gpio_rc_dev *gpio_dev;
+	struct rc_dev *rcdev;
+	const struct gpio_ir_recv_platform_data *pdata =
+					pdev->dev.platform_data;
+	int rc = 0;
+
+	if (!pdata)
+		return -EINVAL;
+
+	if (pdata->gpio_nr < 0)
+		return -EINVAL;
+
+	gpio_dev = kzalloc(sizeof(struct gpio_rc_dev), GFP_KERNEL);
+	if (!gpio_dev)
+		return -ENOMEM;
+
+	mutex_init(&gpio_dev->lock);
+
+	rcdev = rc_allocate_device();
+	if (!rcdev) {
+		rc = -ENOMEM;
+		goto err_allocate_device;
+	}
+
+	rcdev->driver_type = RC_DRIVER_IR_RAW;
+	rcdev->allowed_protos = RC_TYPE_NEC;
+	rcdev->input_name = TSOP_DEVICE_NAME;
+	rcdev->input_id.bustype = BUS_HOST;
+	rcdev->driver_name = TSOP_DRIVER_NAME;
+	rcdev->map_name = RC_MAP_SAMSUNG_NECX;
+
+	gpio_dev->rcdev = rcdev;
+	gpio_dev->gpio_nr = pdata->gpio_nr;
+	gpio_dev->active_low = pdata->active_low;
+	gpio_dev->can_wakeup = pdata->can_wakeup;
+
+	INIT_WORK(&gpio_dev->work, ir_decoder_work);
+
+	rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv");
+	if (rc < 0)
+		goto err_gpio_request;
+	rc  = gpio_direction_input(pdata->gpio_nr);
+	if (rc < 0)
+		goto err_gpio_direction_input;
+
+	rc = rc_register_device(rcdev);
+	if (rc < 0) {
+		dev_err(&pdev->dev, "failed to register rc device\n");
+		goto err_register_rc_device;
+	}
+
+	platform_set_drvdata(pdev, gpio_dev);
+
+	rc = request_irq(gpio_to_irq(pdata->gpio_nr), gpio_ir_recv_irq_handler,
+			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			"gpio-ir-recv-irq", gpio_dev);
+	if (rc < 0)
+		goto err_request_irq;
+
+	if (pdata->can_wakeup == true) {
+		rc = enable_irq_wake(gpio_to_irq(pdata->gpio_nr));
+		if (rc < 0)
+			goto err_enable_irq_wake;
+	}
+
+	return 0;
+
+err_enable_irq_wake:
+	free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev);
+err_request_irq:
+	platform_set_drvdata(pdev, NULL);
+	rc_unregister_device(rcdev);
+err_register_rc_device:
+err_gpio_direction_input:
+	gpio_free(pdata->gpio_nr);
+err_gpio_request:
+	rc_free_device(rcdev);
+	rcdev = NULL;
+err_allocate_device:
+	mutex_destroy(&gpio_dev->lock);
+	kfree(gpio_dev);
+	return rc;
+}
+
+static int __devexit gpio_ir_recv_remove(struct platform_device *pdev)
+{
+	struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);
+
+	flush_work_sync(&gpio_dev->work);
+	disable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr));
+	free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev);
+	platform_set_drvdata(pdev, NULL);
+	rc_unregister_device(gpio_dev->rcdev);
+	gpio_free(gpio_dev->gpio_nr);
+	rc_free_device(gpio_dev->rcdev);
+	mutex_destroy(&gpio_dev->lock);
+	kfree(gpio_dev);
+	return 0;
+}
+
+static struct platform_driver gpio_ir_recv_driver = {
+	.probe  = gpio_ir_recv_probe,
+	.remove = __devexit_p(gpio_ir_recv_remove),
+	.driver = {
+		.name   = TSOP_DRIVER_NAME,
+		.owner  = THIS_MODULE,
+	},
+};
+
+static int __init gpio_ir_recv_init(void)
+{
+	return platform_driver_register(&gpio_ir_recv_driver);
+}
+module_init(gpio_ir_recv_init);
+
+static void __exit gpio_ir_recv_exit(void)
+{
+	platform_driver_unregister(&gpio_ir_recv_driver);
+}
+module_exit(gpio_ir_recv_exit);
+
+MODULE_DESCRIPTION("GPIO IR Receiver driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/rc/tsop-ir.c b/drivers/media/rc/tsop-ir.c
deleted file mode 100644
index ffffa9f..0000000
--- a/drivers/media/rc/tsop-ir.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/* 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/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-#include <media/rc-core.h>
-#include <media/tsop-ir.h>
-
-#define TSOP_DRIVER_NAME	"tsop-rc"
-#define TSOP_DEVICE_NAME	"tsop_ir"
-
-struct tsop_remote {
-	struct rc_dev *rcdev;
-	struct mutex lock;
-	unsigned int gpio_nr;
-	bool active_low;
-	bool can_wakeup;
-	struct work_struct work;
-};
-
-static void ir_decoder_work(struct work_struct *work)
-{
-	struct tsop_remote *tsop_dev = container_of(work,
-			struct tsop_remote, work);
-	unsigned int gval;
-	int rc = 0;
-	enum raw_event_type type = IR_SPACE;
-
-	mutex_lock(&tsop_dev->lock);
-	gval = gpio_get_value_cansleep(tsop_dev->gpio_nr);
-
-	if (gval < 0)
-		goto err_get_value;
-
-	if (tsop_dev->active_low)
-		gval = !gval;
-
-	if (gval == 1)
-		type = IR_PULSE;
-
-	rc = ir_raw_event_store_edge(tsop_dev->rcdev, type);
-	if (rc < 0)
-		goto err_get_value;
-
-	ir_raw_event_handle(tsop_dev->rcdev);
-
-err_get_value:
-	mutex_unlock(&tsop_dev->lock);
-}
-
-static irqreturn_t tsop_irq_handler(int irq, void *data)
-{
-	struct tsop_remote *tsop_dev = data;
-
-	schedule_work(&tsop_dev->work);
-
-	return IRQ_HANDLED;
-}
-
-static int __devinit tsop_driver_probe(struct platform_device *pdev)
-{
-	struct tsop_remote *tsop_dev;
-	struct rc_dev *rcdev;
-	const struct tsop_platform_data *pdata = pdev->dev.platform_data;
-	int rc = 0;
-
-	if (!pdata)
-		return -EINVAL;
-
-	if (pdata->gpio_nr < 0)
-		return -EINVAL;
-
-	tsop_dev = kzalloc(sizeof(struct tsop_remote), GFP_KERNEL);
-	if (!tsop_dev)
-		return -ENOMEM;
-
-	mutex_init(&tsop_dev->lock);
-
-	rcdev = rc_allocate_device();
-	if (!rcdev) {
-		rc = -ENOMEM;
-		goto err_allocate_device;
-	}
-
-	rcdev->driver_type = RC_DRIVER_IR_RAW;
-	rcdev->allowed_protos = RC_TYPE_NEC;
-	rcdev->input_name = TSOP_DEVICE_NAME;
-	rcdev->input_id.bustype = BUS_HOST;
-	rcdev->driver_name = TSOP_DRIVER_NAME;
-	rcdev->map_name = RC_MAP_SAMSUNG_NECX;
-
-	tsop_dev->rcdev = rcdev;
-	tsop_dev->gpio_nr = pdata->gpio_nr;
-	tsop_dev->active_low = pdata->active_low;
-	tsop_dev->can_wakeup = pdata->can_wakeup;
-
-	INIT_WORK(&tsop_dev->work, ir_decoder_work);
-
-	rc = gpio_request(pdata->gpio_nr, "tsop-ir");
-	if (rc < 0)
-		goto err_gpio_request;
-	rc  = gpio_direction_input(pdata->gpio_nr);
-	if (rc < 0)
-		goto err_gpio_direction_input;
-
-	rc = rc_register_device(rcdev);
-	if (rc < 0) {
-		dev_err(&pdev->dev, "failed to register rc device\n");
-		goto err_register_rc_device;
-	}
-
-	platform_set_drvdata(pdev, tsop_dev);
-
-	rc = request_irq(gpio_to_irq(pdata->gpio_nr), tsop_irq_handler,
-			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
-			"tsop-irq", tsop_dev);
-	if (rc < 0)
-		goto err_request_irq;
-
-	if (pdata->can_wakeup == true) {
-		rc = enable_irq_wake(gpio_to_irq(pdata->gpio_nr));
-		if (rc < 0)
-			goto err_enable_irq_wake;
-	}
-
-	return 0;
-
-err_enable_irq_wake:
-	free_irq(gpio_to_irq(tsop_dev->gpio_nr), tsop_dev);
-err_request_irq:
-	platform_set_drvdata(pdev, NULL);
-	rc_unregister_device(rcdev);
-err_register_rc_device:
-err_gpio_direction_input:
-	gpio_free(pdata->gpio_nr);
-err_gpio_request:
-	rc_free_device(rcdev);
-	rcdev = NULL;
-err_allocate_device:
-	mutex_destroy(&tsop_dev->lock);
-	kfree(tsop_dev);
-	return rc;
-}
-
-static int __devexit tsop_driver_remove(struct platform_device *pdev)
-{
-	struct tsop_remote *tsop_dev = platform_get_drvdata(pdev);
-
-	flush_work_sync(&tsop_dev->work);
-	disable_irq_wake(gpio_to_irq(tsop_dev->gpio_nr));
-	free_irq(gpio_to_irq(tsop_dev->gpio_nr), tsop_dev);
-	platform_set_drvdata(pdev, NULL);
-	rc_unregister_device(tsop_dev->rcdev);
-	gpio_free(tsop_dev->gpio_nr);
-	rc_free_device(tsop_dev->rcdev);
-	mutex_destroy(&tsop_dev->lock);
-	kfree(tsop_dev);
-	return 0;
-}
-
-static struct platform_driver tsop_driver = {
-	.probe  = tsop_driver_probe,
-	.remove = __devexit_p(tsop_driver_remove),
-	.driver = {
-		.name   = TSOP_DRIVER_NAME,
-		.owner  = THIS_MODULE,
-	},
-};
-
-static int __init tsop_init(void)
-{
-	return platform_driver_register(&tsop_driver);
-}
-module_init(tsop_init);
-
-static void __exit tsop_exit(void)
-{
-	platform_driver_unregister(&tsop_driver);
-}
-module_exit(tsop_exit);
-
-MODULE_DESCRIPTION("TSOP IR driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index a9aa28b..ed77185 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -38,9 +38,6 @@
 module_param(msm_camera_v4l2_nr, uint, 0644);
 MODULE_PARM_DESC(msm_camera_v4l2_nr, "videoX start number, -1 is autodetect");
 
-static int msm_setup_v4l2_event_queue(struct v4l2_fh *eventHandle,
-				  struct video_device *pvdev);
-
 static void msm_queue_init(struct msm_device_queue *queue, const char *name)
 {
 	D("%s\n", __func__);
@@ -835,7 +832,8 @@
 	pcam_inst = container_of(f->private_data,
 		struct msm_cam_v4l2_dev_inst, eventHandle);
 
-	D("%s Inst = %p\n", __func__, pcam_inst);
+	D("%s Inst=%p, mode=%d, idx=%d\n", __func__, pcam_inst,
+		pcam_inst->image_mode, pb->index);
 	WARN_ON(pctx != f->private_data);
 
 	if (!pcam_inst->buf_offset) {
@@ -865,7 +863,8 @@
 	}
 
 	rc = vb2_qbuf(&pcam_inst->vid_bufq, pb);
-	D("%s, videobuf_qbuf returns %d\n", __func__, rc);
+	D("%s, videobuf_qbuf mode %d and idx %d returns %d\n", __func__,
+		pcam_inst->image_mode, pb->index, rc);
 
 	return rc;
 }
@@ -1677,6 +1676,7 @@
 	struct v4l2_event ev;
 	struct msm_camera_info temp_cam_info;
 	struct msm_cam_config_dev_info temp_config_info;
+	struct msm_mctl_node_info temp_mctl_info;
 	struct v4l2_event_subscription temp_sub;
 	int i;
 
@@ -1744,6 +1744,34 @@
 		}
 		rc = 0;
 		break;
+	case MSM_CAM_IOCTL_GET_MCTL_INFO:
+		if (copy_from_user(&temp_mctl_info, (void __user *)arg,
+				  sizeof(struct msm_mctl_node_info))) {
+			rc = -EINVAL;
+			return rc;
+		}
+
+		for (i = 0; i < g_server_dev.mctl_node_info.num_mctl_nodes;
+				i++) {
+			if (copy_to_user((void __user *)
+			temp_mctl_info.mctl_node_name[i],
+			g_server_dev.mctl_node_info.mctl_node_name[i], strnlen(
+			g_server_dev.mctl_node_info.mctl_node_name[i],
+			MAX_DEV_NAME_LEN))) {
+				rc = -EINVAL;
+				return rc;
+			}
+		}
+		temp_mctl_info.num_mctl_nodes =
+			g_server_dev.mctl_node_info.num_mctl_nodes;
+		if (copy_to_user((void __user *)arg,
+							  &temp_mctl_info,
+				sizeof(struct msm_mctl_node_info))) {
+			rc = -EINVAL;
+			return rc;
+		}
+		rc = 0;
+	break;
 
 	case VIDIOC_SUBSCRIBE_EVENT:
 		if (copy_from_user(&temp_sub, (void __user *)arg,
@@ -1991,7 +2019,6 @@
 				(*((uint32_t *)ev.u.data));
 		/* Copy the event structure into user struct. */
 		u_isp_event = *k_isp_event;
-
 		if (ev.type != (V4L2_EVENT_PRIVATE_START +
 				MSM_CAM_RESP_DIV_FRAME_EVT_MSG) &&
 				ev.type != (V4L2_EVENT_PRIVATE_START +
@@ -2152,7 +2179,7 @@
 	.mmap	= msm_mmap_config,
 };
 
-static int msm_setup_v4l2_event_queue(struct v4l2_fh *eventHandle,
+int msm_setup_v4l2_event_queue(struct v4l2_fh *eventHandle,
 					struct video_device *pvdev)
 {
 	int rc = 0;
@@ -2476,6 +2503,7 @@
 	/* init the user count and lock*/
 	pcam->use_count = 0;
 	mutex_init(&pcam->vid_lock);
+	mutex_init(&pcam->mctl_node.dev_lock);
 
 	/* Initialize the formats supported */
 	rc  = msm_mctl_init_user_formats(pcam);
@@ -2486,11 +2514,18 @@
 	if (rc < 0)
 		goto failure;
 
+	rc = msm_setup_mctl_node(pcam);
+	if (rc < 0) {
+		pr_err("%s:failed to create mctl device: %d\n",
+			 __func__, rc);
+		goto failure;
+	}
+
 	g_server_dev.camera_info.video_dev_name
 	[g_server_dev.camera_info.num_cameras]
 	= video_device_node_name(pcam->pvdev);
 	D("%s Connected video device %s\n", __func__,
-	  g_server_dev.camera_info.video_dev_name
+		g_server_dev.camera_info.video_dev_name
 		[g_server_dev.camera_info.num_cameras]);
 
 	g_server_dev.camera_info.s_mount_angle
@@ -2501,7 +2536,17 @@
 	[g_server_dev.camera_info.num_cameras]
 	= sdata->camera_type;
 
+	g_server_dev.mctl_node_info.mctl_node_name
+	[g_server_dev.mctl_node_info.num_mctl_nodes]
+	= video_device_node_name(pcam->mctl_node.pvdev);
+
+	pr_info("%s mctl_node_name[%d] = %s\n", __func__,
+		g_server_dev.mctl_node_info.num_mctl_nodes,
+		g_server_dev.mctl_node_info.mctl_node_name
+		[g_server_dev.mctl_node_info.num_mctl_nodes]);
+
 	g_server_dev.camera_info.num_cameras++;
+	g_server_dev.mctl_node_info.num_mctl_nodes++;
 
 	D("%s done, rc = %d\n", __func__, rc);
 	D("%s number of sensors connected is %d\n", __func__,
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index cc2e8b4..22322b8 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -235,6 +235,10 @@
 	struct pm_qos_request_list pm_qos_req_list;
 	struct msm_mctl_pp_info pp_info;
 	struct ion_client *client;
+	/* VFE output mode.
+	* Used to interpret the Primary/Secondary messages
+	* to preview/video/main/thumbnail image types*/
+	uint32_t vfe_output_mode;
 };
 
 /* abstract camera device represents a VFE and connected sensor */
@@ -290,6 +294,16 @@
 	struct img_plane_info plane_info;
 	int vbqueue_initialized;
 };
+
+struct msm_cam_mctl_node {
+	/* MCTL V4l2 device */
+	struct v4l2_device v4l2_dev;
+	struct video_device *pvdev;
+	struct msm_cam_v4l2_dev_inst *dev_inst[MSM_DEV_INST_MAX];
+	struct msm_cam_v4l2_dev_inst *dev_inst_map[MSM_MAX_IMG_MODE];
+	struct mutex dev_lock;
+};
+
 /* abstract camera device for each sensor successfully probed*/
 struct msm_cam_v4l2_device {
 	/* standard device interfaces */
@@ -340,6 +354,7 @@
 	uint8_t ctrl_data[max_control_command_size];
 	struct msm_ctrl_cmd ctrl;
 	uint32_t event_mask;
+	struct msm_cam_mctl_node mctl_node;
 };
 static inline struct msm_cam_v4l2_device *to_pcam(
 	struct v4l2_device *v4l2_dev)
@@ -387,7 +402,8 @@
 	int use_count;
 	/* all the registered ISP subdevice*/
 	struct msm_isp_ops *isp_subdev[MSM_MAX_CAMERA_CONFIGS];
-
+	/* info of MCTL nodes successfully probed*/
+	struct msm_mctl_node_info mctl_node_info;
 };
 
 /* camera server related functions */
@@ -412,8 +428,10 @@
 int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
 			int msg_type, struct msm_free_buf *frame, int dirty);
 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);
 int msm_mctl_release_free_buf(struct msm_cam_media_controller *pmctl,
+				struct msm_cam_v4l2_dev_inst *pcam_inst,
 				int path, struct msm_free_buf *free_buf);
 /*Memory(PMEM) functions*/
 int msm_register_pmem(struct hlist_head *ptype, void __user *arg,
@@ -454,7 +472,7 @@
 			unsigned int cmd, unsigned long arg);
 int msm_mctl_pp_notify(struct msm_cam_media_controller *pmctl,
 			struct msm_mctl_pp_frame_info *pp_frame_info);
-int msm_mctl_out_type_to_inst_index(struct msm_cam_v4l2_device *pcam,
+int msm_mctl_img_mode_to_inst_index(struct msm_cam_media_controller *pmctl,
 					int out_type);
 struct msm_frame_buffer *msm_mctl_buf_find(
 	struct msm_cam_media_controller *pmctl,
@@ -490,7 +508,16 @@
 int msm_mctl_pp_divert_done(
 	struct msm_cam_media_controller *p_mctl,
 	void __user *arg);
-
+int msm_setup_v4l2_event_queue(struct v4l2_fh *eventHandle,
+					struct video_device *pvdev);
+int msm_setup_mctl_node(struct msm_cam_v4l2_device *pcam);
+struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst(
+		struct msm_cam_media_controller *pmctl,
+		int image_mode);
+int msm_mctl_buf_return_buf(struct msm_cam_media_controller *pmctl,
+			int image_mode, struct msm_frame_buffer *buf);
+int msm_mctl_pp_mctl_divert_done(struct msm_cam_media_controller *p_mctl,
+					void __user *arg);
 #endif /* __KERNEL__ */
 
 #endif /* _MSM_H */
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 6a9d7c4..6b3aef7 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -83,9 +83,64 @@
 	return 0;
 }
 
+int msm_isp_vfe_msg_to_img_mode(struct msm_cam_media_controller *pmctl,
+				int vfe_msg)
+{
+	int image_mode;
+	if (vfe_msg == VFE_MSG_OUTPUT_PRIMARY) {
+		switch (pmctl->vfe_output_mode) {
+		case VFE_OUTPUTS_MAIN_AND_PREVIEW:
+		case VFE_OUTPUTS_MAIN_AND_VIDEO:
+		case VFE_OUTPUTS_MAIN_AND_THUMB:
+		case VFE_OUTPUTS_RAW:
+			image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
+			break;
+		case VFE_OUTPUTS_THUMB_AND_MAIN:
+			image_mode = MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
+			break;
+		case VFE_OUTPUTS_VIDEO:
+		case VFE_OUTPUTS_VIDEO_AND_PREVIEW:
+			image_mode = MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
+			break;
+		case VFE_OUTPUTS_PREVIEW:
+		case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
+			image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
+			break;
+		default:
+			image_mode = -1;
+			break;
+		}
+	} else if (vfe_msg == VFE_MSG_OUTPUT_SECONDARY) {
+		switch (pmctl->vfe_output_mode) {
+		case VFE_OUTPUTS_MAIN_AND_PREVIEW:
+		case VFE_OUTPUTS_VIDEO_AND_PREVIEW:
+			image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
+			break;
+		case VFE_OUTPUTS_MAIN_AND_VIDEO:
+		case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
+			image_mode = MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
+			break;
+		case VFE_OUTPUTS_MAIN_AND_THUMB:
+			image_mode = MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
+			break;
+		case VFE_OUTPUTS_THUMB_AND_MAIN:
+			image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
+			break;
+		default:
+			image_mode = -1;
+			break;
+		}
+	} else
+		image_mode = -1;
+
+	D("%s Selected image mode %d vfe output mode %d, vfe msg %d\n",
+	  __func__, image_mode, pmctl->vfe_output_mode, vfe_msg);
+	return image_mode;
+}
+
 static int msm_isp_notify_VFE_BUF_EVT(struct v4l2_subdev *sd, void *arg)
 {
-	int rc = -EINVAL;
+	int rc = -EINVAL, image_mode;
 	struct msm_vfe_resp *vdata = (struct msm_vfe_resp *)arg;
 	struct msm_free_buf free_buf;
 	struct msm_camvfe_params vfe_params;
@@ -100,19 +155,24 @@
 		msm_isp_sync_free(vdata);
 		return rc;
 	}
+	/* Convert the vfe msg to the image mode */
+	image_mode = msm_isp_vfe_msg_to_img_mode(&pcam->mctl, vfe_id);
+	BUG_ON(image_mode < 0);
 	switch (vdata->type) {
 	case VFE_MSG_V32_START:
 	case VFE_MSG_V32_START_RECORDING:
 	case VFE_MSG_V2X_PREVIEW:
 		D("%s Got V32_START_*: Getting ping addr id = %d",
 						__func__, vfe_id);
-		msm_mctl_reserve_free_buf(&pcam->mctl, vfe_id, &free_buf);
+		msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+					image_mode, &free_buf);
 		cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR;
 		cfgcmd.value = &vfe_id;
 		vfe_params.vfe_cfg = &cfgcmd;
 		vfe_params.data = (void *)&free_buf;
 		rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
-		msm_mctl_reserve_free_buf(&pcam->mctl, vfe_id, &free_buf);
+		msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+					image_mode, &free_buf);
 		cfgcmd.cmd_type = CMD_CONFIG_PONG_ADDR;
 		cfgcmd.value = &vfe_id;
 		vfe_params.vfe_cfg = &cfgcmd;
@@ -123,7 +183,8 @@
 	case VFE_MSG_V2X_CAPTURE:
 		pr_err("%s Got V32_CAPTURE: getting buffer for id = %d",
 						__func__, vfe_id);
-		msm_mctl_reserve_free_buf(&pcam->mctl, vfe_id, &free_buf);
+		msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+					image_mode, &free_buf);
 		cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR;
 		cfgcmd.value = &vfe_id;
 		vfe_params.vfe_cfg = &cfgcmd;
@@ -139,7 +200,8 @@
 	case VFE_MSG_OUTPUT_IRQ:
 		D("%s Got OUTPUT_IRQ: Getting free buf id = %d",
 						__func__, vfe_id);
-		msm_mctl_reserve_free_buf(&pcam->mctl, vfe_id, &free_buf);
+		msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+					image_mode, &free_buf);
 		cfgcmd.cmd_type = CMD_CONFIG_FREE_BUF_ADDR;
 		cfgcmd.value = &vfe_id;
 		vfe_params.vfe_cfg = &cfgcmd;
@@ -219,6 +281,12 @@
 		case MSG_ID_OUTPUT_S:
 			msgid = VFE_MSG_OUTPUT_S;
 			break;
+		case MSG_ID_OUTPUT_PRIMARY:
+			msgid = VFE_MSG_OUTPUT_PRIMARY;
+			break;
+		case MSG_ID_OUTPUT_SECONDARY:
+			msgid = VFE_MSG_OUTPUT_SECONDARY;
+			break;
 		default:
 			pr_err("%s: Invalid VFE output id: %d\n",
 				__func__, isp_output->output_id);
@@ -232,6 +300,8 @@
 			isp_event->isp_data.isp_msg.frame_id =
 				isp_output->frameCounter;
 			buf = isp_output->buf;
+			msgid = msm_isp_vfe_msg_to_img_mode(pmctl, msgid);
+			BUG_ON(msgid < 0);
 			msm_mctl_buf_done(pmctl, msgid,
 				&buf, isp_output->frameCounter);
 		}
@@ -561,6 +631,11 @@
 	case CMD_AXI_CFG_VIDEO_ALL_CHNLS:
 	case CMD_AXI_CFG_ZSL_ALL_CHNLS:
 	case CMD_RAW_PICT_AXI_CFG:
+	case CMD_AXI_CFG_PRIM:
+	case CMD_AXI_CFG_PRIM_ALL_CHNLS:
+	case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC:
+	case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC_ALL_CHNLS:
+	case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC:
 		/* Dont need to pass buffer information.
 		 * subdev will get the buffer from media
 		 * controller free queue.
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index e76b1d2..2c4fbe4 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -277,6 +277,21 @@
 	return rc;
 }
 
+static int msm_mctl_set_vfe_output_mode(struct msm_cam_media_controller
+					*p_mctl, void __user *arg)
+{
+	int rc = 0;
+	if (copy_from_user(&p_mctl->vfe_output_mode,
+		(void __user *)arg, sizeof(p_mctl->vfe_output_mode))) {
+		pr_err("%s Copy from user failed ", __func__);
+		rc = -EFAULT;
+	} else {
+		pr_info("%s: mctl=0x%p, vfe output mode =0x%x",
+		  __func__, p_mctl, p_mctl->vfe_output_mode);
+	}
+	return rc;
+}
+
 /* called by the server or the config nodes to handle user space
 	commands*/
 static int msm_mctl_cmd(struct msm_cam_media_controller *p_mctl,
@@ -409,6 +424,14 @@
 		rc = msm_mctl_pp_release_free_frame(p_mctl,
 			(void __user *)arg);
 		break;
+	case MSM_CAM_IOCTL_SET_VFE_OUTPUT_TYPE:
+		rc = msm_mctl_set_vfe_output_mode(p_mctl,
+		  (void __user *)arg);
+		break;
+	case MSM_CAM_IOCTL_MCTL_DIVERT_DONE:
+		rc = msm_mctl_pp_mctl_divert_done(p_mctl,
+			(void __user *)arg);
+		break;
 			/* ISFIF config*/
 	default:
 		/* ISP config*/
@@ -778,6 +801,7 @@
 	/* init mctl buf */
 	msm_mctl_buf_init(pcam);
 	memset(&pmctl->pp_info, 0, sizeof(pmctl->pp_info));
+	pmctl->vfe_output_mode = 0;
 	spin_lock_init(&pmctl->pp_info.lock);
 	/* init sub device*/
 	v4l2_subdev_init(&(pmctl->mctl_sdev), &mctl_subdev_ops);
@@ -785,3 +809,778 @@
 
 	return 0;
 }
+
+
+/* mctl node v4l2_file_operations */
+static int msm_mctl_dev_open(struct file *f)
+{
+	int rc = -EINVAL, i;
+	/* get the video device */
+	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	D("%s : E ", __func__);
+
+	if (!pcam) {
+		pr_err("%s NULL pointer passed in!\n", __func__);
+		return rc;
+	}
+
+	mutex_lock(&pcam->mctl_node.dev_lock);
+	for (i = 0; i < MSM_DEV_INST_MAX; i++) {
+		if (pcam->mctl_node.dev_inst[i] == NULL)
+			break;
+	}
+	/* if no instance is available, return error */
+	if (i == MSM_DEV_INST_MAX) {
+		mutex_unlock(&pcam->mctl_node.dev_lock);
+		return rc;
+	}
+	pcam_inst = kzalloc(sizeof(struct msm_cam_v4l2_dev_inst), GFP_KERNEL);
+	if (!pcam_inst) {
+		mutex_unlock(&pcam->mctl_node.dev_lock);
+		return rc;
+	}
+
+	pcam_inst->sensor_pxlcode = pcam->usr_fmts[0].pxlcode;
+	pcam_inst->my_index = i;
+	pcam_inst->pcam = pcam;
+	pcam->mctl_node.dev_inst[i] = pcam_inst;
+
+	D("%s pcam_inst %p my_index = %d\n", __func__,
+		pcam_inst, pcam_inst->my_index);
+	D("%s for %s\n", __func__, pcam->pdev->name);
+	rc = msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
+					pcam->mctl_node.pvdev);
+	if (rc < 0) {
+		mutex_unlock(&pcam->mctl_node.dev_lock);
+		return rc;
+	}
+	pcam_inst->vbqueue_initialized = 0;
+
+	f->private_data = &pcam_inst->eventHandle;
+
+	D("f->private_data = 0x%x, pcam = 0x%x\n",
+		(u32)f->private_data, (u32)pcam_inst);
+
+	mutex_unlock(&pcam->mctl_node.dev_lock);
+	D("%s : X ", __func__);
+	return rc;
+}
+
+static unsigned int msm_mctl_dev_poll(struct file *f,
+				struct poll_table_struct *wait)
+{
+	int rc = 0;
+	struct msm_cam_v4l2_device *pcam;
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+			struct msm_cam_v4l2_dev_inst, eventHandle);
+	pcam = pcam_inst->pcam;
+
+	D("%s : E pcam_inst = %p", __func__, pcam_inst);
+	if (!pcam) {
+		pr_err("%s NULL pointer of camera device!\n", __func__);
+		return -EINVAL;
+	}
+
+	poll_wait(f, &(pcam_inst->eventHandle.events->wait), wait);
+	if (v4l2_event_pending(&pcam_inst->eventHandle)) {
+		rc |= POLLPRI;
+		D("%s Event available on mctl node ", __func__);
+	}
+
+	D("%s poll on vb2\n", __func__);
+	if (!pcam_inst->vid_bufq.streaming) {
+		D("%s vid_bufq.streaming is off, inst=0x%x\n",
+				__func__, (u32)pcam_inst);
+		return rc;
+	}
+	rc |= vb2_poll(&pcam_inst->vid_bufq, f, wait);
+
+	D("%s : X ", __func__);
+	return rc;
+}
+
+static int msm_mctl_dev_close(struct file *f)
+{
+	int rc = 0;
+	struct msm_cam_v4l2_device *pcam;
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+		struct msm_cam_v4l2_dev_inst, eventHandle);
+	pcam = pcam_inst->pcam;
+
+	D("%s : E ", __func__);
+	if (!pcam) {
+		pr_err("%s NULL pointer of camera device!\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&pcam->mctl_node.dev_lock);
+	pcam_inst->streamon = 0;
+	pcam->mctl_node.dev_inst_map[pcam_inst->image_mode] = NULL;
+	if (pcam_inst->vbqueue_initialized)
+		vb2_queue_release(&pcam_inst->vid_bufq);
+	D("%s Closing down instance %p ", __func__, pcam_inst);
+	pcam->mctl_node.dev_inst[pcam_inst->my_index] = NULL;
+	v4l2_fh_del(&pcam_inst->eventHandle);
+	v4l2_fh_exit(&pcam_inst->eventHandle);
+
+	kfree(pcam_inst);
+	f->private_data = NULL;
+	mutex_unlock(&pcam->mctl_node.dev_lock);
+	D("%s : X ", __func__);
+	return rc;
+}
+
+static struct v4l2_file_operations g_msm_mctl_fops = {
+	.owner   = THIS_MODULE,
+	.open	= msm_mctl_dev_open,
+	.poll	= msm_mctl_dev_poll,
+	.release = msm_mctl_dev_close,
+	.unlocked_ioctl = video_ioctl2,
+};
+
+/*
+ *
+ * implementation of mctl node v4l2_ioctl_ops
+ *
+ */
+static int msm_mctl_v4l2_querycap(struct file *f, void *pctx,
+				struct v4l2_capability *pcaps)
+{
+	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
+
+	D("%s\n", __func__);
+	WARN_ON(pctx != f->private_data);
+
+	strlcpy(pcaps->driver, pcam->pdev->name, sizeof(pcaps->driver));
+	pcaps->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+	return 0;
+}
+
+static int msm_mctl_v4l2_queryctrl(struct file *f, void *pctx,
+				struct v4l2_queryctrl *pqctrl)
+{
+	int rc = 0;
+
+	D("%s\n", __func__);
+	WARN_ON(pctx != f->private_data);
+
+	return rc;
+}
+
+static int msm_mctl_v4l2_g_ctrl(struct file *f, void *pctx,
+					struct v4l2_control *c)
+{
+	int rc = 0;
+
+	D("%s\n", __func__);
+	WARN_ON(pctx != f->private_data);
+
+	return rc;
+}
+
+static int msm_mctl_v4l2_s_ctrl(struct file *f, void *pctx,
+					struct v4l2_control *ctrl)
+{
+	int rc = 0;
+	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+			struct msm_cam_v4l2_dev_inst, eventHandle);
+
+	D("%s\n", __func__);
+
+	WARN_ON(pctx != f->private_data);
+	mutex_lock(&pcam->mctl_node.dev_lock);
+	if (ctrl->id == MSM_V4L2_PID_PP_PLANE_INFO) {
+		if (copy_from_user(&pcam_inst->plane_info,
+					(void *)ctrl->value,
+					sizeof(struct img_plane_info))) {
+			pr_err("%s inst %p Copying plane_info failed ",
+					__func__, pcam_inst);
+			rc = -EFAULT;
+		}
+		D("%s inst %p got plane info: num_planes = %d,"
+				"plane size = %ld %ld ", __func__, pcam_inst,
+				pcam_inst->plane_info.num_planes,
+				pcam_inst->plane_info.plane[0].size,
+				pcam_inst->plane_info.plane[1].size);
+	} else
+		pr_err("%s Unsupported S_CTRL Value ", __func__);
+
+	mutex_unlock(&pcam->mctl_node.dev_lock);
+
+	return rc;
+}
+
+static int msm_mctl_v4l2_reqbufs(struct file *f, void *pctx,
+				struct v4l2_requestbuffers *pb)
+{
+	int rc = 0, i, j;
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+		struct msm_cam_v4l2_dev_inst, eventHandle);
+	D("%s\n", __func__);
+	WARN_ON(pctx != f->private_data);
+	rc = vb2_reqbufs(&pcam_inst->vid_bufq, pb);
+	if (rc < 0) {
+		pr_err("%s reqbufs failed %d ", __func__, rc);
+		return rc;
+	}
+	if (!pb->count) {
+		/* Deallocation. free buf_offset array */
+		D("%s Inst %p freeing buffer offsets array",
+			__func__, pcam_inst);
+		for (j = 0 ; j < pcam_inst->buf_count ; j++)
+			kfree(pcam_inst->buf_offset[j]);
+		kfree(pcam_inst->buf_offset);
+		pcam_inst->buf_offset = NULL;
+		/* If the userspace has deallocated all the
+		 * buffers, then release the vb2 queue */
+		if (pcam_inst->vbqueue_initialized) {
+			vb2_queue_release(&pcam_inst->vid_bufq);
+			pcam_inst->vbqueue_initialized = 0;
+		}
+	} else {
+		D("%s Inst %p Allocating buf_offset array",
+			__func__, pcam_inst);
+		/* Allocation. allocate buf_offset array */
+		pcam_inst->buf_offset = (struct msm_cam_buf_offset **)
+			kzalloc(pb->count * sizeof(struct msm_cam_buf_offset *),
+							GFP_KERNEL);
+		if (!pcam_inst->buf_offset) {
+			pr_err("%s out of memory ", __func__);
+			return -ENOMEM;
+		}
+		for (i = 0; i < pb->count; i++) {
+			pcam_inst->buf_offset[i] =
+				kzalloc(sizeof(struct msm_cam_buf_offset) *
+				pcam_inst->plane_info.num_planes, GFP_KERNEL);
+			if (!pcam_inst->buf_offset[i]) {
+				pr_err("%s out of memory ", __func__);
+				for (j = i-1 ; j >= 0; j--)
+					kfree(pcam_inst->buf_offset[j]);
+				kfree(pcam_inst->buf_offset);
+				pcam_inst->buf_offset = NULL;
+				return -ENOMEM;
+			}
+		}
+	}
+	pcam_inst->buf_count = pb->count;
+	D("%s inst %p, buf count %d ", __func__,
+		pcam_inst, pcam_inst->buf_count);
+	return rc;
+}
+
+static int msm_mctl_v4l2_querybuf(struct file *f, void *pctx,
+					struct v4l2_buffer *pb)
+{
+	/* get the video device */
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+		struct msm_cam_v4l2_dev_inst, eventHandle);
+
+	D("%s\n", __func__);
+	WARN_ON(pctx != f->private_data);
+	return vb2_querybuf(&pcam_inst->vid_bufq, pb);
+}
+
+static int msm_mctl_v4l2_qbuf(struct file *f, void *pctx,
+					struct v4l2_buffer *pb)
+{
+	int rc = 0, i = 0;
+	/* get the camera device */
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+		struct msm_cam_v4l2_dev_inst, eventHandle);
+
+	D("%s Inst = %p\n", __func__, pcam_inst);
+	WARN_ON(pctx != f->private_data);
+
+	if (!pcam_inst->buf_offset) {
+		pr_err("%s Buffer is already released. Returning. ", __func__);
+		return -EINVAL;
+	}
+
+	if (pb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		/* Reject the buffer if planes array was not allocated */
+		if (pb->m.planes == NULL) {
+			pr_err("%s Planes array is null ", __func__);
+			return -EINVAL;
+		}
+		for (i = 0; i < pcam_inst->plane_info.num_planes; i++) {
+			D("%s stored offsets for plane %d as"
+				"addr offset %d, data offset %d",
+				__func__, i, pb->m.planes[i].reserved[0],
+				pb->m.planes[i].data_offset);
+			pcam_inst->buf_offset[pb->index][i].data_offset =
+				pb->m.planes[i].data_offset;
+			pcam_inst->buf_offset[pb->index][i].addr_offset =
+				pb->m.planes[i].reserved[0];
+		}
+	} else {
+		D("%s stored reserved info %d", __func__, pb->reserved);
+		pcam_inst->buf_offset[pb->index][0].addr_offset = pb->reserved;
+	}
+
+	rc = vb2_qbuf(&pcam_inst->vid_bufq, pb);
+	D("%s, videobuf_qbuf returns %d\n", __func__, rc);
+
+	return rc;
+}
+
+static int msm_mctl_v4l2_dqbuf(struct file *f, void *pctx,
+					struct v4l2_buffer *pb)
+{
+	int rc = 0;
+	/* get the camera device */
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+		struct msm_cam_v4l2_dev_inst, eventHandle);
+
+	D("%s\n", __func__);
+	WARN_ON(pctx != f->private_data);
+
+	rc = vb2_dqbuf(&pcam_inst->vid_bufq, pb,  f->f_flags & O_NONBLOCK);
+	D("%s, videobuf_dqbuf returns %d\n", __func__, rc);
+
+	return rc;
+}
+
+static int msm_mctl_v4l2_streamon(struct file *f, void *pctx,
+					enum v4l2_buf_type buf_type)
+{
+	int rc = 0;
+	/* get the camera device */
+	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+		struct msm_cam_v4l2_dev_inst, eventHandle);
+
+	D("%s Inst %p\n", __func__, pcam_inst);
+	WARN_ON(pctx != f->private_data);
+
+	if ((buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
+		(buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
+		pr_err("%s Invalid buffer type ", __func__);
+		return -EINVAL;
+	}
+
+	D("%s Calling videobuf_streamon", __func__);
+	/* if HW streaming on is successful, start buffer streaming */
+	rc = vb2_streamon(&pcam_inst->vid_bufq, buf_type);
+	D("%s, videobuf_streamon returns %d\n", __func__, rc);
+
+	mutex_lock(&pcam->mctl_node.dev_lock);
+	/* turn HW (VFE/sensor) streaming */
+	pcam_inst->streamon = 1;
+	mutex_unlock(&pcam->mctl_node.dev_lock);
+	D("%s rc = %d\n", __func__, rc);
+	return rc;
+}
+
+static int msm_mctl_v4l2_streamoff(struct file *f, void *pctx,
+					enum v4l2_buf_type buf_type)
+{
+	int rc = 0;
+	/* get the camera device */
+	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+		struct msm_cam_v4l2_dev_inst, eventHandle);
+
+	D("%s Inst %p\n", __func__, pcam_inst);
+	WARN_ON(pctx != f->private_data);
+
+	if ((buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
+		(buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
+		pr_err("%s Invalid buffer type ", __func__);
+		return -EINVAL;
+	}
+
+	/* first turn of HW (VFE/sensor) streaming so that buffers are
+		not in use when we free the buffers */
+	mutex_lock(&pcam->mctl_node.dev_lock);
+	pcam_inst->streamon = 0;
+	mutex_unlock(&pcam->mctl_node.dev_lock);
+	if (rc < 0)
+		pr_err("%s: hw failed to stop streaming\n", __func__);
+
+	/* stop buffer streaming */
+	rc = vb2_streamoff(&pcam_inst->vid_bufq, buf_type);
+	D("%s, videobuf_streamoff returns %d\n", __func__, rc);
+	return rc;
+}
+
+static int msm_mctl_v4l2_enum_fmt_cap(struct file *f, void *pctx,
+					struct v4l2_fmtdesc *pfmtdesc)
+{
+	/* get the video device */
+	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
+	const struct msm_isp_color_fmt *isp_fmt;
+
+	D("%s\n", __func__);
+	WARN_ON(pctx != f->private_data);
+	if ((pfmtdesc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
+		(pfmtdesc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+		return -EINVAL;
+
+	if (pfmtdesc->index >= pcam->num_fmts)
+		return -EINVAL;
+
+	isp_fmt = &pcam->usr_fmts[pfmtdesc->index];
+
+	if (isp_fmt->name)
+		strlcpy(pfmtdesc->description, isp_fmt->name,
+						sizeof(pfmtdesc->description));
+
+	pfmtdesc->pixelformat = isp_fmt->fourcc;
+
+	D("%s: [%d] 0x%x, %s\n", __func__, pfmtdesc->index,
+		isp_fmt->fourcc, isp_fmt->name);
+	return 0;
+}
+
+static int msm_mctl_v4l2_g_fmt_cap(struct file *f,
+		void *pctx, struct v4l2_format *pfmt)
+{
+	int rc = 0;
+
+	D("%s\n", __func__);
+	WARN_ON(pctx != f->private_data);
+
+	if (pfmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	return rc;
+}
+
+static int msm_mctl_v4l2_g_fmt_cap_mplane(struct file *f,
+		void *pctx, struct v4l2_format *pfmt)
+{
+	int rc = 0;
+
+	D("%s\n", __func__);
+	WARN_ON(pctx != f->private_data);
+
+	if (pfmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		return -EINVAL;
+
+	return rc;
+}
+
+/* This function will readjust the format parameters based in HW
+  capabilities. Called by s_fmt_cap
+*/
+static int msm_mctl_v4l2_try_fmt_cap(struct file *f, void *pctx,
+					struct v4l2_format *pfmt)
+{
+	int rc = 0;
+
+	D("%s\n", __func__);
+	WARN_ON(pctx != f->private_data);
+
+	return rc;
+}
+
+static int msm_mctl_v4l2_try_fmt_cap_mplane(struct file *f, void *pctx,
+					struct v4l2_format *pfmt)
+{
+	int rc = 0;
+
+	D("%s\n", __func__);
+	WARN_ON(pctx != f->private_data);
+
+	return rc;
+}
+
+/* This function will reconfig the v4l2 driver and HW device, it should be
+   called after the streaming is stopped.
+*/
+static int msm_mctl_v4l2_s_fmt_cap(struct file *f, void *pctx,
+					struct v4l2_format *pfmt)
+{
+	int rc = 0;
+	/* get the video device */
+	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+		struct msm_cam_v4l2_dev_inst, eventHandle);
+
+	D("%s\n", __func__);
+	D("%s, inst=0x%x,idx=%d,priv = 0x%p\n",
+		__func__, (u32)pcam_inst, pcam_inst->my_index,
+		(void *)pfmt->fmt.pix.priv);
+	WARN_ON(pctx != f->private_data);
+
+	if (!pcam_inst->vbqueue_initialized) {
+		pcam->mctl.mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
+					V4L2_BUF_TYPE_VIDEO_CAPTURE);
+		pcam_inst->vbqueue_initialized = 1;
+	}
+
+	return rc;
+}
+
+static int msm_mctl_v4l2_s_fmt_cap_mplane(struct file *f, void *pctx,
+				struct v4l2_format *pfmt)
+{
+	int rc = 0, i;
+	struct msm_cam_v4l2_device *pcam = video_drvdata(f);
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+			struct msm_cam_v4l2_dev_inst, eventHandle);
+
+	D("%s Inst %p vbqueue %d\n", __func__,
+		pcam_inst, pcam_inst->vbqueue_initialized);
+	WARN_ON(pctx != f->private_data);
+
+	if (!pcam_inst->vbqueue_initialized) {
+		pcam->mctl.mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
+					V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+		pcam_inst->vbqueue_initialized = 1;
+	}
+	for (i = 0; i < pcam->num_fmts; i++)
+		if (pcam->usr_fmts[i].fourcc == pfmt->fmt.pix_mp.pixelformat)
+			break;
+	if (i == pcam->num_fmts) {
+		pr_err("%s: User requested pixelformat %x not supported\n",
+			__func__, pfmt->fmt.pix_mp.pixelformat);
+		return -EINVAL;
+	}
+	pcam_inst->vid_fmt = *pfmt;
+	pcam_inst->sensor_pxlcode =
+		pcam->usr_fmts[i].pxlcode;
+	D("%s: inst=%p, width=%d, heigth=%d\n",
+		__func__, pcam_inst,
+		pcam_inst->vid_fmt.fmt.pix_mp.width,
+		pcam_inst->vid_fmt.fmt.pix_mp.height);
+	return rc;
+}
+static int msm_mctl_v4l2_g_jpegcomp(struct file *f, void *pctx,
+				struct v4l2_jpegcompression *pcomp)
+{
+	int rc = -EINVAL;
+
+	D("%s\n", __func__);
+	WARN_ON(pctx != f->private_data);
+
+	return rc;
+}
+
+static int msm_mctl_v4l2_s_jpegcomp(struct file *f, void *pctx,
+				struct v4l2_jpegcompression *pcomp)
+{
+	int rc = -EINVAL;
+
+	D("%s\n", __func__);
+	WARN_ON(pctx != f->private_data);
+
+	return rc;
+}
+
+
+static int msm_mctl_v4l2_g_crop(struct file *f, void *pctx,
+					struct v4l2_crop *crop)
+{
+	int rc = -EINVAL;
+
+	D("%s\n", __func__);
+	WARN_ON(pctx != f->private_data);
+
+	return rc;
+}
+
+static int msm_mctl_v4l2_s_crop(struct file *f, void *pctx,
+					struct v4l2_crop *a)
+{
+	int rc = -EINVAL;
+
+	D("%s\n", __func__);
+	WARN_ON(pctx != f->private_data);
+
+	return rc;
+}
+
+/* Stream type-dependent parameter ioctls */
+static int msm_mctl_v4l2_g_parm(struct file *f, void *pctx,
+				struct v4l2_streamparm *a)
+{
+	int rc = -EINVAL;
+	return rc;
+}
+
+static int msm_mctl_vidbuf_get_path(u32 extendedmode)
+{
+	switch (extendedmode) {
+	case MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL:
+		return OUTPUT_TYPE_T;
+	case MSM_V4L2_EXT_CAPTURE_MODE_MAIN:
+		return OUTPUT_TYPE_S;
+	case MSM_V4L2_EXT_CAPTURE_MODE_VIDEO:
+		return OUTPUT_TYPE_V;
+	case MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT:
+	case MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW:
+	default:
+		return OUTPUT_TYPE_P;
+	}
+}
+
+static int msm_mctl_v4l2_s_parm(struct file *f, void *pctx,
+				struct v4l2_streamparm *a)
+{
+	int rc = 0;
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst = container_of(f->private_data,
+		struct msm_cam_v4l2_dev_inst, eventHandle);
+	pcam_inst->image_mode = a->parm.capture.extendedmode;
+	pcam_inst->pcam->mctl_node.dev_inst_map[pcam_inst->image_mode] =
+		pcam_inst;
+	pcam_inst->path = msm_mctl_vidbuf_get_path(pcam_inst->image_mode);
+	D("%s path=%d, image mode = %d rc=%d\n", __func__,
+		pcam_inst->path, pcam_inst->image_mode, rc);
+	return rc;
+}
+
+static int msm_mctl_v4l2_subscribe_event(struct v4l2_fh *fh,
+			struct v4l2_event_subscription *sub)
+{
+	int rc = 0;
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst =
+		(struct msm_cam_v4l2_dev_inst *)container_of(fh,
+		struct msm_cam_v4l2_dev_inst, eventHandle);
+
+	D("%s:fh = 0x%x, type = 0x%x\n", __func__, (u32)fh, sub->type);
+
+	if (sub->type == V4L2_EVENT_ALL)
+		sub->type = V4L2_EVENT_PRIVATE_START+MSM_CAM_APP_NOTIFY_EVENT;
+	rc = v4l2_event_subscribe(fh, sub);
+	if (rc < 0)
+		pr_err("%s: failed for evtType = 0x%x, rc = %d\n",
+						__func__, sub->type, rc);
+	return rc;
+}
+
+static int msm_mctl_v4l2_unsubscribe_event(struct v4l2_fh *fh,
+			struct v4l2_event_subscription *sub)
+{
+	int rc = 0;
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	pcam_inst =
+		(struct msm_cam_v4l2_dev_inst *)container_of(fh,
+		struct msm_cam_v4l2_dev_inst, eventHandle);
+
+	D("%s: fh = 0x%x\n", __func__, (u32)fh);
+
+	rc = v4l2_event_unsubscribe(fh, sub);
+	D("%s: rc = %d\n", __func__, rc);
+	return rc;
+}
+
+/* mctl node v4l2_ioctl_ops */
+static const struct v4l2_ioctl_ops g_msm_mctl_ioctl_ops = {
+	.vidioc_querycap = msm_mctl_v4l2_querycap,
+
+	.vidioc_s_crop = msm_mctl_v4l2_s_crop,
+	.vidioc_g_crop = msm_mctl_v4l2_g_crop,
+
+	.vidioc_queryctrl = msm_mctl_v4l2_queryctrl,
+	.vidioc_g_ctrl = msm_mctl_v4l2_g_ctrl,
+	.vidioc_s_ctrl = msm_mctl_v4l2_s_ctrl,
+
+	.vidioc_reqbufs = msm_mctl_v4l2_reqbufs,
+	.vidioc_querybuf = msm_mctl_v4l2_querybuf,
+	.vidioc_qbuf = msm_mctl_v4l2_qbuf,
+	.vidioc_dqbuf = msm_mctl_v4l2_dqbuf,
+
+	.vidioc_streamon = msm_mctl_v4l2_streamon,
+	.vidioc_streamoff = msm_mctl_v4l2_streamoff,
+
+	/* format ioctls */
+	.vidioc_enum_fmt_vid_cap = msm_mctl_v4l2_enum_fmt_cap,
+	.vidioc_enum_fmt_vid_cap_mplane = msm_mctl_v4l2_enum_fmt_cap,
+	.vidioc_try_fmt_vid_cap = msm_mctl_v4l2_try_fmt_cap,
+	.vidioc_try_fmt_vid_cap_mplane = msm_mctl_v4l2_try_fmt_cap_mplane,
+	.vidioc_g_fmt_vid_cap = msm_mctl_v4l2_g_fmt_cap,
+	.vidioc_g_fmt_vid_cap_mplane = msm_mctl_v4l2_g_fmt_cap_mplane,
+	.vidioc_s_fmt_vid_cap = msm_mctl_v4l2_s_fmt_cap,
+	.vidioc_s_fmt_vid_cap_mplane = msm_mctl_v4l2_s_fmt_cap_mplane,
+
+	.vidioc_g_jpegcomp = msm_mctl_v4l2_g_jpegcomp,
+	.vidioc_s_jpegcomp = msm_mctl_v4l2_s_jpegcomp,
+
+	/* Stream type-dependent parameter ioctls */
+	.vidioc_g_parm =  msm_mctl_v4l2_g_parm,
+	.vidioc_s_parm =  msm_mctl_v4l2_s_parm,
+
+	/* event subscribe/unsubscribe */
+	.vidioc_subscribe_event = msm_mctl_v4l2_subscribe_event,
+	.vidioc_unsubscribe_event = msm_mctl_v4l2_unsubscribe_event,
+};
+
+int msm_setup_mctl_node(struct msm_cam_v4l2_device *pcam)
+{
+	int rc = -EINVAL;
+	struct video_device *pvdev = NULL;
+	struct i2c_client *client = v4l2_get_subdevdata(pcam->mctl.sensor_sdev);
+
+	D("%s\n", __func__);
+
+	/* first register the v4l2 device */
+	pcam->mctl_node.v4l2_dev.dev = &client->dev;
+	rc = v4l2_device_register(pcam->mctl_node.v4l2_dev.dev,
+				&pcam->mctl_node.v4l2_dev);
+	if (rc < 0)
+		return -EINVAL;
+	/*	else
+			pcam->v4l2_dev.notify = msm_cam_v4l2_subdev_notify; */
+
+	/* now setup video device */
+	pvdev = video_device_alloc();
+	if (pvdev == NULL) {
+		pr_err("%s: video_device_alloc failed\n", __func__);
+		return rc;
+	}
+
+	/* init video device's driver interface */
+	D("sensor name = %s, sizeof(pvdev->name)=%d\n",
+			pcam->mctl.sensor_sdev->name, sizeof(pvdev->name));
+
+	/* device info - strlcpy is safer than strncpy but
+	   only if architecture supports*/
+	strlcpy(pvdev->name, pcam->mctl.sensor_sdev->name,
+			sizeof(pvdev->name));
+
+	pvdev->release   = video_device_release;
+	pvdev->fops	  = &g_msm_mctl_fops;
+	pvdev->ioctl_ops  = &g_msm_mctl_ioctl_ops;
+	pvdev->minor	  = -1;
+	pvdev->vfl_type   = 1;
+
+	/* register v4l2 video device to kernel as /dev/videoXX */
+	D("%s video_register_device\n", __func__);
+	rc = video_register_device(pvdev,
+			VFL_TYPE_GRABBER,
+			-1);
+	if (rc) {
+		pr_err("%s: video_register_device failed\n", __func__);
+		goto reg_fail;
+	}
+	D("%s: video device registered as /dev/video%d\n",
+			__func__, pvdev->num);
+
+	/* connect pcam and mctl video dev to each other */
+	pcam->mctl_node.pvdev	= pvdev;
+	video_set_drvdata(pcam->mctl_node.pvdev, pcam);
+
+	return rc ;
+
+reg_fail:
+	video_device_release(pvdev);
+	v4l2_device_unregister(&pcam->mctl_node.v4l2_dev);
+	pcam->mctl_node.v4l2_dev.dev = NULL;
+	return rc;
+}
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 7a0cc02..1ab76fe 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.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
@@ -186,6 +186,8 @@
 	buf->state = MSM_BUFFER_STATE_DEQUEUED;
 	D("%s: inst=0x%x, buf=0x, %x, idx=%d\n", __func__,
 	(uint32_t)pcam_inst, (uint32_t)buf, vb->v4l2_buf.index);
+	D("%s: inst=%p, buf=%x, idx=%d\n", __func__,
+	pcam_inst, (uint32_t)buf, vb->v4l2_buf.index);
 	return 0;
 }
 
@@ -260,12 +262,6 @@
 
 static int msm_vb2_ops_stop_streaming(struct vb2_queue *q)
 {
-	int rc = 0;
-	struct msm_free_buf *free_buf = NULL;
-	struct msm_cam_v4l2_dev_inst *pcam_inst = vb2_get_drv_priv(q);
-	if (rc != 0)
-		msm_mctl_release_free_buf(&pcam_inst->pcam->mctl,
-					pcam_inst->path, free_buf);
 	return 0;
 }
 
@@ -286,6 +282,8 @@
 	D("%s pcam_inst=%p,(vb=0x%p),idx=%d,len=%d\n",
 		__func__, pcam_inst,
 	vb, vb->v4l2_buf.index, vb->v4l2_buf.length);
+	D("%s pcam_inst=%p, idx=%d\n", __func__, pcam_inst,
+		vb->v4l2_buf.index);
 	buf = container_of(vb, struct msm_frame_buffer, vidbuf);
 	spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
 	/* we are returning a buffer to the queue */
@@ -326,29 +324,13 @@
 	return 0;
 }
 
-int msm_mctl_out_type_to_inst_index(struct msm_cam_v4l2_device *pcam,
-					int out_type)
+int msm_mctl_img_mode_to_inst_index(struct msm_cam_media_controller *pmctl,
+					int image_mode)
 {
-	int image_mode;
-	switch (out_type) {
-	case VFE_MSG_OUTPUT_P:
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
-		break;
-	case VFE_MSG_OUTPUT_V:
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
-		break;
-	case VFE_MSG_OUTPUT_S:
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
-		break;
-	case VFE_MSG_OUTPUT_T:
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
-		break;
-	default:
-		image_mode = -1;
-		break;
-	}
-	if ((image_mode >= 0) && pcam->dev_inst_map[image_mode])
-		return pcam->dev_inst_map[image_mode]->my_index;
+	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;
 	else
 		return -EINVAL;
 }
@@ -367,7 +349,7 @@
 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,
-	int msg_type, struct msm_free_buf *fbuf)
+	int image_mode, struct msm_free_buf *fbuf)
 {
 	struct msm_frame_buffer *buf = NULL, *tmp;
 	uint32_t buf_phyaddr = 0;
@@ -408,14 +390,14 @@
 int msm_mctl_buf_done_proc(
 		struct msm_cam_media_controller *pmctl,
 		struct msm_cam_v4l2_dev_inst *pcam_inst,
-		int msg_type, struct msm_free_buf *fbuf,
+		int image_mode, struct msm_free_buf *fbuf,
 		uint32_t *frame_id, int gen_timestamp)
 {
 	struct msm_frame_buffer *buf = NULL;
 	int del_buf = 1;
 
 	buf = msm_mctl_buf_find(pmctl, pcam_inst, del_buf,
-					msg_type, fbuf);
+					image_mode, fbuf);
 	if (!buf) {
 		pr_err("%s: buf=0x%x not found\n",
 			__func__, fbuf->ch_paddr[0]);
@@ -431,23 +413,24 @@
 	return 0;
 }
 
+
 int msm_mctl_buf_done(struct msm_cam_media_controller *p_mctl,
-			int msg_type, struct msm_free_buf *fbuf,
+			int image_mode, struct msm_free_buf *fbuf,
 			uint32_t frame_id)
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	int idx, rc;
 	int pp_divert_type = 0, pp_type = 0;
 
-	msm_mctl_check_pp(p_mctl, msg_type, &pp_divert_type, &pp_type);
-	D("%s: pp_type=%d, pp_divert_type = %d",
-		 __func__, pp_type, pp_divert_type);
+	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);
 	if (pp_type || pp_divert_type)
 		rc = msm_mctl_do_pp_divert(p_mctl,
-		msg_type, fbuf, frame_id, pp_type);
+		image_mode, fbuf, frame_id, pp_type);
 	else {
-		idx = msm_mctl_out_type_to_inst_index(
-				p_mctl->sync.pcam_sync, msg_type);
+		idx = msm_mctl_img_mode_to_inst_index(
+				p_mctl, image_mode);
 		if (idx < 0) {
 			pr_err("%s Invalid instance, dropping buffer\n",
 				__func__);
@@ -455,7 +438,7 @@
 		}
 		pcam_inst = p_mctl->sync.pcam_sync->dev_inst[idx];
 		rc = msm_mctl_buf_done_proc(p_mctl, pcam_inst,
-				msg_type, fbuf,
+				image_mode, fbuf,
 				&frame_id, 1);
 	}
 	return rc;
@@ -467,15 +450,47 @@
 	return 0;
 }
 
+struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst(
+				struct msm_cam_media_controller *pmctl,
+				int image_mode)
+{
+	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]) {
+			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;
+}
+
 int msm_mctl_reserve_free_buf(
 		struct msm_cam_media_controller *pmctl,
-		int msg_type, struct msm_free_buf *free_buf)
+		struct msm_cam_v4l2_dev_inst *pref_pcam_inst,
+		int image_mode, struct msm_free_buf *free_buf)
 {
-	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	struct msm_cam_v4l2_dev_inst *pcam_inst = pref_pcam_inst;
 	unsigned long flags = 0;
 	struct videobuf2_contig_pmem *mem;
 	struct msm_frame_buffer *buf = NULL;
-	int rc = -EINVAL, idx, i;
+	int rc = -EINVAL, i;
 	uint32_t buf_idx, plane_offset = 0;
 
 	if (!free_buf || !pmctl) {
@@ -483,13 +498,14 @@
 		return rc;
 	}
 	memset(free_buf, 0, sizeof(struct msm_free_buf));
-	idx = msm_mctl_out_type_to_inst_index(pmctl->sync.pcam_sync,
-		msg_type);
-	if (idx < 0) {
-		pr_err("%s Invalid instance, returning\n", __func__);
-		return idx;
-	}
-	pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+
+	/* If the caller wants to reserve a buffer from a particular
+	 * camera instance, he would send the preferred camera instance.
+	 * If the preferred camera instance is NULL, get the
+	 * camera instance using the image mode passed */
+	if (!pcam_inst)
+		pcam_inst = msm_mctl_get_pcam_inst(pmctl, image_mode);
+
 	if (!pcam_inst || !pcam_inst->streamon) {
 		pr_err("%s: stream is turned off\n", __func__);
 		return rc;
@@ -518,6 +534,7 @@
 				videobuf2_to_pmem_contig(&buf->vidbuf, i) +
 				pcam_inst->buf_offset[buf_idx][i].data_offset +
 				plane_offset;
+
 			}
 		} else {
 			mem = vb2_plane_cookie(&buf->vidbuf, 0);
@@ -529,9 +546,9 @@
 		}
 		free_buf->vb = (uint32_t)buf;
 		buf->state = MSM_BUFFER_STATE_RESERVED;
-		D("%s idx=%d,inst=0x%p,idx=%d,paddr=0x%x, "
+		D("%s inst=0x%p, idx=%d, paddr=0x%x, "
 			"ch1 addr=0x%x\n", __func__,
-			idx, pcam_inst,	buf->vidbuf.v4l2_buf.index,
+			pcam_inst, buf->vidbuf.v4l2_buf.index,
 			free_buf->ch_paddr[0], free_buf->ch_paddr[1]);
 		rc = 0;
 		break;
@@ -544,23 +561,23 @@
 }
 
 int msm_mctl_release_free_buf(struct msm_cam_media_controller *pmctl,
-				int msg_type, struct msm_free_buf *free_buf)
+				struct msm_cam_v4l2_dev_inst *pcam_inst,
+				int image_mode, struct msm_free_buf *free_buf)
 {
-	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	unsigned long flags = 0;
 	struct msm_frame_buffer *buf = NULL;
 	uint32_t buf_phyaddr = 0;
-	int rc = -EINVAL, idx;
+	int rc = -EINVAL;
 
 	if (!free_buf)
 		return rc;
 
-	idx = msm_mctl_out_type_to_inst_index(pmctl->sync.pcam_sync, msg_type);
-	if (idx < 0) {
-		pr_err("%s Invalid instance, buffer not released\n", __func__);
-		return idx;
+	if (!pcam_inst) {
+		pr_err("%s Invalid instance, buffer not released\n",
+			__func__);
+		return rc;
 	}
-	pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+
 	spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
 	list_for_each_entry(buf, &pcam_inst->free_vq, list) {
 		buf_phyaddr =
@@ -582,40 +599,46 @@
 
 int msm_mctl_buf_done_pp(
 		struct msm_cam_media_controller *pmctl,
-		int msg_type, struct msm_free_buf *frame, int dirty)
+		int image_mode, struct msm_free_buf *frame, int dirty)
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
-	int idx, rc = 0;
+	int rc = 0, idx;
 
-	idx = msm_mctl_out_type_to_inst_index(
-		pmctl->sync.pcam_sync, msg_type);
+	idx = msm_mctl_img_mode_to_inst_index(pmctl, image_mode);
 	if (idx < 0) {
-		pr_err("%s Invalid instance, buffer dropped\n", __func__);
+		pr_err("%s Invalid instance, buffer not released\n", __func__);
 		return idx;
 	}
 	pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+	if (!pcam_inst) {
+		pr_err("%s Invalid instance, cannot send buf to user",
+			__func__);
+		return -EINVAL;
+	}
+
 	D("%s:inst=0x%p, paddr=0x%x, dirty=%d",
 		__func__, pcam_inst, frame->ch_paddr[0], dirty);
 	if (dirty)
 		/* the frame is dirty, not going to disptach to app */
-		rc = msm_mctl_release_free_buf(pmctl, msg_type, frame);
+		rc = msm_mctl_release_free_buf(pmctl, pcam_inst,
+						image_mode, frame);
 	else
 		rc = msm_mctl_buf_done_proc(pmctl, pcam_inst,
-			msg_type, frame, NULL, 0);
+			image_mode, frame, NULL, 0);
 	return rc;
 }
 
 struct msm_frame_buffer *msm_mctl_get_free_buf(
 		struct msm_cam_media_controller *pmctl,
-		int msg_type)
+		int image_mode)
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	unsigned long flags = 0;
 	struct msm_frame_buffer *buf = NULL;
 	int rc = -EINVAL, idx;
 
-	idx = msm_mctl_out_type_to_inst_index(pmctl->sync.pcam_sync,
-		msg_type);
+	idx = msm_mctl_img_mode_to_inst_index(pmctl,
+		image_mode);
 	if (idx < 0) {
 		pr_err("%s Invalid instance, cant get buffer\n", __func__);
 		return NULL;
@@ -646,15 +669,15 @@
 
 int msm_mctl_put_free_buf(
 		struct msm_cam_media_controller *pmctl,
-		int msg_type, struct msm_frame_buffer *my_buf)
+		int image_mode, struct msm_frame_buffer *my_buf)
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	unsigned long flags = 0;
 	int rc = 0, idx;
 	struct msm_frame_buffer *buf = NULL;
 
-	idx = msm_mctl_out_type_to_inst_index(pmctl->sync.pcam_sync,
-		msg_type);
+	idx = msm_mctl_img_mode_to_inst_index(pmctl,
+		image_mode);
 	if (idx < 0) {
 		pr_err("%s Invalid instance, cant put buffer\n", __func__);
 		return idx;
@@ -680,7 +703,7 @@
 }
 
 int msm_mctl_buf_del(struct msm_cam_media_controller *pmctl,
-	int msg_type,
+	int image_mode,
 	struct msm_frame_buffer *my_buf)
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
@@ -688,8 +711,8 @@
 	unsigned long flags = 0;
 	int idx;
 
-	idx = msm_mctl_out_type_to_inst_index(pmctl->sync.pcam_sync,
-		msg_type);
+	idx = msm_mctl_img_mode_to_inst_index(pmctl,
+		image_mode);
 	if (idx < 0) {
 		pr_err("%s Invalid instance, cant delete buffer\n", __func__);
 		return idx;
@@ -712,3 +735,43 @@
 	return -EINVAL;
 }
 
+int msm_mctl_buf_return_buf(struct msm_cam_media_controller *pmctl,
+			int image_mode, struct msm_frame_buffer *rbuf)
+{
+	int idx = 0;
+	struct msm_frame_buffer *buf = NULL;
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	struct msm_cam_v4l2_device *pcam = pmctl->sync.pcam_sync;
+	unsigned long flags = 0;
+
+	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 {
+		pr_err("%s Invalid image mode %d ", __func__, image_mode);
+		return -EINVAL;
+	}
+
+	if (!pcam_inst) {
+		pr_err("%s Invalid instance\n", __func__);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
+	if (!list_empty(&pcam_inst->free_vq)) {
+		list_for_each_entry(buf, &pcam_inst->free_vq, list) {
+			if (rbuf == buf) {
+				D("%s Return buffer %x in pcam_inst %p ",
+				__func__, (int)rbuf, pcam_inst);
+				buf->state = MSM_BUFFER_STATE_QUEUED;
+				spin_unlock_irqrestore(&pcam_inst->vq_irqlock,
+					flags);
+				return 0;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+	return -EINVAL;
+}
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index 6a2c8aa..1593e7e 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.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
@@ -66,39 +66,36 @@
 }
 
 int msm_mctl_check_pp(struct msm_cam_media_controller *p_mctl,
-	int msg_type, int *pp_divert_type, int *pp_type)
+	int image_mode, int *pp_divert_type, int *pp_type)
 {
 	int rc = 0;
 	unsigned long flags;
 	uint32_t pp_key = 0;
-	int image_mode = MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT;
 
 	*pp_type = 0;
 	*pp_divert_type = 0;
 	spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
-	switch (msg_type) {
-	case VFE_MSG_OUTPUT_P:
+	switch (image_mode) {
+	case MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW:
 		pp_key = PP_PREV;
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
 		if (p_mctl->pp_info.pp_key & pp_key)
 			*pp_divert_type = OUTPUT_TYPE_P;
 		if (p_mctl->pp_info.pp_ctrl.pp_msg_type & OUTPUT_TYPE_P)
 			*pp_type = OUTPUT_TYPE_P;
 		break;
-	case VFE_MSG_OUTPUT_S:
+	case MSM_V4L2_EXT_CAPTURE_MODE_MAIN:
 		pp_key = PP_SNAP;
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
 		if (p_mctl->pp_info.pp_key & pp_key)
 			*pp_divert_type = OUTPUT_TYPE_S;
 		if (p_mctl->pp_info.pp_ctrl.pp_msg_type & OUTPUT_TYPE_S)
 			*pp_type = OUTPUT_TYPE_P;
 		break;
-	case VFE_MSG_OUTPUT_V:
-		if (p_mctl->pp_info.pp_ctrl.pp_msg_type & OUTPUT_TYPE_V)
+	case MSM_V4L2_EXT_CAPTURE_MODE_VIDEO:
+		if (p_mctl->pp_info.pp_ctrl.pp_msg_type == OUTPUT_TYPE_V)
 			*pp_type = OUTPUT_TYPE_V;
 		break;
-	case VFE_MSG_OUTPUT_T:
-		if (p_mctl->pp_info.pp_ctrl.pp_msg_type & OUTPUT_TYPE_T)
+	case MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL:
+		if (p_mctl->pp_info.pp_ctrl.pp_msg_type == OUTPUT_TYPE_T)
 			*pp_type = OUTPUT_TYPE_T;
 		break;
 	default:
@@ -108,36 +105,37 @@
 		*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);
+	__func__, *pp_type, *pp_divert_type);
 	return rc;
 }
 
 int msm_mctl_do_pp_divert(
 	struct msm_cam_media_controller *p_mctl,
-	int msg_type, struct msm_free_buf *fbuf,
+	int image_mode, struct msm_free_buf *fbuf,
 	uint32_t frame_id, int pp_type)
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
-	int idx, rc = 0, i, buf_idx;
+	int rc = 0, i, buf_idx;
 	int del_buf = 0; /* delete from free queue */
 	struct msm_cam_evt_divert_frame div;
 	struct msm_frame_buffer *vb = NULL;
 	struct videobuf2_contig_pmem *mem;
 
-	idx = msm_mctl_out_type_to_inst_index(
-		p_mctl->sync.pcam_sync, msg_type);
-	if (idx < 0) {
-		pr_err("%s Invalid instance. returning\n", __func__);
+	pcam_inst = msm_mctl_get_pcam_inst(p_mctl, image_mode);
+	if (!pcam_inst) {
+		pr_err("%s Invalid instance. Cannot divert frame.\n",
+			__func__);
 		return -EINVAL;
 	}
-	pcam_inst = p_mctl->sync.pcam_sync->dev_inst[idx];
 	vb = msm_mctl_buf_find(p_mctl, pcam_inst,
-		  del_buf, msg_type, fbuf);
+		  del_buf, image_mode, fbuf);
 	if (!vb)
 		return -EINVAL;
 
 	vb->vidbuf.v4l2_buf.sequence = frame_id;
 	buf_idx = vb->vidbuf.v4l2_buf.index;
+	D("%s Diverting frame %d %x Image mode %d\n", __func__, buf_idx,
+		(uint32_t)vb, pcam_inst->image_mode);
 	div.image_mode = pcam_inst->image_mode;
 	div.op_mode    = pcam_inst->pcam->op_mode;
 	div.inst_idx   = pcam_inst->my_index;
@@ -145,6 +143,7 @@
 	p_mctl->pp_info.cur_frame_id[pcam_inst->image_mode] = frame_id;
 	div.frame.frame_id =
 		p_mctl->pp_info.cur_frame_id[pcam_inst->image_mode];
+	div.frame.buf_idx  = buf_idx;
 	div.frame.handle = (uint32_t)vb;
 	msm_mctl_gettimeofday(&div.frame.timestamp);
 	vb->vidbuf.v4l2_buf.timestamp = div.frame.timestamp;
@@ -180,8 +179,11 @@
 			mem = vb2_plane_cookie(&vb->vidbuf, i);
 			div.frame.mp[i].phy_addr =
 				videobuf2_to_pmem_contig(&vb->vidbuf, i);
-			div.frame.mp[i].data_offset =
-			pcam_inst->buf_offset[buf_idx][i].data_offset;
+			if (!pcam_inst->buf_offset)
+				div.frame.mp[i].data_offset = 0;
+			else
+				div.frame.mp[i].data_offset =
+				pcam_inst->buf_offset[buf_idx][i].data_offset;
 			div.frame.mp[i].addr_offset =
 				mem->addr_offset;
 			div.frame.mp[i].fd = (int)mem->vaddr;
@@ -211,6 +213,7 @@
 	pp_frame->handle = (uint32_t)vb;
 	pp_frame->frame_id = vb->vidbuf.v4l2_buf.sequence;
 	pp_frame->timestamp = vb->vidbuf.v4l2_buf.timestamp;
+	pp_frame->buf_idx = buf_idx;
 	/* Get the cookie for 1st plane and store the path.
 	 * Also use this to check the number of planes in
 	 * this buffer.*/
@@ -312,7 +315,7 @@
 		struct msm_vpe_clock_rate clk_rate;
 		if (sizeof(struct msm_vpe_clock_rate) !=
 			pp_cmd->length) {
-			D("%s: vpe cmd size mismatch "
+			pr_err("%s: vpe cmd size mismatch "
 				"(id=%d, length = %d, expect size = %d",
 				__func__, pp_cmd->id, pp_cmd->length,
 				sizeof(struct msm_vpe_clock_rate));
@@ -321,7 +324,7 @@
 		}
 		if (copy_from_user(&clk_rate, pp_cmd->value,
 			sizeof(struct msm_vpe_clock_rate))) {
-			D("%s:clk_rate copy failed", __func__);
+			pr_err("%s:clk_rate copy failed", __func__);
 			return -EFAULT;
 		}
 		pp_cmd->value = (void *)&clk_rate;
@@ -527,18 +530,19 @@
 	return rc;
 }
 
-static int msm_mctl_pp_path_to_msg_type(int path)
+static int msm_mctl_pp_path_to_img_mode(int path)
 {
 	switch (path) {
 	case OUTPUT_TYPE_P:
-		return VFE_MSG_OUTPUT_P;
+		return MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
 	case OUTPUT_TYPE_V:
-		return VFE_MSG_OUTPUT_V;
+		return MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
 	case OUTPUT_TYPE_S:
-		return VFE_MSG_OUTPUT_S;
+		return MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
 	case OUTPUT_TYPE_T:
+		return MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
 	default:
-		return VFE_MSG_OUTPUT_T;
+		return -EINVAL;
 	}
 }
 
@@ -549,7 +553,7 @@
 	struct msm_mctl_pp_frame_buffer pp_buffer;
 	struct msm_frame_buffer *buf = NULL;
 	void __user *argp = (void __user *)pp_cmd->value;
-	int msg_type = VFE_MSG_OUTPUT_V;
+	int img_mode;
 	unsigned long flags;
 
 	switch (pp_cmd->id) {
@@ -557,8 +561,12 @@
 		if (copy_from_user(&pp_buffer, pp_cmd->value,
 				sizeof(pp_buffer)))
 			return -EFAULT;
-		msg_type = msm_mctl_pp_path_to_msg_type(pp_buffer.path);
-		buf = msm_mctl_get_free_buf(p_mctl, msg_type);
+		img_mode = msm_mctl_pp_path_to_img_mode(pp_buffer.path);
+		if (img_mode < 0) {
+			pr_err("%s Invalid image mode\n", __func__);
+			return img_mode;
+		}
+		buf = msm_mctl_get_free_buf(p_mctl, img_mode);
 		pp_buffer.buf_handle = (uint32_t)buf;
 		if (copy_to_user((void *)argp,
 			&pp_buffer,
@@ -572,9 +580,13 @@
 		if (copy_from_user(&pp_buffer, pp_cmd->value,
 				sizeof(pp_buffer)))
 			return -EFAULT;
-		msg_type = msm_mctl_pp_path_to_msg_type(pp_buffer.path);
-			buf = (struct msm_frame_buffer *)pp_buffer.buf_handle;
-		msm_mctl_put_free_buf(p_mctl, msg_type, buf);
+		img_mode = msm_mctl_pp_path_to_img_mode(pp_buffer.path);
+		if (img_mode < 0) {
+			pr_err("%s Invalid image mode\n", __func__);
+			return img_mode;
+		}
+		buf = (struct msm_frame_buffer *)pp_buffer.buf_handle;
+		msm_mctl_put_free_buf(p_mctl, img_mode, buf);
 		break;
 	}
 	case MCTL_CMD_DIVERT_FRAME_PP_PATH: {
@@ -646,17 +658,20 @@
 		if ((MSM_MCTL_PP_VPE_FRAME_TO_APP &
 			pp_frame_cmd->vpe_output_action)) {
 			struct msm_free_buf done_frame;
-			int msg_type =
-				msm_mctl_pp_path_to_msg_type(
+			int img_mode =
+				msm_mctl_pp_path_to_img_mode(
 					pp_frame_cmd->path);
-
+			if (img_mode < 0) {
+				pr_err("%s Invalid image mode\n", __func__);
+				return img_mode;
+			}
 			done_frame.ch_paddr[0] =
 				pp_frame_info->dest_frame.sp.phy_addr;
 			done_frame.vb =
 				pp_frame_info->dest_frame.handle;
 			msm_mctl_buf_done_pp(
-				p_mctl, msg_type, &done_frame, 0);
-			pr_info("%s: vpe done to app, vb=0x%x, path=%d, phy=0x%x",
+				p_mctl, img_mode, &done_frame, 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]);
 		}
@@ -701,43 +716,38 @@
 	void __user *arg)
 {
 	struct msm_cam_evt_divert_frame frame;
-	int msg_type, image_mode, rc = 0;
+	int image_mode, rc = 0;
 	struct msm_free_buf free_buf;
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+
 	memset(&free_buf, 0, sizeof(struct msm_free_buf));
 	if (copy_from_user(&frame, arg,
 		sizeof(struct msm_cam_evt_divert_frame)))
 		return -EFAULT;
-	switch (frame.frame.path) {
-	case OUTPUT_TYPE_P:
-		msg_type = VFE_MSG_OUTPUT_P;
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
-		break;
-	case OUTPUT_TYPE_S:
-		msg_type = VFE_MSG_OUTPUT_S;
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
-		break;
-	case OUTPUT_TYPE_V:
-		msg_type = VFE_MSG_OUTPUT_V;
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
-		break;
-	case OUTPUT_TYPE_T:
-	default:
-		rc = -EFAULT;
-		return rc;
+
+	image_mode = frame.image_mode;
+	if (image_mode <= 0) {
+		pr_err("%s Invalid image mode %d", __func__, image_mode);
+		return -EINVAL;
 	}
-	rc = msm_mctl_reserve_free_buf(p_mctl, msg_type, &free_buf);
+	/* Always reserve the buffer from user's video node */
+	pcam_inst = p_mctl->sync.pcam_sync->dev_inst[image_mode];
+	if (!pcam_inst) {
+		pr_err("%s Instance already closed ", __func__);
+		return -EINVAL;
+	}
+	rc = msm_mctl_reserve_free_buf(p_mctl, pcam_inst,
+					image_mode, &free_buf);
 	if (rc == 0) {
-		frame.frame.sp.phy_addr = free_buf.ch_paddr[0];
-		frame.frame.handle = free_buf.vb;
-		if (copy_to_user((void *)arg,
-				&frame,
-				sizeof(frame))) {
+		msm_mctl_pp_get_phy_addr(pcam_inst, free_buf.vb, &frame.frame);
+		if (copy_to_user((void *)arg, &frame, sizeof(frame))) {
 			ERR_COPY_TO_USER();
 			rc = -EFAULT;
 		}
 	}
-	D("%s: reserve free buf, rc = %d, phy = 0x%x",
-		__func__, rc, free_buf.ch_paddr[0]);
+	D("%s: reserve free buf got buffer %d from %p rc = %d, phy = 0x%x",
+		__func__, frame.frame.buf_idx,
+		pcam_inst, rc, free_buf.ch_paddr[0]);
 	return rc;
 }
 
@@ -745,33 +755,36 @@
 	struct msm_cam_media_controller *p_mctl,
 	void __user *arg)
 {
-	struct msm_cam_evt_divert_frame frame;
-	int msg_type, image_mode, rc = 0;
+	struct msm_cam_evt_divert_frame div_frame;
+	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	struct msm_pp_frame *frame;
+	int image_mode, rc = 0;
 	struct msm_free_buf free_buf;
 
-	if (copy_from_user(&frame, arg,
+	if (copy_from_user(&div_frame, arg,
 		sizeof(struct msm_cam_evt_divert_frame)))
 		return -EFAULT;
-	switch (frame.frame.path) {
-	case OUTPUT_TYPE_P:
-		msg_type = VFE_MSG_OUTPUT_P;
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
-		break;
-	case OUTPUT_TYPE_S:
-		msg_type = VFE_MSG_OUTPUT_S;
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
-		break;
-	case OUTPUT_TYPE_V:
-		msg_type = VFE_MSG_OUTPUT_V;
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
-		break;
-	case OUTPUT_TYPE_T:
-	default:
-		rc = -EFAULT;
-		return rc;
+
+	image_mode = div_frame.image_mode;
+	if (image_mode < 0) {
+		pr_err("%s Invalid image mode %d\n", __func__, image_mode);
+		return -EINVAL;
 	}
-	free_buf.ch_paddr[0] = frame.frame.sp.phy_addr;
-	rc = msm_mctl_release_free_buf(p_mctl, msg_type, &free_buf);
+	frame = &div_frame.frame;
+	if (frame->num_planes > 1)
+		free_buf.ch_paddr[0] = frame->mp[0].phy_addr;
+	else
+		free_buf.ch_paddr[0] = frame->sp.phy_addr;
+
+	pcam_inst = msm_mctl_get_pcam_inst(p_mctl, image_mode);
+	if (!pcam_inst) {
+		pr_err("%s Invalid instance. Cannot release frame.\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	rc = msm_mctl_release_free_buf(p_mctl, pcam_inst,
+					image_mode, &free_buf);
 	D("%s: release free buf, rc = %d, phy = 0x%x",
 		__func__, rc, free_buf.ch_paddr[0]);
 
@@ -799,7 +812,7 @@
 	void __user *arg)
 {
 	struct msm_pp_frame frame;
-	int msg_type, image_mode, rc = 0;
+	int image_mode, rc = 0;
 	int dirty = 0;
 	struct msm_free_buf buf;
 	unsigned long flags;
@@ -808,23 +821,10 @@
 		return -EFAULT;
 
 	spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
-	switch (frame.path) {
-	case OUTPUT_TYPE_P:
-		msg_type = VFE_MSG_OUTPUT_P;
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
-		break;
-	case OUTPUT_TYPE_S:
-		msg_type = VFE_MSG_OUTPUT_S;
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
-		break;
-	case OUTPUT_TYPE_V:
-		msg_type = VFE_MSG_OUTPUT_V;
-		image_mode = MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
-		break;
-	case OUTPUT_TYPE_T:
-	default:
-		rc = -EFAULT;
-		goto err;
+	image_mode = msm_mctl_pp_path_to_img_mode(frame.path);
+	if (image_mode < 0) {
+		pr_err("%s Invalid image mode\n", __func__);
+		return image_mode;
 	}
 	D("%s Returning frame %x id %d to kernel ", __func__,
 		(int)frame.handle, frame.frame_id);
@@ -848,10 +848,7 @@
 	}
 	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
 	/* here buf.addr is phy_addr */
-	rc = msm_mctl_buf_done_pp(p_mctl, msg_type, &buf, dirty);
-	return rc;
-err:
-	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
+	rc = msm_mctl_buf_done_pp(p_mctl, image_mode, &buf, dirty);
 	return rc;
 }
 
@@ -864,11 +861,13 @@
 	int dirty = 0;
 	struct msm_free_buf buf;
 	unsigned long flags;
+	D("%s enter\n", __func__);
 
 	if (copy_from_user(&frame, arg, sizeof(frame)))
 		return -EFAULT;
 
 	spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
+	D("%s Frame path: %d\n", __func__, frame.path);
 	switch (frame.path) {
 	case OUTPUT_TYPE_P:
 		msg_type = VFE_MSG_OUTPUT_P;
@@ -887,17 +886,47 @@
 		rc = -EFAULT;
 		goto err;
 	}
+
 	if (frame.num_planes > 1)
-		buf.ch_paddr[0] = frame.mp[0].phy_addr;
+		buf.ch_paddr[0] = frame.mp[0].phy_addr +
+					frame.mp[0].data_offset;
 	else
-		buf.ch_paddr[0] = frame.sp.phy_addr;
+		buf.ch_paddr[0] = frame.sp.phy_addr + frame.sp.y_off;
+
 	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
-	/* here buf.addr is phy_addr */
-	rc = msm_mctl_buf_done_pp(p_mctl, msg_type, &buf, dirty);
+	D("%s Frame done id: %d\n", __func__, frame.frame_id);
+	rc = msm_mctl_buf_done_pp(p_mctl, image_mode, &buf, dirty);
 	return rc;
 err:
 	spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
 	return rc;
 }
 
+int msm_mctl_pp_mctl_divert_done(
+	struct msm_cam_media_controller *p_mctl,
+	void __user *arg)
+{
+	struct msm_cam_evt_divert_frame div_frame;
+	struct msm_frame_buffer *buf;
+	int image_mode, rc = 0;
 
+	if (copy_from_user(&div_frame, arg,
+			sizeof(struct msm_cam_evt_divert_frame))) {
+		pr_err("%s copy from user failed ", __func__);
+		return -EFAULT;
+	}
+
+	if (!div_frame.frame.handle) {
+		pr_err("%s Invalid buffer handle ", __func__);
+		return -EINVAL;
+	}
+	image_mode = div_frame.image_mode;
+	buf = (struct msm_frame_buffer *)div_frame.frame.handle;
+	D("%s Returning buffer %x Image mode %d ", __func__,
+		(int)buf, image_mode);
+	rc = msm_mctl_buf_return_buf(p_mctl, image_mode, buf);
+	if (rc < 0)
+		pr_err("%s Error returning mctl buffer ", __func__);
+
+	return rc;
+}
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index b04f07c..4b86bd8 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.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
@@ -460,63 +460,35 @@
 	vfe32_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info++;
 
 	switch (mode) {
-
-	case OUTPUT_2:
-		vfe32_ctrl->outpath.output_mode |= VFE32_OUTPUT_MODE_PT;
+	case OUTPUT_PRIM:
+		vfe32_ctrl->outpath.output_mode =
+			VFE32_OUTPUT_MODE_PRIMARY;
 		break;
-
-	case OUTPUT_1_AND_2:
-		/* use wm0& 4 for thumbnail, wm1&5 for main image.*/
-		vfe32_ctrl->outpath.output_mode |=
-			VFE32_OUTPUT_MODE_S;  /* main image.*/
-		vfe32_ctrl->outpath.output_mode |=
-			VFE32_OUTPUT_MODE_PT;  /* thumbnail. */
+	case OUTPUT_PRIM_ALL_CHNLS:
+		vfe32_ctrl->outpath.output_mode =
+			VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
 		break;
-
-	case OUTPUT_1_2_AND_3:
-		CDBG("%s: OUTPUT_ZSL", __func__);
-		/* use wm0& 4 for postview, wm1&5 for preview.*/
-		/* use wm2& 6 for main img */
+	case OUTPUT_PRIM|OUTPUT_SEC:
+		vfe32_ctrl->outpath.output_mode =
+			VFE32_OUTPUT_MODE_PRIMARY;
 		vfe32_ctrl->outpath.output_mode |=
-			VFE32_OUTPUT_MODE_S;  /* main image.*/
-		vfe32_ctrl->outpath.output_mode |=
-			VFE32_OUTPUT_MODE_P;  /* preview. */
-		vfe32_ctrl->outpath.output_mode |=
-			VFE32_OUTPUT_MODE_T;  /* thumbnail. */
+			VFE32_OUTPUT_MODE_SECONDARY;
 		break;
-
-	case OUTPUT_1_AND_3:
-		/* use wm0& 4 for preview, wm1&5 for video.*/
+	case OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS:
+		vfe32_ctrl->outpath.output_mode =
+			VFE32_OUTPUT_MODE_PRIMARY;
 		vfe32_ctrl->outpath.output_mode |=
-			VFE32_OUTPUT_MODE_V;  /* video*/
-		vfe32_ctrl->outpath.output_mode |=
-			VFE32_OUTPUT_MODE_PT;  /* preview */
+			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
 		break;
-	case CAMIF_TO_AXI_VIA_OUTPUT_2:
-		/* use wm0 only */
-		CDBG("config axi for raw snapshot.\n");
-		vfe32_ctrl->outpath.out1.ch0 = 0; /* raw */
-		vfe32_ctrl->outpath.output_mode |= VFE32_OUTPUT_MODE_S;
-		break;
-	case OUTPUT_ALL_CHNLS:
-		/* YV12 preview */
+	case OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC:
+		vfe32_ctrl->outpath.output_mode =
+			VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
 		vfe32_ctrl->outpath.output_mode |=
-			VFE32_OUTPUT_MODE_P_ALL_CHNLS;
-		/* video */
-		vfe32_ctrl->outpath.output_mode |=
-			VFE32_OUTPUT_MODE_V;
-		break;
-	case OUTPUT_ZSL_ALL_CHNLS:
-		CDBG("%s: OUTPUT_ZSL_ALL_CHNLS", __func__);
-		vfe32_ctrl->outpath.output_mode |=
-			VFE32_OUTPUT_MODE_S;  /* main image.*/
-		vfe32_ctrl->outpath.output_mode |=
-			VFE32_OUTPUT_MODE_P_ALL_CHNLS;  /* preview. */
-		vfe32_ctrl->outpath.output_mode |=
-			VFE32_OUTPUT_MODE_T;  /* thumbnail. */
+			VFE32_OUTPUT_MODE_SECONDARY;
 		break;
 	default:
-		break;
+		pr_err("%s Invalid AXI mode %d ", __func__, mode);
+		return -EINVAL;
 	}
 	msm_io_w(*ao, vfe32_ctrl->vfebase +
 		VFE_BUS_IO_FORMAT_CFG);
@@ -545,7 +517,8 @@
 	vfe32_ctrl->update_ack_pending = FALSE;
 	spin_unlock_irqrestore(&vfe32_ctrl->update_ack_lock, flags);
 
-	vfe32_ctrl->recording_state = VFE_REC_STATE_IDLE;
+	vfe32_ctrl->recording_state = VFE_STATE_IDLE;
+	vfe32_ctrl->liveshot_state = VFE_STATE_IDLE;
 
 	atomic_set(&vfe32_ctrl->vstate, 0);
 
@@ -734,7 +707,7 @@
 	struct msm_sync *sync = vfe_syncdata;
 	msm_camio_bus_scale_cfg(
 		sync->sdata->pdata->cam_bus_scale_table, S_VIDEO);
-	vfe32_ctrl->recording_state = VFE_REC_STATE_START_REQUESTED;
+	vfe32_ctrl->recording_state = VFE_STATE_START_REQUESTED;
 	msm_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 	return 0;
 }
@@ -742,17 +715,24 @@
 static int vfe32_stop_recording(void)
 {
 	struct msm_sync *sync = vfe_syncdata;
-	vfe32_ctrl->recording_state = VFE_REC_STATE_STOP_REQUESTED;
+	vfe32_ctrl->recording_state = VFE_STATE_STOP_REQUESTED;
 	msm_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 	msm_camio_bus_scale_cfg(
 		sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 	return 0;
 }
 
-static void vfe32_liveshot(void){
+static void vfe32_start_liveshot(void){
 	struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
 	if (p_sync)
 		p_sync->liveshot_enabled = true;
+
+	/* Hardcode 1 live snapshot for now. */
+	vfe32_ctrl->outpath.out0.capture_cnt = 1;
+	vfe32_ctrl->vfe_capture_count = vfe32_ctrl->outpath.out0.capture_cnt;
+
+	vfe32_ctrl->liveshot_state = VFE_STATE_START_REQUESTED;
+	msm_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 }
 
 static int vfe32_zsl(void)
@@ -765,55 +745,57 @@
 
 	CDBG("%s:op mode %d O/P Mode %d\n", __func__,
 		vfe32_ctrl->operation_mode, vfe32_ctrl->outpath.output_mode);
-	if ((vfe32_ctrl->operation_mode == VFE_MODE_OF_OPERATION_ZSL)) {
-		if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_P) {
-			irq_comp_mask |=
-				((0x1 << (vfe32_ctrl->outpath.out0.ch0)) |
+
+	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_PRIMARY) {
+		irq_comp_mask |= ((0x1 << (vfe32_ctrl->outpath.out0.ch0)) |
 				(0x1 << (vfe32_ctrl->outpath.out0.ch1)));
-		} else if (vfe32_ctrl->outpath.output_mode &
-				VFE32_OUTPUT_MODE_P_ALL_CHNLS) {
-			pr_debug("%s Enabling all channels ", __func__);
-			irq_comp_mask |= (0x1 << vfe32_ctrl->outpath.out0.ch0 |
-				0x1 << vfe32_ctrl->outpath.out0.ch1 |
-				0x1 << vfe32_ctrl->outpath.out0.ch2);
-		}
-		if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_T) {
-			irq_comp_mask |=
-				((0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8)) |
-				(0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8)));
-		}
-		if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_S) {
-			irq_comp_mask |=
-			((0x1 << (vfe32_ctrl->outpath.out2.ch0 + 8)) |
-			(0x1 << (vfe32_ctrl->outpath.out2.ch1 + 8)));
-		}
-		if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_P) {
-			msm_io_w(1, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
-			msm_io_w(1, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
-		} else if (vfe32_ctrl->outpath.output_mode &
-					VFE32_OUTPUT_MODE_P_ALL_CHNLS) {
-			msm_io_w(1, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
-			msm_io_w(1, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
-			msm_io_w(1, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch2]);
-		}
-		if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_T) {
-			msm_io_w(1, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
-			msm_io_w(1, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
-		}
-		if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_S) {
-			msm_io_w(1, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out2.ch0]);
-			msm_io_w(1, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out2.ch1]);
-		}
+	} else if (vfe32_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+		irq_comp_mask |= ((0x1 << (vfe32_ctrl->outpath.out0.ch0)) |
+				(0x1 << (vfe32_ctrl->outpath.out0.ch1)) |
+				(0x1 << (vfe32_ctrl->outpath.out0.ch2)));
 	}
+
+	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_SECONDARY) {
+		irq_comp_mask |= ((0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8)) |
+				(0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8)));
+	} else if (vfe32_ctrl->outpath.output_mode &
+			   VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+		irq_comp_mask |= ((0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8)) |
+				(0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8)) |
+				(0x1 << (vfe32_ctrl->outpath.out1.ch2 + 8)));
+	}
+
+	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_PRIMARY) {
+		msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
+		msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
+	} else if (vfe32_ctrl->outpath.output_mode &
+				VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+		msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
+		msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
+		msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch2]);
+	}
+
+	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_SECONDARY) {
+		msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
+		msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
+	} else if (vfe32_ctrl->outpath.output_mode &
+				VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+		msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
+		msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
+		msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch2]);
+	}
+
 	msm_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 	vfe32_start_common();
 	msm_camio_bus_scale_cfg(
@@ -823,6 +805,29 @@
 	msm_io_w(1, vfe32_ctrl->vfebase + 0x188);
 	return 0;
 }
+static int vfe32_capture_raw(uint32_t num_frames_capture)
+{
+	uint32_t irq_comp_mask = 0;
+	struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
+
+	vfe32_ctrl->outpath.out0.capture_cnt = num_frames_capture;
+	vfe32_ctrl->vfe_capture_count = num_frames_capture;
+
+	irq_comp_mask	=
+		msm_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+
+	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_PRIMARY) {
+		irq_comp_mask |= (0x1 << (vfe32_ctrl->outpath.out0.ch0));
+		msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
+	}
+
+	msm_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+	msm_camio_bus_scale_cfg(
+		p_sync->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
+	vfe32_start_common();
+	return 0;
+}
 
 static int vfe32_capture(uint32_t num_frames_capture)
 {
@@ -834,51 +839,49 @@
 	}
 	/* capture command is valid for both idle and active state. */
 	vfe32_ctrl->outpath.out1.capture_cnt = num_frames_capture;
-	if (vfe32_ctrl->operation_mode == VFE_MODE_OF_OPERATION_SNAPSHOT) {
+	if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
+		vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) {
 		vfe32_ctrl->outpath.out0.capture_cnt =
-		num_frames_capture;
+			num_frames_capture;
 	}
 
 	vfe32_ctrl->vfe_capture_count = num_frames_capture;
-	irq_comp_mask	=
-		msm_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+	irq_comp_mask	= msm_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 
-	if (vfe32_ctrl->operation_mode == VFE_MODE_OF_OPERATION_SNAPSHOT) {
-		if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_PT) {
+	if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
+		vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) {
+		if (vfe32_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_PRIMARY) {
 			irq_comp_mask |= (0x1 << vfe32_ctrl->outpath.out0.ch0 |
 					0x1 << vfe32_ctrl->outpath.out0.ch1);
 		}
-		if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_S) {
+		if (vfe32_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY) {
 			irq_comp_mask |=
-			(0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8) |
-			0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8));
+				(0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8) |
+				0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8));
 		}
-		if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_PT) {
+		if (vfe32_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_PRIMARY) {
 			msm_io_w(1, vfe32_ctrl->vfebase +
 				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
 			msm_io_w(1, vfe32_ctrl->vfebase +
 				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
 		}
-		if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_S) {
+		if (vfe32_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY) {
 			msm_io_w(1, vfe32_ctrl->vfebase +
 				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
 			msm_io_w(1, vfe32_ctrl->vfebase +
 				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
 		}
-	} else {  /* this is raw snapshot mode. */
-		if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_S) {
-			irq_comp_mask |=
-			(0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8));
-			msm_io_w(1, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
-		}
 	}
 	msm_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 	msm_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 	msm_camio_bus_scale_cfg(
 		p_sync->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
+
 	vfe32_start_common();
-	msm_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 	/* for debug */
 	msm_io_w(1, vfe32_ctrl->vfebase + 0x18C);
 	msm_io_w(1, vfe32_ctrl->vfebase + 0x188);
@@ -889,44 +892,62 @@
 {
 	uint32_t irq_comp_mask = 0;
 	struct msm_sync *sync = vfe_syncdata;
-	/* start command now is only good for continuous mode. */
-	if ((vfe32_ctrl->operation_mode != VFE_MODE_OF_OPERATION_CONTINUOUS) &&
-		(vfe32_ctrl->operation_mode != VFE_MODE_OF_OPERATION_VIDEO))
-		return 0;
+
 	irq_comp_mask	=
 		msm_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 
-	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_PT) {
+	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_PRIMARY) {
 		irq_comp_mask |= (0x1 << vfe32_ctrl->outpath.out0.ch0 |
 			0x1 << vfe32_ctrl->outpath.out0.ch1);
 	} else if (vfe32_ctrl->outpath.output_mode &
-			VFE32_OUTPUT_MODE_P_ALL_CHNLS) {
-		pr_debug("%s Enabling all channels ", __func__);
+			   VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
 		irq_comp_mask |= (0x1 << vfe32_ctrl->outpath.out0.ch0 |
 			0x1 << vfe32_ctrl->outpath.out0.ch1 |
 			0x1 << vfe32_ctrl->outpath.out0.ch2);
 	}
-
-	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_V) {
-		irq_comp_mask |= (0x1 << (vfe32_ctrl->outpath.out2.ch0 + 16)|
-			0x1 << (vfe32_ctrl->outpath.out2.ch1 + 16));
+	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_SECONDARY) {
+		irq_comp_mask |= (0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8) |
+			0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8));
+	} else if (vfe32_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+		irq_comp_mask |= (0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8) |
+			0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8) |
+			0x1 << (vfe32_ctrl->outpath.out1.ch2 + 8));
 	}
-
 	msm_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 
-	if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_PT) {
-		msm_io_w(1, vfe32_ctrl->vfebase +
+	if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+		if (vfe32_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_PRIMARY) {
+			msm_io_w(1, vfe32_ctrl->vfebase +
 			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
-		msm_io_w(1, vfe32_ctrl->vfebase +
+			msm_io_w(1, vfe32_ctrl->vfebase +
 			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
-	} else if (vfe32_ctrl->outpath.output_mode &
-				VFE32_OUTPUT_MODE_P_ALL_CHNLS) {
-		msm_io_w(1, vfe32_ctrl->vfebase +
+		} else if (vfe32_ctrl->outpath.output_mode &
+				VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+			msm_io_w(1, vfe32_ctrl->vfebase +
 			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
-		msm_io_w(1, vfe32_ctrl->vfebase +
+			msm_io_w(1, vfe32_ctrl->vfebase +
 			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
-		msm_io_w(1, vfe32_ctrl->vfebase +
+			msm_io_w(1, vfe32_ctrl->vfebase +
 			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch2]);
+		}
+	} else {
+		if (vfe32_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY) {
+			msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
+			msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
+		} else if (vfe32_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+			msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
+			msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
+			msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch2]);
+		}
 	}
 	msm_camio_bus_scale_cfg(
 		sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
@@ -1107,39 +1128,13 @@
 {
 	struct vfe32_output_ch *ch = NULL;
 
-	switch (vfe32_ctrl->operation_mode) {
-	case VFE_MODE_OF_OPERATION_CONTINUOUS:
-		if (path == VFE_MSG_OUTPUT_P)
-			ch = &vfe32_ctrl->outpath.out0;
-		break;
-	case VFE_MODE_OF_OPERATION_SNAPSHOT:
-		if (path == VFE_MSG_OUTPUT_T)
-			ch = &vfe32_ctrl->outpath.out0;
-		else if (path == VFE_MSG_OUTPUT_S)
-			ch = &vfe32_ctrl->outpath.out1;
-		break;
-	case VFE_MODE_OF_OPERATION_VIDEO:
-		if (path == VFE_MSG_OUTPUT_P)
-			ch = &vfe32_ctrl->outpath.out0;
-		else if (path == VFE_MSG_OUTPUT_V)
-			ch = &vfe32_ctrl->outpath.out2;
-		break;
-	case VFE_MODE_OF_OPERATION_RAW_SNAPSHOT:
-		if (path == VFE_MSG_OUTPUT_S)
-			ch = &vfe32_ctrl->outpath.out0;
-		break;
-	case VFE_MODE_OF_OPERATION_ZSL:
-		if (path == VFE_MSG_OUTPUT_P)
-			ch = &vfe32_ctrl->outpath.out0;
-		else if (path == VFE_MSG_OUTPUT_T)
-			ch = &vfe32_ctrl->outpath.out1;
-		else if (path == VFE_MSG_OUTPUT_S)
-			ch = &vfe32_ctrl->outpath.out2;
-		break;
-	default:
-		pr_err("%s: Unsupported operation mode %d\n", __func__,
-					vfe32_ctrl->operation_mode);
-	}
+	if (path == VFE_MSG_OUTPUT_PRIMARY)
+		ch = &vfe32_ctrl->outpath.out0;
+	else if (path == VFE_MSG_OUTPUT_SECONDARY)
+		ch = &vfe32_ctrl->outpath.out1;
+	else
+		pr_err("%s: Invalid path %d\n", __func__,
+			path);
 
 	BUG_ON(ch == NULL);
 	return ch;
@@ -1170,7 +1165,7 @@
 			outch->pong.ch_paddr[0]);
 
 		if (vfe32_ctrl->operation_mode !=
-			VFE_MODE_OF_OPERATION_RAW_SNAPSHOT) {
+			VFE_OUTPUTS_RAW) {
 			vfe32_put_ch_ping_addr(outch->ch1,
 				outch->ping.ch_paddr[1]);
 			vfe32_put_ch_pong_addr(outch->ch1,
@@ -1242,11 +1237,18 @@
 	case VFE_CMD_START:
 		pr_info("vfe32_proc_general: cmdID = %s\n",
 			vfe32_general_cmd[cmd->id]);
-		rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_START,
-							VFE_MSG_OUTPUT_P);
+		if (vfe32_ctrl->operation_mode ==
+				VFE_OUTPUTS_PREVIEW_AND_VIDEO)
+			/* Configure primary channel */
+			rc = vfe32_configure_pingpong_buffers(
+				VFE_MSG_V32_START, VFE_MSG_OUTPUT_PRIMARY);
+		else
+			/* Configure secondary channel */
+			rc = vfe32_configure_pingpong_buffers(
+				VFE_MSG_V32_START, VFE_MSG_OUTPUT_SECONDARY);
 		if (rc < 0) {
 			pr_err("%s error configuring pingpong buffers"
-				" for preview", __func__);
+				   " for preview", __func__);
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
@@ -1255,6 +1257,23 @@
 	case VFE_CMD_UPDATE:
 		vfe32_update();
 		break;
+	case VFE_CMD_CAPTURE_RAW:
+		pr_info("%s: cmdID = VFE_CMD_CAPTURE_RAW\n", __func__);
+		if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
+				sizeof(uint32_t))) {
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
+		rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE,
+							VFE_MSG_OUTPUT_PRIMARY);
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers"
+				   " for snapshot", __func__);
+			rc = -EINVAL;
+			goto proc_general_done;
+		}
+		rc = vfe32_capture_raw(snapshot_cnt);
+		break;
 	case VFE_CMD_CAPTURE:
 		pr_info("vfe32_proc_general: cmdID = %s\n",
 			vfe32_general_cmd[cmd->id]);
@@ -1263,32 +1282,39 @@
 			rc = -EFAULT;
 			goto proc_general_done;
 		}
+		/* Configure primary channel */
 		rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE,
-							VFE_MSG_OUTPUT_S);
+						  VFE_MSG_OUTPUT_PRIMARY);
 		if (rc < 0) {
 			pr_err("%s error configuring pingpong buffers"
-				   " for snapshot", __func__);
+				   " for primary output", __func__);
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
-		if (vfe32_ctrl->operation_mode !=
-				VFE_MODE_OF_OPERATION_RAW_SNAPSHOT) {
-			rc = vfe32_configure_pingpong_buffers(
-				VFE_MSG_V32_CAPTURE, VFE_MSG_OUTPUT_T);
-			if (rc < 0) {
-				pr_err("%s error configuring pingpong buffers"
-					   " for thumbnail", __func__);
-				rc = -EINVAL;
-				goto proc_general_done;
-			}
+		/* Configure secondary channel */
+		rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE,
+						  VFE_MSG_OUTPUT_SECONDARY);
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers"
+				   " for secondary output", __func__);
+			rc = -EINVAL;
+			goto proc_general_done;
 		}
 		rc = vfe32_capture(snapshot_cnt);
 		break;
 	case VFE_CMD_START_RECORDING:
 		pr_info("vfe32_proc_general: cmdID = %s\n",
 			vfe32_general_cmd[cmd->id]);
-		rc = vfe32_configure_pingpong_buffers(
-			VFE_MSG_V32_START_RECORDING, VFE_MSG_OUTPUT_V);
+		if (vfe32_ctrl->operation_mode ==
+			VFE_OUTPUTS_PREVIEW_AND_VIDEO)
+			rc = vfe32_configure_pingpong_buffers(
+				VFE_MSG_V32_START_RECORDING,
+				VFE_MSG_OUTPUT_SECONDARY);
+		else if (vfe32_ctrl->operation_mode ==
+			VFE_OUTPUTS_VIDEO_AND_PREVIEW)
+			rc = vfe32_configure_pingpong_buffers(
+				VFE_MSG_V32_START_RECORDING,
+				VFE_MSG_OUTPUT_PRIMARY);
 		if (rc < 0) {
 			pr_err("%s error configuring pingpong buffers"
 				" for video", __func__);
@@ -1685,7 +1711,16 @@
 		break;
 
 	case VFE_CMD_LIVESHOT:
-		vfe32_liveshot();
+		/* Configure primary channel */
+		rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE,
+						VFE_MSG_OUTPUT_PRIMARY);
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers"
+				   " for primary output", __func__);
+			rc = -EINVAL;
+			goto proc_general_done;
+		}
+		vfe32_start_liveshot();
 		break;
 
 	case VFE_CMD_LINEARIZATION_CFG:
@@ -2113,15 +2148,11 @@
 
 	case VFE_CMD_ZSL:
 		rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_START,
-							VFE_MSG_OUTPUT_P);
+			VFE_MSG_OUTPUT_PRIMARY);
 		if (rc < 0)
 			goto proc_general_done;
 		rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_START,
-							VFE_MSG_OUTPUT_T);
-		if (rc < 0)
-			goto proc_general_done;
-		rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_START,
-							VFE_MSG_OUTPUT_S);
+			VFE_MSG_OUTPUT_SECONDARY);
 		if (rc < 0)
 			goto proc_general_done;
 
@@ -2425,50 +2456,59 @@
 
 static void vfe32_process_reg_update_irq(void)
 {
-	uint32_t  old_val;
 	unsigned long flags;
-	if (vfe32_ctrl->recording_state == VFE_REC_STATE_START_REQUESTED) {
-		if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_V) {
+
+	if (vfe32_ctrl->recording_state == VFE_STATE_START_REQUESTED) {
+		if (vfe32_ctrl->operation_mode ==
+				VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
 			msm_io_w(1, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out2.ch0]);
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
 			msm_io_w(1, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out2.ch1]);
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
+		} else if (vfe32_ctrl->operation_mode ==
+				VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+			msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
+			msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
 		}
-		vfe32_ctrl->recording_state = VFE_REC_STATE_STARTED;
+		vfe32_ctrl->recording_state = VFE_STATE_STARTED;
 		msm_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 		CDBG("start video triggered .\n");
 	} else if (vfe32_ctrl->recording_state ==
-			VFE_REC_STATE_STOP_REQUESTED) {
-		if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_V) {
-			msm_io_w_mb(0, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out2.ch0]);
-			msm_io_w_mb(0, vfe32_ctrl->vfebase +
-				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out2.ch1]);
+			VFE_STATE_STOP_REQUESTED) {
+		if (vfe32_ctrl->operation_mode ==
+				VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
+			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]);
+		} else if (vfe32_ctrl->operation_mode ==
+				VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+			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]);
 		}
-
-		/*disable rs& cs when stop recording. */
-		old_val = msm_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
-		old_val &= (~RS_CS_ENABLE_MASK);
-		msm_io_w(old_val, vfe32_ctrl->vfebase + VFE_MODULE_CFG);
-
 		CDBG("stop video triggered .\n");
 	}
+
 	if (vfe32_ctrl->start_ack_pending == TRUE) {
 		vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_START_ACK);
 		vfe32_ctrl->start_ack_pending = FALSE;
 	} else {
 		if (vfe32_ctrl->recording_state ==
-			VFE_REC_STATE_STOP_REQUESTED) {
-			vfe32_ctrl->recording_state = VFE_REC_STATE_STOPPED;
+				VFE_STATE_STOP_REQUESTED) {
+			vfe32_ctrl->recording_state = VFE_STATE_STOPPED;
 			/* request a reg update and send STOP_REC_ACK
 			 * when we process the next reg update irq.
 			 */
 			msm_io_w_mb(1,
 			vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 		} else if (vfe32_ctrl->recording_state ==
-			VFE_REC_STATE_STOPPED) {
+					VFE_STATE_STOPPED) {
 			vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_STOP_REC_ACK);
-			vfe32_ctrl->recording_state = VFE_REC_STATE_IDLE;
+			vfe32_ctrl->recording_state = VFE_STATE_IDLE;
 		}
 		spin_lock_irqsave(&vfe32_ctrl->update_ack_lock, flags);
 		if (vfe32_ctrl->update_ack_pending == TRUE) {
@@ -2481,30 +2521,60 @@
 				&vfe32_ctrl->update_ack_lock, flags);
 		}
 	}
-	if (vfe32_ctrl->operation_mode ==
-		VFE_MODE_OF_OPERATION_SNAPSHOT) {  /* in snapshot mode */
+
+	if (vfe32_ctrl->liveshot_state == VFE_STATE_START_REQUESTED) {
+		pr_info("%s enabling liveshot output\n", __func__);
+		if (vfe32_ctrl->outpath.output_mode &
+				VFE32_OUTPUT_MODE_PRIMARY) {
+			msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
+			msm_io_w(1, vfe32_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
+			vfe32_ctrl->liveshot_state = VFE_STATE_STARTED;
+		}
+	}
+
+	if (vfe32_ctrl->liveshot_state == VFE_STATE_STARTED) {
+		vfe32_ctrl->vfe_capture_count--;
+		if (!vfe32_ctrl->vfe_capture_count)
+			vfe32_ctrl->liveshot_state = VFE_STATE_STOP_REQUESTED;
+		msm_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+	} else if (vfe32_ctrl->liveshot_state == VFE_STATE_STOP_REQUESTED) {
+		CDBG("%s: disabling liveshot output\n", __func__);
+		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]);
+			vfe32_ctrl->liveshot_state = VFE_STATE_STOPPED;
+			msm_io_w_mb(1, vfe32_ctrl->vfebase +
+				VFE_REG_UPDATE_CMD);
+		}
+	} else if (vfe32_ctrl->liveshot_state == VFE_STATE_STOPPED) {
+		vfe32_ctrl->liveshot_state = VFE_STATE_IDLE;
+	}
+
+	if ((vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) ||
+		(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) {
-			/* stop the bus output:  write master enable = 0*/
 			if (vfe32_ctrl->outpath.output_mode &
-					VFE32_OUTPUT_MODE_PT) {
+					VFE32_OUTPUT_MODE_PRIMARY) {
 				msm_io_w(0, vfe32_ctrl->vfebase +
-					vfe32_AXI_WM_CFG[vfe32_ctrl->
-						outpath.out0.ch0]);
+				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]);
+				vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
 			}
 			if (vfe32_ctrl->outpath.output_mode &
-					VFE32_OUTPUT_MODE_S) {
+					VFE32_OUTPUT_MODE_SECONDARY) {
 				msm_io_w(0, vfe32_ctrl->vfebase +
-					vfe32_AXI_WM_CFG[vfe32_ctrl->
-							outpath.out1.ch0]);
+				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]);
+				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);
@@ -2512,7 +2582,7 @@
 			/* then do reg_update. */
 			msm_io_w(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 		}
-	} /* if snapshot mode. */
+	} /* in snapshot mode. */
 }
 
 static void vfe32_set_default_reg_values(void)
@@ -2570,9 +2640,8 @@
 
 static void vfe32_process_camif_sof_irq(void)
 {
-	/* in raw snapshot mode */
 	if (vfe32_ctrl->operation_mode ==
-		VFE_MODE_OF_OPERATION_RAW_SNAPSHOT) {
+		VFE_OUTPUTS_RAW) {
 		if (vfe32_ctrl->start_ack_pending) {
 			vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_START_ACK);
 			vfe32_ctrl->start_ack_pending = FALSE;
@@ -2585,10 +2654,8 @@
 			msm_io_w_mb(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
 				vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
 		}
-	} /* if raw snapshot mode. */
+	}
 	vfe32_ctrl->vfeFrameId++;
-	if (vfe32_ctrl->vfeFrameId == 0)
-		vfe32_ctrl->vfeFrameId = 1; /* wrapped back */
 	vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_SOF_ACK);
 	CDBG("camif_sof_irq, frameId = %d\n", vfe32_ctrl->vfeFrameId);
 
@@ -2602,14 +2669,12 @@
 
 static void vfe32_process_error_irq(uint32_t errStatus)
 {
-	uint32_t camifStatus;
-	uint32_t *temp;
+	uint32_t reg_value;
 
 	if (errStatus & VFE32_IMASK_CAMIF_ERROR) {
 		pr_err("vfe32_irq: camif errors\n");
-		temp = (uint32_t *)(vfe32_ctrl->vfebase + VFE_CAMIF_STATUS);
-		camifStatus = msm_io_r(temp);
-		pr_err("camifStatus  = 0x%x\n", camifStatus);
+		reg_value = msm_io_r(vfe32_ctrl->vfebase + VFE_CAMIF_STATUS);
+		pr_err("camifStatus  = 0x%x\n", reg_value);
 		vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_CAMIF_ERROR);
 	}
 
@@ -2631,8 +2696,12 @@
 	if (errStatus & VFE32_IMASK_REALIGN_BUF_CR_OVFL)
 		pr_err("vfe32_irq: realign bug CR overflow\n");
 
-	if (errStatus & VFE32_IMASK_VIOLATION)
+	if (errStatus & VFE32_IMASK_VIOLATION) {
 		pr_err("vfe32_irq: violation interrupt\n");
+		reg_value =
+			msm_io_r(vfe32_ctrl->vfebase + VFE_VIOLATION_STATUS);
+		pr_err("%s: violationStatus  = 0x%x\n", __func__, reg_value);
+	}
 
 	if (errStatus & VFE32_IMASK_IMG_MAST_0_BUS_OVFL)
 		pr_err("vfe32_irq: image master 0 bus overflow\n");
@@ -2703,26 +2772,24 @@
 	uint32_t ch0_paddr, ch1_paddr, ch2_paddr;
 	uint8_t out_bool = 0;
 	struct msm_free_buf *free_buf = NULL;
-	if (vfe32_ctrl->operation_mode ==
-			VFE_MODE_OF_OPERATION_SNAPSHOT)
-		free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
-							VFE_MSG_OUTPUT_T);
-	else
-		free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
-							VFE_MSG_OUTPUT_P);
+
+	free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+		VFE_MSG_OUTPUT_PRIMARY);
+
 	/* we render frames in the following conditions:
 	1. Continuous mode and the free buffer is avaialable.
 	2. In snapshot shot mode, free buffer is not always available.
 	when pending snapshot count is <=1,  then no need to use
 	free buffer.
 	*/
-	out_bool =
-		((vfe32_ctrl->operation_mode ==
-		VFE_MODE_OF_OPERATION_SNAPSHOT ||
-		vfe32_ctrl->operation_mode ==
-		VFE_MODE_OF_OPERATION_RAW_SNAPSHOT) &&
-		(vfe32_ctrl->vfe_capture_count <= 1)) ||
-		free_buf;
+	out_bool = ((vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN ||
+		vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
+		vfe32_ctrl->operation_mode == VFE_OUTPUTS_RAW ||
+		vfe32_ctrl->liveshot_state == VFE_STATE_STARTED ||
+		vfe32_ctrl->liveshot_state == VFE_STATE_STOP_REQUESTED ||
+		vfe32_ctrl->liveshot_state == VFE_STATE_STOPPED) &&
+		(vfe32_ctrl->vfe_capture_count <= 1)) || free_buf;
+
 	if (out_bool) {
 		ping_pong = msm_io_r(vfe32_ctrl->vfebase +
 			VFE_BUS_PING_PONG_STATUS);
@@ -2754,87 +2821,27 @@
 					free_buf->ch_paddr[2]);
 		}
 		if (vfe32_ctrl->operation_mode ==
-			VFE_MODE_OF_OPERATION_SNAPSHOT) {
-			/* will add message for multi-shot. */
+				VFE_OUTPUTS_THUMB_AND_MAIN ||
+			vfe32_ctrl->operation_mode ==
+				VFE_OUTPUTS_MAIN_AND_THUMB ||
+			vfe32_ctrl->operation_mode ==
+				VFE_OUTPUTS_RAW ||
+			vfe32_ctrl->liveshot_state == VFE_STATE_STOPPED)
 			vfe32_ctrl->outpath.out0.capture_cnt--;
-			vfe_send_outmsg(&vfe32_ctrl->subdev,
-				MSG_ID_OUTPUT_T, ch0_paddr,
-				ch1_paddr, ch2_paddr);
-		} else {
-			/* always send message for continous mode. */
-			/* if continuous mode, for display. (preview) */
-			vfe_send_outmsg(&vfe32_ctrl->subdev,
-				MSG_ID_OUTPUT_P, ch0_paddr,
-				ch1_paddr, ch2_paddr);
-		}
+
+		vfe_send_outmsg(&vfe32_ctrl->subdev,
+			MSG_ID_OUTPUT_PRIMARY, ch0_paddr,
+			ch1_paddr, ch2_paddr);
+
+		if (vfe32_ctrl->liveshot_state == VFE_STATE_STOPPED)
+			vfe32_ctrl->liveshot_state = VFE_STATE_IDLE;
+
 	} else {
 		vfe32_ctrl->outpath.out0.frame_drop_cnt++;
 		CDBG("path_irq_0 - no free buffer!\n");
 	}
 }
 
-static void vfe32_process_zsl_frame(void)
-{
-	uint32_t ping_pong;
-	uint32_t ch0_paddr, ch1_paddr, ch2_paddr;
-	struct msm_free_buf *free_buf = NULL;
-
-	ping_pong = msm_io_r(vfe32_ctrl->vfebase +
-			VFE_BUS_PING_PONG_STATUS);
-
-	/* Thumbnail */
-	free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
-						VFE_MSG_OUTPUT_T);
-	if (free_buf) {
-		ch0_paddr = vfe32_get_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out1.ch0);
-		ch1_paddr = vfe32_get_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out1.ch1);
-		ch2_paddr = vfe32_get_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out1.ch2);
-
-		vfe32_put_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out1.ch0,
-			free_buf->ch_paddr[0]);
-		vfe32_put_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out1.ch1,
-			free_buf->ch_paddr[1]);
-		if (free_buf->num_planes > 2)
-			vfe32_put_ch_addr(ping_pong,
-				vfe32_ctrl->outpath.out1.ch2,
-				free_buf->ch_paddr[2]);
-		vfe_send_outmsg(&vfe32_ctrl->subdev,
-			MSG_ID_OUTPUT_T, ch0_paddr,
-			ch1_paddr, ch2_paddr);
-	}
-
-	/* Mainimg */
-	free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
-						VFE_MSG_OUTPUT_S);
-	if (free_buf) {
-		ch0_paddr = vfe32_get_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out2.ch0);
-		ch1_paddr = vfe32_get_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out2.ch1);
-		ch2_paddr = vfe32_get_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out2.ch2);
-		if (free_buf->num_planes > 2)
-			vfe32_put_ch_addr(ping_pong,
-				vfe32_ctrl->outpath.out2.ch2,
-				free_buf->ch_paddr[2]);
-
-		vfe32_put_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out2.ch0,
-			free_buf->ch_paddr[0]);
-		vfe32_put_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out2.ch1,
-			free_buf->ch_paddr[1]);
-		vfe_send_outmsg(&vfe32_ctrl->subdev,
-			MSG_ID_OUTPUT_S, ch0_paddr,
-			ch1_paddr, ch2_paddr);
-	}
-}
-
 static void vfe32_process_output_path_irq_1(void)
 {
 	uint32_t ping_pong;
@@ -2843,26 +2850,17 @@
 	uint8_t out_bool = 0;
 	struct msm_free_buf *free_buf = NULL;
 
-	if (vfe32_ctrl->operation_mode == VFE_MODE_OF_OPERATION_ZSL) {
-		vfe32_process_zsl_frame();
-		return;
-	}
-
 	free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
-						VFE_MSG_OUTPUT_S);
+		VFE_MSG_OUTPUT_SECONDARY);
 
-	/* we render frames in the following conditions:
-	1. Continuous mode and the free buffer is avaialable.
-	2. In snapshot shot mode, free buffer is not always available.
-	-- when pending snapshot count is <=1,  then no need to use
-	free buffer.
-	*/
-	out_bool =
-		((vfe32_ctrl->operation_mode ==
-			VFE_MODE_OF_OPERATION_SNAPSHOT ||
+	out_bool = ((vfe32_ctrl->operation_mode ==
+				VFE_OUTPUTS_THUMB_AND_MAIN ||
 			vfe32_ctrl->operation_mode ==
-			VFE_MODE_OF_OPERATION_RAW_SNAPSHOT) &&
-		 (vfe32_ctrl->vfe_capture_count <= 1)) || free_buf;
+				VFE_OUTPUTS_MAIN_AND_THUMB ||
+			vfe32_ctrl->operation_mode ==
+				VFE_OUTPUTS_RAW) &&
+			(vfe32_ctrl->vfe_capture_count <= 1)) || free_buf;
+
 	if (out_bool) {
 		ping_pong = msm_io_r(vfe32_ctrl->vfebase +
 			VFE_BUS_PING_PONG_STATUS);
@@ -2876,8 +2874,8 @@
 		ch2_paddr = vfe32_get_ch_addr(ping_pong,
 			vfe32_ctrl->outpath.out1.ch2);
 
-		CDBG("snapshot main, ch0 = 0x%x, ch1 = 0x%x, ch2 = 0x%x\n",
-			ch0_paddr, ch1_paddr, ch2_paddr);
+		pr_debug("%s ch0 = 0x%x, ch1 = 0x%x, ch2 = 0x%x\n",
+			__func__, ch0_paddr, ch1_paddr, ch2_paddr);
 		if (free_buf) {
 			/* Y channel */
 			vfe32_put_ch_addr(ping_pong,
@@ -2892,85 +2890,23 @@
 					vfe32_ctrl->outpath.out1.ch2,
 					free_buf->ch_paddr[2]);
 		}
-
 		if (vfe32_ctrl->operation_mode ==
-			VFE_MODE_OF_OPERATION_SNAPSHOT ||
+				VFE_OUTPUTS_THUMB_AND_MAIN ||
 			vfe32_ctrl->operation_mode ==
-			VFE_MODE_OF_OPERATION_RAW_SNAPSHOT) {
+				VFE_OUTPUTS_MAIN_AND_THUMB ||
+			vfe32_ctrl->operation_mode ==
+				VFE_OUTPUTS_RAW)
 			vfe32_ctrl->outpath.out1.capture_cnt--;
-			vfe_send_outmsg(&vfe32_ctrl->subdev,
-				MSG_ID_OUTPUT_S, ch0_paddr,
-				ch1_paddr, ch2_paddr);
-		}
+
+		vfe_send_outmsg(&vfe32_ctrl->subdev,
+			MSG_ID_OUTPUT_SECONDARY, ch0_paddr,
+			ch1_paddr, ch2_paddr);
 	} else {
 		vfe32_ctrl->outpath.out1.frame_drop_cnt++;
 		CDBG("path_irq_1 - no free buffer!\n");
 	}
 }
 
-static void vfe32_process_output_path_irq_2(void)
-{
-	uint32_t ping_pong;
-	uint32_t ch0_paddr, ch1_paddr, ch2_paddr;
-	struct msm_free_buf *free_buf = NULL;
-
-	if (vfe32_ctrl->recording_state == VFE_REC_STATE_STOP_REQUESTED) {
-		vfe32_ctrl->outpath.out2.frame_drop_cnt++;
-		CDBG("%s: path_irq_2 - recording stop requested ", __func__);
-		return;
-	}
-
-	free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
-						VFE_MSG_OUTPUT_V);
-	/* we render frames in the following conditions:
-	1. Continuous mode and the free buffer is avaialable.
-	2. In snapshot shot mode, free buffer is not always available.
-	-- when pending snapshot count is <=1,  then no need to use
-	free buffer.
-	*/
-
-	CDBG("%s: op mode = %d, capture_cnt = %d\n", __func__,
-		 vfe32_ctrl->operation_mode, vfe32_ctrl->vfe_capture_count);
-
-	if (free_buf) {
-		ping_pong = msm_io_r(vfe32_ctrl->vfebase +
-			VFE_BUS_PING_PONG_STATUS);
-
-		/* Y channel */
-		ch0_paddr = vfe32_get_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out2.ch0);
-		/* Chroma channel */
-		ch1_paddr = vfe32_get_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out2.ch1);
-		ch2_paddr = vfe32_get_ch_addr(ping_pong,
-			vfe32_ctrl->outpath.out2.ch2);
-
-		CDBG("video output, ch0 = 0x%x,	ch1 = 0x%x, ch2 = 0x%x\n",
-			ch0_paddr, ch1_paddr, ch2_paddr);
-
-		/* Y channel */
-		vfe32_put_ch_addr(ping_pong,
-		vfe32_ctrl->outpath.out2.ch0,
-		free_buf->ch_paddr[0]);
-		/* Chroma channel */
-		vfe32_put_ch_addr(ping_pong,
-		vfe32_ctrl->outpath.out2.ch1,
-		free_buf->ch_paddr[1]);
-		if (free_buf->num_planes > 2)
-			vfe32_put_ch_addr(ping_pong,
-				vfe32_ctrl->outpath.out2.ch2,
-				free_buf->ch_paddr[2]);
-
-		vfe_send_outmsg(&vfe32_ctrl->subdev,
-			MSG_ID_OUTPUT_V, ch0_paddr,
-			ch1_paddr, ch2_paddr);
-
-	} else {
-		vfe32_ctrl->outpath.out2.frame_drop_cnt++;
-		CDBG("path_irq_2 - no free buffer!\n");
-	}
-}
-
 static void vfe32_process_stats_comb_irq(uint32_t *irqstatus)
 {
 	return;
@@ -3076,6 +3012,8 @@
 	} else{
 		spin_unlock_irqrestore(&vfe32_ctrl->aec_ack_lock, flags);
 		vfe32_ctrl->aecStatsControl.droppedStatsFrameCount++;
+		CDBG("%s: droppedStatsFrameCount = %d", __func__,
+			vfe32_ctrl->aecStatsControl.droppedStatsFrameCount);
 	}
 }
 
@@ -3094,6 +3032,8 @@
 	} else{
 		spin_unlock_irqrestore(&vfe32_ctrl->awb_ack_lock, flags);
 		vfe32_ctrl->awbStatsControl.droppedStatsFrameCount++;
+		CDBG("%s: droppedStatsFrameCount = %d", __func__,
+			vfe32_ctrl->awbStatsControl.droppedStatsFrameCount);
 	}
 }
 
@@ -3112,6 +3052,8 @@
 	} else{
 		spin_unlock_irqrestore(&vfe32_ctrl->af_ack_lock, flags);
 		vfe32_ctrl->afStatsControl.droppedStatsFrameCount++;
+		CDBG("%s: droppedStatsFrameCount = %d", __func__,
+			vfe32_ctrl->afStatsControl.droppedStatsFrameCount);
 	}
 }
 
@@ -3124,8 +3066,11 @@
 
 		vfe_send_stats_msg(vfe32_ctrl->ihistStatsControl.bufToRender,
 						statsIhistNum);
-	} else
+	} else {
 		vfe32_ctrl->ihistStatsControl.droppedStatsFrameCount++;
+		CDBG("%s: droppedStatsFrameCount = %d", __func__,
+			vfe32_ctrl->ihistStatsControl.droppedStatsFrameCount);
+	}
 }
 
 static void vfe32_process_stats_rs_irq(void)
@@ -3137,8 +3082,11 @@
 
 		vfe_send_stats_msg(vfe32_ctrl->rsStatsControl.bufToRender,
 						statsRsNum);
-	} else
+	} else {
 		vfe32_ctrl->rsStatsControl.droppedStatsFrameCount++;
+		CDBG("%s: droppedStatsFrameCount = %d", __func__,
+			vfe32_ctrl->rsStatsControl.droppedStatsFrameCount);
+	}
 }
 
 static void vfe32_process_stats_cs_irq(void)
@@ -3150,8 +3098,11 @@
 
 		vfe_send_stats_msg(vfe32_ctrl->csStatsControl.bufToRender,
 						statsCsNum);
-	} else
+	} else {
 		vfe32_ctrl->csStatsControl.droppedStatsFrameCount++;
+		CDBG("%s: droppedStatsFrameCount = %d", __func__,
+			vfe32_ctrl->csStatsControl.droppedStatsFrameCount);
+	}
 }
 
 static void vfe32_do_tasklet(unsigned long data)
@@ -3215,17 +3166,14 @@
 				CDBG("Image composite done 1 irq occured.\n");
 				vfe32_process_output_path_irq_1();
 			}
-			if (qcmd->vfeInterruptStatus0 &
-				VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE2_MASK) {
-				CDBG("Image composite done 2 irq occured.\n");
-				vfe32_process_output_path_irq_2();
-			}
 			/* in snapshot mode if done then send
 			snapshot done message */
 			if (vfe32_ctrl->operation_mode ==
-				VFE_MODE_OF_OPERATION_SNAPSHOT ||
+					VFE_OUTPUTS_THUMB_AND_MAIN ||
 				vfe32_ctrl->operation_mode ==
-				VFE_MODE_OF_OPERATION_RAW_SNAPSHOT) {
+					VFE_OUTPUTS_MAIN_AND_THUMB ||
+				vfe32_ctrl->operation_mode ==
+					VFE_OUTPUTS_RAW) {
 				if ((vfe32_ctrl->outpath.out0.capture_cnt == 0)
 						&& (vfe32_ctrl->outpath.out1.
 						capture_cnt == 0)) {
@@ -3446,7 +3394,12 @@
 		case CMD_STATS_CS_ENABLE:
 			rc = vfe_stats_cs_buf_init(scfg);
 			break;
+		default:
+			pr_err("%s Unsupported cmd type %d",
+				__func__, cmd->cmd_type);
+			break;
 		}
+		goto vfe32_config_done;
 	}
 	switch (cmd->cmd_type) {
 	case CMD_GENERAL:
@@ -3496,7 +3449,7 @@
 		vfe32_stats_cs_ack(sack);
 		break;
 
-	case CMD_AXI_CFG_PREVIEW: {
+	case CMD_AXI_CFG_PRIM: {
 		uint32_t *axio = NULL;
 		axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
 				GFP_ATOMIC);
@@ -3511,12 +3464,11 @@
 			rc = -EFAULT;
 			break;
 		}
-		vfe32_config_axi(OUTPUT_2, axio);
+		vfe32_config_axi(OUTPUT_PRIM, axio);
 		kfree(axio);
 	}
 		break;
-
-	case CMD_RAW_PICT_AXI_CFG: {
+	case CMD_AXI_CFG_PRIM_ALL_CHNLS: {
 		uint32_t *axio = NULL;
 		axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
 				GFP_ATOMIC);
@@ -3531,12 +3483,11 @@
 			rc = -EFAULT;
 			break;
 		}
-		vfe32_config_axi(CAMIF_TO_AXI_VIA_OUTPUT_2, axio);
+		vfe32_config_axi(OUTPUT_PRIM_ALL_CHNLS, axio);
 		kfree(axio);
 	}
 		break;
-
-	case CMD_AXI_CFG_SNAP: {
+	case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC: {
 		uint32_t *axio = NULL;
 		axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
 				GFP_ATOMIC);
@@ -3551,14 +3502,12 @@
 			rc = -EFAULT;
 			break;
 		}
-		vfe32_config_axi(OUTPUT_1_AND_2, axio);
+		vfe32_config_axi(OUTPUT_PRIM|OUTPUT_SEC, axio);
 		kfree(axio);
 	}
 		break;
-
-	case CMD_AXI_CFG_ZSL: {
+	case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC_ALL_CHNLS: {
 		uint32_t *axio = NULL;
-		CDBG("%s, CMD_AXI_CFG_ZSL\n", __func__);
 		axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
 				GFP_ATOMIC);
 		if (!axio) {
@@ -3572,14 +3521,12 @@
 			rc = -EFAULT;
 			break;
 		}
-		vfe32_config_axi(OUTPUT_1_2_AND_3, axio);
+		vfe32_config_axi(OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS, axio);
 		kfree(axio);
 	}
 		break;
-
-	case CMD_AXI_CFG_ZSL_ALL_CHNLS: {
+	case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC: {
 		uint32_t *axio = NULL;
-		CDBG("%s, CMD_AXI_CFG_ZSL\n", __func__);
 		axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
 				GFP_ATOMIC);
 		if (!axio) {
@@ -3593,51 +3540,17 @@
 			rc = -EFAULT;
 			break;
 		}
-		vfe32_config_axi(OUTPUT_ZSL_ALL_CHNLS, axio);
+		vfe32_config_axi(OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC, axio);
 		kfree(axio);
 	}
 		break;
-
-	case CMD_AXI_CFG_VIDEO: {
-		uint32_t *axio = NULL;
-		axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
-				GFP_ATOMIC);
-		if (!axio) {
-			rc = -ENOMEM;
-			break;
-		}
-
-		if (copy_from_user(axio, (void __user *)(vfecmd.value),
-				vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
-			kfree(axio);
-			rc = -EFAULT;
-			break;
-		}
-		vfe32_config_axi(OUTPUT_1_AND_3, axio);
-		kfree(axio);
-	}
-		break;
-
-	case CMD_AXI_CFG_VIDEO_ALL_CHNLS: {
-		uint32_t *axio = NULL;
-		axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
-				GFP_ATOMIC);
-		if (!axio) {
-			rc = -ENOMEM;
-			break;
-		}
-
-		if (copy_from_user(axio, (void __user *)(vfecmd.value),
-				vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
-			kfree(axio);
-			rc = -EFAULT;
-			break;
-		}
-		vfe32_config_axi(OUTPUT_ALL_CHNLS, axio);
-		kfree(axio);
-	}
+	case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC_ALL_CHNLS:
+		pr_err("%s Invalid/Unsupported AXI configuration %x",
+			__func__, cmd->cmd_type);
 		break;
 	default:
+		pr_err("%s Unsupported AXI configuration %x ", __func__,
+			cmd->cmd_type);
 		break;
 	}
 vfe32_config_done:
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index ff42c28..1adfffd 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.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,8 @@
 #ifndef __MSM_VFE32_H__
 #define __MSM_VFE32_H__
 
+#include <linux/bitops.h>
+
 #define TRUE  1
 #define FALSE 0
 
@@ -191,17 +193,12 @@
 	ROLLOFF_RAM1_BANK1       = 0x15,
 };
 
-enum  VFE_STATE {
+enum vfe_output_state {
 	VFE_STATE_IDLE,
-	VFE_STATE_ACTIVE
-};
-
-enum  vfe_recording_state {
-	VFE_REC_STATE_IDLE,
-	VFE_REC_STATE_START_REQUESTED,
-	VFE_REC_STATE_STARTED,
-	VFE_REC_STATE_STOP_REQUESTED,
-	VFE_REC_STATE_STOPPED,
+	VFE_STATE_START_REQUESTED,
+	VFE_STATE_STARTED,
+	VFE_STATE_STOP_REQUESTED,
+	VFE_STATE_STOPPED,
 };
 
 #define V32_CAMIF_OFF             0x000001E4
@@ -870,18 +867,23 @@
 #define VFE_DMI_CFG                     0x00000598
 #define VFE_DMI_ADDR                    0x0000059C
 #define VFE_DMI_DATA_LO                 0x000005A4
-#define VFE_BUS_IO_FORMAT_CFG		0x000006F8
+#define VFE_BUS_IO_FORMAT_CFG           0x000006F8
 #define VFE_PIXEL_IF_CFG                0x000006FC
+#define VFE_VIOLATION_STATUS            0x000007B4
 
 #define VFE33_DMI_DATA_HI               0x000005A0
 #define VFE33_DMI_DATA_LO               0x000005A4
 
-#define VFE32_OUTPUT_MODE_PT (0x1 << 0)
-#define VFE32_OUTPUT_MODE_S (0x1 << 1)
-#define VFE32_OUTPUT_MODE_V (0x1 << 2)
-#define VFE32_OUTPUT_MODE_P (0x1 << 3)
-#define VFE32_OUTPUT_MODE_T (0x1 << 4)
-#define VFE32_OUTPUT_MODE_P_ALL_CHNLS (0x1 << 5)
+#define VFE32_OUTPUT_MODE_PT			BIT(0)
+#define VFE32_OUTPUT_MODE_S			BIT(1)
+#define VFE32_OUTPUT_MODE_V			BIT(2)
+#define VFE32_OUTPUT_MODE_P			BIT(3)
+#define VFE32_OUTPUT_MODE_T			BIT(4)
+#define VFE32_OUTPUT_MODE_P_ALL_CHNLS		BIT(5)
+#define VFE32_OUTPUT_MODE_PRIMARY		BIT(6)
+#define VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS	BIT(7)
+#define VFE32_OUTPUT_MODE_SECONDARY		BIT(8)
+#define VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS	BIT(9)
 
 struct vfe_stats_control {
 	uint8_t  ackPending;
@@ -912,11 +914,12 @@
 	int8_t stop_ack_pending;
 	int8_t reset_ack_pending;
 	int8_t update_ack_pending;
-	enum vfe_recording_state recording_state;
+	enum vfe_output_state recording_state;
 	int8_t update_linear;
 	int8_t update_rolloff;
 	int8_t update_la;
 	int8_t update_gamma;
+	enum vfe_output_state liveshot_state;
 
 	spinlock_t  tasklet_lock;
 	struct list_head tasklet_q;
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index fcf2495..7186e58 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -156,9 +156,7 @@
 	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_IMAGE_SIZE_OFFSET);
 	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_YSTRIDE1_OFFSET);
 	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_SIZE_OFFSET);
-	vpe_ctrl->in_h_w = *p;
 	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_XY_OFFSET);
-	CDBG("%s: in_h_w=0x%x", __func__, vpe_ctrl->in_h_w);
 }
 
 void vpe_output_plane_config(uint32_t *p)
@@ -168,7 +166,6 @@
 	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_OUT_YSTRIDE1_OFFSET);
 	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_OUT_SIZE_OFFSET);
 	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_OUT_XY_OFFSET);
-	vpe_ctrl->pcbcr_dis_offset = *(++p);
 }
 
 static int vpe_operation_config(uint32_t *p)
@@ -187,9 +184,8 @@
 		vpe_ctrl->out_w = w;
 		vpe_ctrl->out_h = h;
 	}
-	vpe_ctrl->dis_en = *p;
-	CDBG("%s: out_w=%d, out_h=%d, dis_en=%d",
-		__func__, vpe_ctrl->out_w, vpe_ctrl->out_h, vpe_ctrl->dis_en);
+	CDBG("%s: out_w=%d, out_h=%d", __func__, vpe_ctrl->out_w,
+		vpe_ctrl->out_h);
 	return 0;
 }
 
@@ -202,7 +198,6 @@
 	uint32_t out_ROI_width, out_ROI_height;
 	uint32_t src_ROI_width, src_ROI_height;
 
-	uint32_t rc = 0;  /* default to no zoom. */
 	/*
 	* phase_step_x, phase_step_y, phase_init_x and phase_init_y
 	* are represented in fixed-point, unsigned 3.29 format
@@ -216,26 +211,7 @@
 	uint32_t yscale_filter_sel, xscale_filter_sel;
 	uint32_t scale_unit_sel_x, scale_unit_sel_y;
 	uint64_t numerator, denominator;
-	if ((pcrop->src_w >= pcrop->dst_w) &&
-		(pcrop->src_h >= pcrop->dst_h)) {
-		CDBG(" =======VPE no zoom needed.\n");
 
-		temp = msm_io_r(vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET)
-		& 0xfffffffc;
-		msm_io_w(temp, vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET);
-
-
-		msm_io_w(0, vpe_ctrl->vpebase + VPE_SRC_XY_OFFSET);
-
-		CDBG("vpe_ctrl->in_h_w = %d\n", vpe_ctrl->in_h_w);
-		msm_io_w(vpe_ctrl->in_h_w , vpe_ctrl->vpebase +
-				VPE_SRC_SIZE_OFFSET);
-
-		return rc;
-	}
-	/* If fall through then scaler is needed.*/
-
-	CDBG("========VPE zoom needed.\n");
 	/* assumption is both direction need zoom. this can be
 	improved. */
 	temp =
@@ -414,18 +390,6 @@
 	return 1;
 }
 
-static inline void vpe_get_zoom_dis_xy(
-		struct dis_offset_type *dis_offset,
-		struct msm_pp_crop *pcrop,
-		int32_t  *zoom_dis_x,
-		int32_t *zoom_dis_y)
-{
-	*zoom_dis_x = dis_offset->dis_offset_x *
-	pcrop->src_w / pcrop->dst_w;
-	*zoom_dis_y = dis_offset->dis_offset_y *
-	pcrop->src_h / pcrop->dst_h;
-}
-
 int msm_vpe_is_busy(void)
 {
 	int busy = 0;
@@ -596,7 +560,10 @@
 	spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
 	vpe_ctrl->pp_frame_info = pp_frame_info;
 	msm_vpe_cfg_update(
-			&vpe_ctrl->pp_frame_info->pp_frame_cmd.crop);
+		&vpe_ctrl->pp_frame_info->pp_frame_cmd.crop);
+	CDBG("%s Sending frame idx %d id %d to VPE ", __func__,
+		pp_frame_info->src_frame.buf_idx,
+		pp_frame_info->src_frame.frame_id);
 	rc = msm_send_frame_to_vpe();
 	return rc;
 }
@@ -644,7 +611,6 @@
 		break;
 	case VPE_CMD_INPUT_PLANE_UPDATE:
 	case VPE_CMD_FLUSH:
-	case VPE_CMD_DIS_OFFSET_CFG:
 	default:
 		break;
 	}
diff --git a/drivers/media/video/msm/msm_vpe.h b/drivers/media/video/msm/msm_vpe.h
index 6d84f4e..46c9d2f 100644
--- a/drivers/media/video/msm/msm_vpe.h
+++ b/drivers/media/video/msm/msm_vpe.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
@@ -91,12 +91,6 @@
 	VPE_STATE_ACTIVE,
 };
 
-struct dis_offset_type {
-	int32_t dis_offset_x;
-	int32_t dis_offset_y;
-	uint32_t frame_id;
-};
-
 struct vpe_ctrl_type {
 	spinlock_t        lock;
 	uint32_t          irq_status;
@@ -105,14 +99,9 @@
 	void              *extdata;
 	uint32_t          extlen;
 	struct msm_vpe_callback *resp;
-	uint32_t          in_h_w;
 	uint32_t          out_h;  /* this is BEFORE rotation. */
 	uint32_t          out_w;  /* this is BEFORE rotation. */
-	uint32_t          dis_en;
 	struct timespec   ts;
-	struct dis_offset_type   dis_offset;
-	uint32_t          pcbcr_before_dis;
-	uint32_t          pcbcr_dis_offset;
 	int               output_type;
 	int               frame_pack;
 	uint8_t           pad_2k_bool;
@@ -149,7 +138,7 @@
 
 struct vpe_input_plane_update_type {
 	struct vpe_src_size_packed             src_roi_size;
-	/* DIS updates this set. */
+	/* crop updates this set. */
 	struct vpe_src_xy_packed               src_roi_offset;
 	/* input address*/
 	uint8_t                         *src_p0_addr;
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index abba5d4..00a688c 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -403,11 +403,12 @@
 	vcd_property_hdr.prop_id = VCD_I_CODEC;
 	vcd_property_hdr.sz = sizeof(struct vcd_property_codec);
 	vcd_property_codec.codec = VCD_CODEC_H264;
+
 	switch (codec) {
-	case V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC:
+	case V4L2_PIX_FMT_H264:
 		vcd_property_codec.codec = VCD_CODEC_H264;
 		break;
-	case V4L2_MPEG_VIDEO_ENCODING_MPEG_1:
+	case V4L2_PIX_FMT_MPEG4:
 		vcd_property_codec.codec = VCD_CODEC_MPEG4;
 		break;
 	default:
@@ -418,39 +419,6 @@
 				&vcd_property_hdr, &vcd_property_codec);
 }
 
-static long venc_get_codec(struct video_client_ctx *client_ctx, __s32 *codec)
-{
-	struct vcd_property_codec vcd_property_codec;
-	struct vcd_property_hdr vcd_property_hdr;
-	int rc = 0;
-
-	vcd_property_hdr.prop_id = VCD_I_CODEC;
-	vcd_property_hdr.sz = sizeof(struct vcd_property_codec);
-
-	rc = vcd_get_property(client_ctx->vcd_handle,
-				&vcd_property_hdr, &vcd_property_codec);
-
-	if (rc < 0) {
-		WFD_MSG_ERR("Failed to get codec property");
-		return rc;
-	}
-
-	switch (vcd_property_codec.codec) {
-	case VCD_CODEC_H264:
-		*codec = V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC;
-		break;
-	case VCD_CODEC_MPEG4:
-		*codec = V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
-		break;
-	default:
-		WFD_MSG_ERR("Unrecognized codec");
-		return -EINVAL;
-		break;
-	}
-
-	return rc;
-}
-
 static long venc_set_codec_level(struct video_client_ctx *client_ctx,
 					__s32 codec, __s32 level)
 {
@@ -939,6 +907,12 @@
 		WFD_MSG_ERR("Invalid parameters\n");
 		return -EINVAL;
 	}
+	rc = venc_set_codec(client_ctx, fmt->fmt.pix.pixelformat);
+	if (rc) {
+		WFD_MSG_ERR("Failed to set codec, rc = %d\n", rc);
+		goto err;
+	}
+
 	rc = venc_set_frame_size(client_ctx, fmt->fmt.pix.height,
 				fmt->fmt.pix.width);
 	if (rc) {
@@ -1233,9 +1207,6 @@
 	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
 		rc = venc_set_bitrate_mode(client_ctx, ctrl->value);
 		break;
-	case V4L2_CID_MPEG_VIDEO_ENCODING:
-		rc = venc_set_codec(client_ctx, ctrl->value);
-		break;
 	case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
 		rc = venc_set_h264_intra_period(client_ctx, ctrl->value);
 		break;
@@ -1270,9 +1241,6 @@
 	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
 		rc = venc_get_bitrate_mode(client_ctx, &ctrl->value);
 		break;
-	case V4L2_CID_MPEG_VIDEO_ENCODING:
-		rc = venc_get_codec(client_ctx, &ctrl->value);
-		break;
 	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
 		rc = venc_get_codec_level(client_ctx, ctrl->id, &ctrl->value);
 		break;
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
index 27a8888..93dd367 100644
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -490,9 +490,9 @@
 		return -EINVAL;
 	}
 	if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-		fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_NV12) {
+		fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_H264) {
 		WFD_MSG_ERR("Only V4L2_BUF_TYPE_VIDEO_CAPTURE and "
-				"V4L2_PIX_FMT_NV12 are supported\n");
+				"V4L2_PIX_FMT_H264 are supported\n");
 		return -EINVAL;
 	}
 	rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl, SET_FORMAT,
@@ -707,7 +707,7 @@
 	fmt.fmt.pix.height = inst->height = DEFAULT_WFD_HEIGHT;
 	fmt.fmt.pix.width = inst->width = DEFAULT_WFD_WIDTH;
 	fmt.fmt.pix.pixelformat = inst->pixelformat
-			= V4L2_PIX_FMT_NV12;
+			= V4L2_PIX_FMT_H264;
 	spin_unlock_irqrestore(&inst->inst_lock, flags);
 	wfdioc_s_fmt(filp, filp->private_data, &fmt);
 	return 0;
diff --git a/drivers/media/video/videobuf2-msm-mem.c b/drivers/media/video/videobuf2-msm-mem.c
index 37b935b..c12bed3 100644
--- a/drivers/media/video/videobuf2-msm-mem.c
+++ b/drivers/media/video/videobuf2-msm-mem.c
@@ -239,6 +239,7 @@
 	}
 	paddr = mem->msm_buffer->iova[0];
 	mem->mapped_phyaddr = paddr + addr_offset;
+	mem->addr_offset = addr_offset;
 	return rc;
 }
 EXPORT_SYMBOL_GPL(videobuf2_pmem_contig_user_get);
diff --git a/drivers/mfd/pm8018-core.c b/drivers/mfd/pm8018-core.c
index fc85a42..5c4b705 100644
--- a/drivers/mfd/pm8018-core.c
+++ b/drivers/mfd/pm8018-core.c
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -253,8 +253,8 @@
 	SMPS("8018_s4", "8018_s4_pc", 0x1E8, 0x1ED, 0x00C, 0x1EA, SMPS_1500),
 	SMPS("8018_s5", "8018_s5_pc", 0x1F0, 0x1F5, 0x00D, 0x1F2, SMPS_1500),
 
-	/* name		     pc_name	     ctrl */
-	VS("8018_lvs1",      "8018_lvs1_pc", 0x060),
+	/* name		     pc_name	     ctrl   test */
+	VS("8018_lvs1",      "8018_lvs1_pc", 0x060, 0x061),
 };
 
 #define MAX_NAME_COMPARISON_LEN 32
diff --git a/drivers/mfd/pm8038-core.c b/drivers/mfd/pm8038-core.c
index 8a9d289..ceb4210 100644
--- a/drivers/mfd/pm8038-core.c
+++ b/drivers/mfd/pm8038-core.c
@@ -313,9 +313,9 @@
 	FTSMPS("8038_s5", 0x025, 0x02E, 0x026, 0x032, SMPS_2000),
 	FTSMPS("8038_s6", 0x036, 0x03F, 0x037, 0x043, SMPS_2000),
 
-	/* name		       pc_name	       ctrl */
-	VS("8038_lvs1",        "8038_lvs1_pc", 0x060),
-	VS("8038_lvs2",        "8038_lvs2_pc", 0x062),
+	/* name		       pc_name	       ctrl   test */
+	VS("8038_lvs1",        "8038_lvs1_pc", 0x060, 0x061),
+	VS("8038_lvs2",        "8038_lvs2_pc", 0x062, 0x063),
 };
 
 #define MAX_NAME_COMPARISON_LEN 32
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index 2c99a7f..e4d8bd5 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -412,16 +412,16 @@
 	SMPS("8921_s7", "8921_s7_pc", 0x1F0, 0x1F5, 0x012, 0x1F2, SMPS_1500),
 	SMPS("8921_s8", "8921_s8_pc", 0x1F8, 0x1FD, 0x013, 0x1FA, SMPS_1500),
 
-	/* name		       pc_name	       ctrl */
-	VS("8921_lvs1",        "8921_lvs1_pc", 0x060),
-	VS300("8921_lvs2",		       0x062),
-	VS("8921_lvs3",        "8921_lvs3_pc", 0x064),
-	VS("8921_lvs4",        "8921_lvs4_pc", 0x066),
-	VS("8921_lvs5",        "8921_lvs5_pc", 0x068),
-	VS("8921_lvs6",        "8921_lvs6_pc", 0x06A),
-	VS("8921_lvs7",        "8921_lvs7_pc", 0x06C),
-	VS300("8921_usb_otg",		       0x06E),
-	VS300("8921_hdmi_mvs",		       0x070),
+	/* name		       pc_name	       ctrl   test */
+	VS("8921_lvs1",        "8921_lvs1_pc", 0x060, 0x061),
+	VS300("8921_lvs2",		       0x062, 0x063),
+	VS("8921_lvs3",        "8921_lvs3_pc", 0x064, 0x065),
+	VS("8921_lvs4",        "8921_lvs4_pc", 0x066, 0x067),
+	VS("8921_lvs5",        "8921_lvs5_pc", 0x068, 0x069),
+	VS("8921_lvs6",        "8921_lvs6_pc", 0x06A, 0x06B),
+	VS("8921_lvs7",        "8921_lvs7_pc", 0x06C, 0x06D),
+	VS300("8921_usb_otg",		       0x06E, 0x06F),
+	VS300("8921_hdmi_mvs",		       0x070, 0x071),
 
 	/*  name	ctrl */
 	NCP("8921_ncp", 0x090),
diff --git a/drivers/mfd/pm8xxx-misc.c b/drivers/mfd/pm8xxx-misc.c
index 283f985..eb0048a 100644
--- a/drivers/mfd/pm8xxx-misc.c
+++ b/drivers/mfd/pm8xxx-misc.c
@@ -132,6 +132,9 @@
 #define UART_PATH_SEL_MASK			0x60
 #define UART_PATH_SEL_SHIFT			0x5
 
+#define USB_ID_PU_EN_MASK			0x10	/* PM8921 family only */
+#define USB_ID_PU_EN_SHIFT			4
+
 /* Shutdown/restart delays to allow for LDO 7/dVdd regulator load settling. */
 #define PM8901_DELAY_AFTER_REG_DISABLE_MS	4
 #define PM8901_DELAY_BEFORE_SHUTDOWN_MS		8
@@ -944,6 +947,48 @@
 }
 EXPORT_SYMBOL(pm8xxx_uart_gpio_mux_ctrl);
 
+/**
+ * pm8xxx_usb_id_pullup - Control a pullup for USB ID
+ *
+ * @enable: enable (1) or disable (0) the pullup
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_usb_id_pullup(int enable)
+{
+	struct pm8xxx_misc_chip *chip;
+	unsigned long flags;
+	int rc = -ENXIO;
+
+	spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+	/* Loop over all attached PMICs and call specific functions for them. */
+	list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+		switch (chip->version) {
+		case PM8XXX_VERSION_8921:
+		case PM8XXX_VERSION_8922:
+		case PM8XXX_VERSION_8917:
+		case PM8XXX_VERSION_8038:
+			rc = pm8xxx_misc_masked_write(chip,
+				REG_PM8XXX_GPIO_MUX_CTRL, USB_ID_PU_EN_MASK,
+				enable << USB_ID_PU_EN_SHIFT);
+
+			if (rc)
+				pr_err("Fail: reg=%x, rc=%d\n",
+				       REG_PM8XXX_GPIO_MUX_CTRL, rc);
+			break;
+		default:
+			/* Functionality not supported */
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+	return rc;
+}
+EXPORT_SYMBOL(pm8xxx_usb_id_pullup);
+
 static int __pm8901_preload_dVdd(struct pm8xxx_misc_chip *chip)
 {
 	int rc;
diff --git a/drivers/mfd/pm8xxx-pwm.c b/drivers/mfd/pm8xxx-pwm.c
index b5e2092..05f02c4 100644
--- a/drivers/mfd/pm8xxx-pwm.c
+++ b/drivers/mfd/pm8xxx-pwm.c
@@ -27,8 +27,14 @@
 
 #define PM8XXX_PWM_CHANNELS		3
 
-#define PM8XXX_LPG_BANKS                8
-#define PM8XXX_LPG_PWM_CHANNELS         PM8XXX_LPG_BANKS
+/*
+ * For the lack of better term to distinguish functional
+ * differences, hereby, LPG version 0 (V0, v0) denotes
+ * PM8058/8921, and version 1 (V1, v1) denotes
+ * PM8922/8038.
+ */
+#define PM8XXX_LPG_V0_PWM_CHANNELS	8
+#define PM8XXX_LPG_V1_PWM_CHANNELS	6
 #define PM8XXX_LPG_CTL_REGS		7
 
 /* PM8XXX PWM */
@@ -149,12 +155,10 @@
 #define NSEC_32768HZ	(NSEC_PER_SEC / 32768)
 #define NSEC_19P2MHZ	(NSEC_PER_SEC / 19200000)
 
-#define CLK_PERIOD_MIN	NSEC_19P2MHZ
-#define CLK_PERIOD_MAX	NSEC_1024HZ
-
 #define NUM_LPG_PRE_DIVIDE	4
 #define NUM_PWM_PRE_DIVIDE	2
 
+#define PRE_DIVIDE_1		1	/* v1 */
 #define PRE_DIVIDE_2		2
 #define PRE_DIVIDE_3		3
 #define PRE_DIVIDE_5		5
@@ -1339,11 +1343,19 @@
 
 	if (version == PM8XXX_VERSION_8921 ||
 			version == PM8XXX_VERSION_8058 ||
-			version == PM8XXX_VERSION_8922) {
+			version == PM8XXX_VERSION_8922 ||
+			version == PM8XXX_VERSION_8038) {
 		chip->is_lpg_supported = 1;
 	}
 	if (chip->is_lpg_supported) {
-		chip->pwm_channels = PM8XXX_LPG_PWM_CHANNELS;
+		if (version == PM8XXX_VERSION_8922 ||
+				version == PM8XXX_VERSION_8038) {
+			for (i = 0; i < NUM_CLOCKS; i++)
+				pt_t[0][i] /= PRE_DIVIDE_2;
+			chip->pwm_channels = PM8XXX_LPG_V1_PWM_CHANNELS;
+		} else {
+			chip->pwm_channels = PM8XXX_LPG_V0_PWM_CHANNELS;
+		}
 		chip->pwm_total_pre_divs = NUM_LPG_PRE_DIVIDE;
 	} else {
 		chip->pwm_channels = PM8XXX_PWM_CHANNELS;
diff --git a/drivers/mfd/wcd9310-core.c b/drivers/mfd/wcd9310-core.c
index 4b81e99..84eadef 100644
--- a/drivers/mfd/wcd9310-core.c
+++ b/drivers/mfd/wcd9310-core.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
@@ -388,6 +388,10 @@
 		goto err_irq;
 	}
 
+	tabla->version = tabla_reg_read(tabla, TABLA_A_CHIP_VERSION) & 0x1F;
+	pr_info("%s : Tabla version %u initialized\n",
+		__func__, tabla->version);
+
 	return ret;
 err_irq:
 	tabla_irq_exit(tabla);
@@ -918,7 +922,6 @@
 	}
 #endif
 
-
 	return ret;
 
 err_slim_add:
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 9a99cf3..8f42e5b 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -2817,10 +2817,9 @@
 						u8 phase)
 {
 	int rc = 0;
-	u8 grey_coded_phase_table[] = {0x0, 0x1, 0x3, 0x2, 0x6,
-					0x7, 0x5, 0x4, 0x8, 0x9,
-					0xB, 0xA, 0xE, 0xF, 0xD,
-					0xC};
+	u8 grey_coded_phase_table[] = {0x0, 0x1, 0x3, 0x2, 0x6, 0x7, 0x5, 0x4,
+					0xC, 0xD, 0xF, 0xE, 0xA, 0xB, 0x9,
+					0x8};
 	unsigned long flags;
 	u32 config;
 
diff --git a/drivers/net/msm_rmnet_bam.c b/drivers/net/msm_rmnet_bam.c
index f11fb60..401b63c 100644
--- a/drivers/net/msm_rmnet_bam.c
+++ b/drivers/net/msm_rmnet_bam.c
@@ -77,17 +77,14 @@
 	unsigned long wakeups_rcv;
 	unsigned long timeout_us;
 #endif
-	struct sk_buff *skb;
+	struct sk_buff *waiting_for_ul_skb;
 	spinlock_t lock;
 	struct tasklet_struct tsklt;
 	u32 operation_mode; /* IOCTL specified mode (protocol, QoS header) */
 	uint8_t device_up;
-	uint8_t waiting_for_ul;
 	uint8_t in_reset;
 };
 
-static uint8_t ul_is_connected;
-
 #ifdef CONFIG_MSM_RMNET_DEBUG
 static unsigned long timeout_us;
 
@@ -349,6 +346,7 @@
 static void bam_notify(void *dev, int event, unsigned long data)
 {
 	struct rmnet_private *p = netdev_priv(dev);
+	unsigned long flags;
 
 	switch (event) {
 	case BAM_DMUX_RECEIVE:
@@ -358,14 +356,26 @@
 		bam_write_done(dev, (struct sk_buff *)(data));
 		break;
 	case BAM_DMUX_UL_CONNECTED:
-		ul_is_connected = 1;
-		if (p->waiting_for_ul) {
+		spin_lock_irqsave(&p->lock, flags);
+		if (p->waiting_for_ul_skb != NULL) {
+			struct sk_buff *skb;
+			int ret;
+
+			skb = p->waiting_for_ul_skb;
+			p->waiting_for_ul_skb = NULL;
+			spin_unlock_irqrestore(&p->lock, flags);
+			ret = _rmnet_xmit(skb, dev);
+			if (ret) {
+				pr_err("%s: error %d dropping delayed TX SKB %p\n",
+						__func__, ret, skb);
+				dev_kfree_skb_any(skb);
+			}
 			netif_wake_queue(dev);
-			p->waiting_for_ul = 0;
+		} else {
+			spin_unlock_irqrestore(&p->lock, flags);
 		}
 		break;
 	case BAM_DMUX_UL_DISCONNECTED:
-		ul_is_connected = 0;
 		break;
 	}
 }
@@ -446,6 +456,8 @@
 static int rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct rmnet_private *p = netdev_priv(dev);
+	unsigned long flags;
+	int awake;
 	int ret = 0;
 
 	if (netif_queue_stopped(dev)) {
@@ -454,15 +466,23 @@
 		return 0;
 	}
 
-	if (!ul_is_connected) {
+	spin_lock_irqsave(&p->lock, flags);
+	awake = msm_bam_dmux_ul_power_vote();
+	if (!awake) {
+		/* send SKB once wakeup is complete */
 		netif_stop_queue(dev);
-		p->waiting_for_ul = 1;
-		msm_bam_dmux_kickoff_ul_wakeup();
-		return NETDEV_TX_BUSY;
+		p->waiting_for_ul_skb = skb;
+		spin_unlock_irqrestore(&p->lock, flags);
+		ret = 0;
+		goto exit;
 	}
+	spin_unlock_irqrestore(&p->lock, flags);
+
 	ret = _rmnet_xmit(skb, dev);
-	if (ret == -EPERM)
-		return NETDEV_TX_BUSY;
+	if (ret == -EPERM) {
+		ret = NETDEV_TX_BUSY;
+		goto exit;
+	}
 
 	/*
 	 * detected SSR a bit early.  shut some things down now, and leave
@@ -471,7 +491,8 @@
 	if (ret == -EFAULT) {
 		netif_carrier_off(dev);
 		dev_kfree_skb_any(skb);
-		return 0;
+		ret = 0;
+		goto exit;
 	}
 
 	if (ret == -EAGAIN) {
@@ -484,7 +505,8 @@
 		 * in the write_done callback when the low watermark is hit.
 		 */
 		netif_stop_queue(dev);
-		return NETDEV_TX_BUSY;
+		ret = NETDEV_TX_BUSY;
+		goto exit;
 	}
 
 	if (msm_bam_dmux_is_ch_full(p->ch_id)) {
@@ -492,7 +514,9 @@
 		DBG0("%s: High WM hit, stopping queue=%p\n",    __func__, skb);
 	}
 
-	return 0;
+exit:
+	msm_bam_dmux_ul_power_unvote();
+	return ret;
 }
 
 static struct net_device_stats *rmnet_get_stats(struct net_device *dev)
@@ -700,7 +724,10 @@
 
 	p = netdev_priv(netdevs[i]);
 	p->in_reset = 1;
-	p->waiting_for_ul = 0;
+	if (p->waiting_for_ul_skb != NULL) {
+		dev_kfree_skb_any(p->waiting_for_ul_skb);
+		p->waiting_for_ul_skb = NULL;
+	}
 	msm_bam_dmux_close(p->ch_id);
 	netif_carrier_off(netdevs[i]);
 	netif_stop_queue(netdevs[i]);
@@ -740,7 +767,7 @@
 		/* Initial config uses Ethernet */
 		p->operation_mode = RMNET_MODE_LLP_ETH;
 		p->ch_id = n;
-		p->waiting_for_ul = 0;
+		p->waiting_for_ul_skb = NULL;
 		p->in_reset = 0;
 		spin_lock_init(&p->lock);
 #ifdef CONFIG_MSM_RMNET_DEBUG
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 293c25d..2e80692 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -1318,6 +1318,8 @@
 
 	read_soc_params_raw(the_chip, &raw);
 
+	calculate_cc_uah(the_chip, raw.cc, &bms_end_cc_uah);
+
 	if (is_battery_full) {
 		unsigned long flags;
 		int fcc_uah, new_fcc_uah, delta_fcc_uah;
@@ -1355,10 +1357,9 @@
 
 	bms_end_percent = the_chip->end_percent;
 	bms_end_ocv_uv = raw.last_good_ocv_uv;
-	calculate_cc_uah(the_chip, raw.cc, &bms_end_cc_uah);
 
 	if (the_chip->end_percent > the_chip->start_percent) {
-		last_charge_increase =
+		last_charge_increase +=
 			the_chip->end_percent - the_chip->start_percent;
 		if (last_charge_increase > 100) {
 			last_chargecycles++;
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 51ec91c..e24c700 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -235,6 +235,7 @@
 	unsigned int			batt_temp_channel;
 	unsigned int			batt_id_channel;
 	struct power_supply		usb_psy;
+	struct power_supply		dc_psy;
 	struct power_supply		*ext_psy;
 	struct power_supply		batt_psy;
 	struct dentry			*dent;
@@ -957,25 +958,41 @@
 	"battery",
 };
 
+#define USB_WALL_THRESHOLD_MA	500
 static int pm_power_get_property(struct power_supply *psy,
 				  enum power_supply_property psp,
 				  union power_supply_propval *val)
 {
-	struct pm8921_chg_chip *chip;
+	int current_max;
+
+	/* Check if called before init */
+	if (!the_chip)
+		return -EINVAL;
 
 	switch (psp) {
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		pm_chg_iusbmax_get(the_chip, &current_max);
+		val->intval = current_max;
+		break;
 	case POWER_SUPPLY_PROP_PRESENT:
 	case POWER_SUPPLY_PROP_ONLINE:
-		if (psy->type == POWER_SUPPLY_TYPE_USB ||
-			psy->type == POWER_SUPPLY_TYPE_USB_DCP ||
-			psy->type == POWER_SUPPLY_TYPE_USB_CDP ||
-			psy->type == POWER_SUPPLY_TYPE_USB_ACA) {
-			chip = container_of(psy, struct pm8921_chg_chip,
-							usb_psy);
-			if (pm_is_chg_charge_dis_bit_set(chip))
-				val->intval = 0;
+		if (pm_is_chg_charge_dis_bit_set(the_chip) ||
+				!is_usb_chg_plugged_in(the_chip))
+			val->intval = 0;
+		else if (psy->type == POWER_SUPPLY_TYPE_USB ||
+				psy->type == POWER_SUPPLY_TYPE_USB_DCP ||
+				psy->type == POWER_SUPPLY_TYPE_USB_CDP ||
+				psy->type == POWER_SUPPLY_TYPE_USB_ACA) {
+			val->intval = 1;
+		} else if (psy->type == POWER_SUPPLY_TYPE_MAINS) {
+			pm_chg_iusbmax_get(the_chip, &current_max);
+			if (current_max > USB_WALL_THRESHOLD_MA)
+				val->intval = 1;
 			else
-				val->intval = is_usb_chg_plugged_in(chip);
+				val->intval = 0;
+		} else {
+			val->intval = 0;
+			pr_err("Unkown POWER_SUPPLY_TYPE %d\n", psy->type);
 		}
 		break;
 	default:
@@ -3209,6 +3226,14 @@
 	chip->usb_psy.num_properties = ARRAY_SIZE(pm_power_props),
 	chip->usb_psy.get_property = pm_power_get_property,
 
+	chip->dc_psy.name = "pm8921-dc",
+	chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS,
+	chip->dc_psy.supplied_to = pm_power_supplied_to,
+	chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to),
+	chip->dc_psy.properties = pm_power_props,
+	chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props),
+	chip->dc_psy.get_property = pm_power_get_property,
+
 	chip->batt_psy.name = "battery",
 	chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY,
 	chip->batt_psy.properties = msm_batt_power_props,
@@ -3221,10 +3246,16 @@
 		goto free_chip;
 	}
 
+	rc = power_supply_register(chip->dev, &chip->dc_psy);
+	if (rc < 0) {
+		pr_err("power_supply_register usb failed rc = %d\n", rc);
+		goto unregister_usb;
+	}
+
 	rc = power_supply_register(chip->dev, &chip->batt_psy);
 	if (rc < 0) {
 		pr_err("power_supply_register batt failed rc = %d\n", rc);
-		goto unregister_usb;
+		goto unregister_dc;
 	}
 
 	platform_set_drvdata(pdev, chip);
@@ -3283,6 +3314,8 @@
 	free_irqs(chip);
 unregister_batt:
 	power_supply_unregister(&chip->batt_psy);
+unregister_dc:
+	power_supply_unregister(&chip->dc_psy);
 unregister_usb:
 	power_supply_unregister(&chip->usb_psy);
 free_chip:
diff --git a/drivers/regulator/pm8xxx-regulator.c b/drivers/regulator/pm8xxx-regulator.c
index 15a9cb1..94b028d 100644
--- a/drivers/regulator/pm8xxx-regulator.c
+++ b/drivers/regulator/pm8xxx-regulator.c
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -14,6 +14,7 @@
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
 #include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
@@ -356,12 +357,21 @@
 #define VS_PULL_DOWN_DISABLE		0x40
 #define VS_PULL_DOWN_ENABLE		0x00
 
+#define VS_MODE_MASK			0x30
+#define VS_MODE_NORMAL			0x10
+#define VS_MODE_LPM			0x20
+
 #define VS_PIN_CTRL_MASK		0x0F
 #define VS_PIN_CTRL_EN0			0x08
 #define VS_PIN_CTRL_EN1			0x04
 #define VS_PIN_CTRL_EN2			0x02
 #define VS_PIN_CTRL_EN3			0x01
 
+/* TEST register */
+#define VS_OCP_MASK			0x10
+#define VS_OCP_ENABLE			0x00
+#define VS_OCP_DISABLE			0x10
+
 /* VS300 masks and values */
 
 /* CTRL register */
@@ -372,6 +382,10 @@
 #define VS300_PULL_DOWN_ENABLE_MASK	0x20
 #define VS300_PULL_DOWN_ENABLE		0x20
 
+#define VS300_MODE_MASK			0x18
+#define VS300_MODE_NORMAL		0x00
+#define VS300_MODE_LPM			0x08
+
 /* NCP masks and values */
 
 /* CTRL register */
@@ -1900,9 +1914,32 @@
 
 	mutex_lock(&vreg->pc_lock);
 
-	rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, VS_ENABLE,
-		VS_ENABLE_MASK, &vreg->ctrl_reg);
+	if (vreg->pdata.ocp_enable) {
+		/* Disable OCP. */
+		rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr,
+			VS_OCP_DISABLE, VS_OCP_MASK, &vreg->test_reg[0]);
+		if (rc)
+			goto done;
 
+		/* Enable the switch while OCP is disabled. */
+		rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr,
+			VS_ENABLE | VS_MODE_NORMAL,
+			VS_ENABLE_MASK | VS_MODE_MASK,
+			&vreg->ctrl_reg);
+		if (rc)
+			goto done;
+
+		/* Wait for inrush current to subside, then enable OCP. */
+		udelay(vreg->pdata.ocp_enable_time);
+		rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr,
+			VS_OCP_ENABLE, VS_OCP_MASK, &vreg->test_reg[0]);
+	} else {
+		/* Enable the switch without touching OCP. */
+		rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, VS_ENABLE,
+			VS_ENABLE_MASK, &vreg->ctrl_reg);
+	}
+
+done:
 	if (!rc)
 		vreg->is_enabled = true;
 
@@ -1944,13 +1981,39 @@
 	struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev);
 	int rc;
 
-	rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, VS300_CTRL_ENABLE,
-		VS300_CTRL_ENABLE_MASK, &vreg->ctrl_reg);
+	if (vreg->pdata.ocp_enable) {
+		/* Disable OCP. */
+		rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr,
+			VS_OCP_DISABLE, VS_OCP_MASK, &vreg->test_reg[0]);
+		if (rc)
+			goto done;
 
-	if (rc)
+		/* Enable the switch while OCP is disabled. */
+		rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr,
+			VS300_CTRL_ENABLE | VS300_MODE_NORMAL,
+			VS300_CTRL_ENABLE_MASK | VS300_MODE_MASK,
+			&vreg->ctrl_reg);
+		if (rc)
+			goto done;
+
+		/* Wait for inrush current to subside, then enable OCP. */
+		udelay(vreg->pdata.ocp_enable_time);
+		rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr,
+			VS_OCP_ENABLE, VS_OCP_MASK, &vreg->test_reg[0]);
+	} else {
+		/* Enable the regulator without touching OCP. */
+		rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr,
+			VS300_CTRL_ENABLE, VS300_CTRL_ENABLE_MASK,
+			&vreg->ctrl_reg);
+	}
+
+done:
+	if (rc) {
 		vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc);
-	else
+	} else {
+		vreg->is_enabled = true;
 		pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_ENABLE);
+	}
 
 	return rc;
 }
@@ -2805,6 +2868,14 @@
 		return rc;
 	}
 
+	/* Save the current test register state. */
+	rc = pm8xxx_readb(vreg->dev->parent, vreg->test_addr,
+		&vreg->test_reg[0]);
+	if (rc) {
+		vreg_err(vreg, "pm8xxx_readb failed, rc=%d\n", rc);
+		return rc;
+	}
+
 	if (is_real) {
 		/* Set pull down enable based on platform data. */
 		rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr,
@@ -2833,6 +2904,14 @@
 		return rc;
 	}
 
+	/* Save the current test register state. */
+	rc = pm8xxx_readb(vreg->dev->parent, vreg->test_addr,
+		&vreg->test_reg[0]);
+	if (rc) {
+		vreg_err(vreg, "pm8xxx_readb failed, rc=%d\n", rc);
+		return rc;
+	}
+
 	/* Set pull down enable based on platform data. */
 	rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr,
 		    (vreg->pdata.pull_down_enable ? VS300_PULL_DOWN_ENABLE : 0),
diff --git a/drivers/staging/qcache/fmem.c b/drivers/staging/qcache/fmem.c
index 489d27a..d12c8e8 100644
--- a/drivers/staging/qcache/fmem.c
+++ b/drivers/staging/qcache/fmem.c
@@ -1,6 +1,6 @@
 /*
  *
- * 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
@@ -51,12 +51,14 @@
 {
 	struct fmem_platform_data *pdata = pdev->dev.platform_data;
 
-	if (!pdata->size)
+	fmem_data.phys = pdata->phys + pdata->reserved_size;
+	fmem_data.size = pdata->size - pdata->reserved_size;
+	fmem_data.reserved_size = pdata->reserved_size;
+
+	if (!fmem_data.size)
 		return -ENODEV;
 
-	fmem_data.phys = pdata->phys;
-	fmem_data.size = pdata->size;
-	fmem_data.area = get_vm_area(pdata->size, VM_IOREMAP);
+	fmem_data.area = get_vm_area(fmem_data.size, VM_IOREMAP);
 	if (!fmem_data.area)
 		return -ENOMEM;
 
@@ -177,7 +179,7 @@
 
 	if (fmem_state == FMEM_UNINITIALIZED) {
 		if (new_state == FMEM_T_STATE) {
-			tmem_enable(false);
+			tmem_enable();
 			create_sysfs = 1;
 			goto out_set;
 		}
@@ -194,7 +196,7 @@
 			ret = PTR_ERR(v);
 			goto out;
 		}
-		tmem_enable(true);
+		tmem_enable();
 	} else {
 		tmem_disable();
 		fmem_unmap_virtual_area();
diff --git a/drivers/staging/qcache/tmem.c b/drivers/staging/qcache/tmem.c
index 8c9049c..e5c3f30 100644
--- a/drivers/staging/qcache/tmem.c
+++ b/drivers/staging/qcache/tmem.c
@@ -810,26 +810,24 @@
 }
 
 /* The following must be called with tmem state locked */
-static void tmem_reset(void)
+static void tmem_cleanup(void)
 {
 	(*tmem_hostops.flush_all_obj)();
 }
 
-void tmem_enable(bool reset)
+void tmem_enable(void)
 {
 	pr_info("turning tmem on\n");
 	tmem_enabled = true;
 
-	if (!reset)
-		return;
-
-	tmem_reset();
 	(*tmem_hostops.control)(false);
 }
 
 void tmem_disable(void)
 {
 	pr_info("turning tmem off\n");
-	(*tmem_hostops.control)(true);
 	tmem_enabled = false;
+
+	tmem_cleanup();
+	(*tmem_hostops.control)(true);
 }
diff --git a/drivers/staging/qcache/tmem.h b/drivers/staging/qcache/tmem.h
index 9f6bfbb..dd8a6ea 100644
--- a/drivers/staging/qcache/tmem.h
+++ b/drivers/staging/qcache/tmem.h
@@ -207,6 +207,6 @@
 extern int tmem_flush_pool(struct tmem_pool *);
 extern void tmem_new_pool(struct tmem_pool *, uint32_t);
 
-extern void tmem_enable(bool);
+extern void tmem_enable(void);
 extern void tmem_disable(void);
 #endif /* _TMEM_H */
diff --git a/drivers/thermal/msm8960_tsens.c b/drivers/thermal/msm8960_tsens.c
index f2be9dc..2a2166a 100644
--- a/drivers/thermal/msm8960_tsens.c
+++ b/drivers/thermal/msm8960_tsens.c
@@ -176,7 +176,6 @@
 				TSENS_TRDY_RDY_MAX_TIME);
 		tmdev->prev_reading_avail = true;
 	}
-
 	code = readl_relaxed(TSENS_S0_STATUS_ADDR +
 			(sensor_num << TSENS_STATUS_ADDR_OFFSET));
 	*temp = tsens_tz_code_to_degC(code, sensor_num);
@@ -726,7 +725,7 @@
 				tmdev->sensor[i].calib_data_backup;
 
 		if (!tmdev->sensor[i].calib_data) {
-			pr_err("%s: No temperature sensor:%d data for"
+			WARN(1, "%s: No temperature sensor:%d data for"
 			" calibration in QFPROM!\n", __func__, i);
 			return -ENODEV;
 		}
@@ -789,12 +788,14 @@
 	rc = tsens_check_version_support();
 	if (rc < 0) {
 		kfree(tmdev);
+		tmdev = NULL;
 		return rc;
 	}
 
 	rc = tsens_calib_sensors();
 	if (rc < 0) {
 		kfree(tmdev);
+		tmdev = NULL;
 		return rc;
 	}
 
@@ -846,6 +847,7 @@
 fail:
 	tsens_disable_mode();
 	kfree(tmdev);
+	tmdev = NULL;
 	mb();
 	return rc;
 }
@@ -860,6 +862,7 @@
 	for (i = 0; i < tmdev->tsens_num_sensor; i++)
 		thermal_zone_device_unregister(tmdev->sensor[i].tz_dev);
 	kfree(tmdev);
+	tmdev = NULL;
 }
 
 module_init(tsens_tm_init);
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index 25290ba..ed80b1b 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -75,7 +75,7 @@
 	tsens_dev.sensor_num = DEF_TEMP_SENSOR;
 	ret = tsens_get_temp(&tsens_dev, &temp);
 	if (ret) {
-		pr_err("msm_thermal: Unable to read TSENS sensor %d\n",
+		pr_debug("msm_thermal: Unable to read TSENS sensor %d\n",
 				tsens_dev.sensor_num);
 		goto reschedule;
 	}
diff --git a/drivers/usb/gadget/f_diag.c b/drivers/usb/gadget/f_diag.c
index 10a9256..987ae65 100644
--- a/drivers/usb/gadget/f_diag.c
+++ b/drivers/usb/gadget/f_diag.c
@@ -525,7 +525,6 @@
 	if (rc) {
 		ERROR(dev->cdev, "can't enable %s, result %d\n",
 						dev->in->name, rc);
-		dev->in->driver_data = NULL;
 		return rc;
 	}
 	dev->out->driver_data = dev;
@@ -534,8 +533,6 @@
 		ERROR(dev->cdev, "can't enable %s, result %d\n",
 						dev->out->name, rc);
 		usb_ep_disable(dev->in);
-		dev->in->driver_data = NULL;
-		dev->out->driver_data = NULL;
 		return rc;
 	}
 	schedule_work(&dev->config_work);
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 86f8a25..d846c4e 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -61,7 +61,7 @@
 	unsigned long			cpkts_len;
 };
 
-#define NR_RMNET_PORTS	1
+#define NR_RMNET_PORTS	3
 static unsigned int nr_rmnet_ports;
 static unsigned int no_ctrl_smd_ports;
 static unsigned int no_ctrl_hsic_ports;
@@ -334,10 +334,8 @@
 	switch (dxport) {
 	case USB_GADGET_XPORT_BAM:
 	case USB_GADGET_XPORT_BAM2BAM:
-		/* currently only one connection (idx 0)
-		   is supported */
 		ret = gbam_connect(&dev->port, port_num,
-						   dxport, 0);
+						   dxport, port_num);
 		if (ret) {
 			pr_err("%s: gbam_connect failed: err:%d\n",
 					__func__, ret);
diff --git a/drivers/usb/gadget/f_rmnet_smd.c b/drivers/usb/gadget/f_rmnet_smd.c
index f59b683..2049dc0 100644
--- a/drivers/usb/gadget/f_rmnet_smd.c
+++ b/drivers/usb/gadget/f_rmnet_smd.c
@@ -5,7 +5,7 @@
  * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
  * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
  * Copyright (C) 2008 Nokia Corporation
- * 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 as published by
@@ -116,6 +116,8 @@
 	atomic_t		online;
 	atomic_t		notify_count;
 
+	struct platform_driver		pdrv;
+	u8				is_pdrv_used;
 	struct rmnet_smd_ch_info	smd_ctl;
 	struct rmnet_smd_ch_info	smd_data;
 
@@ -134,6 +136,8 @@
 	unsigned long	cpkts_to_modem;
 };
 
+static struct rmnet_smd_dev *rmnet_smd;
+
 static struct usb_interface_descriptor rmnet_smd_interface_desc = {
 	.bLength =		USB_DT_INTERFACE_SIZE,
 	.bDescriptorType =	USB_DT_INTERFACE,
@@ -856,6 +860,10 @@
 		list_add_tail(&qmi->list, &dev->qmi_resp_pool);
 	}
 
+	if (dev->is_pdrv_used) {
+		platform_driver_unregister(&dev->pdrv);
+		dev->is_pdrv_used = 0;
+	}
 }
 
 /* SMD close may sleep
@@ -894,7 +902,18 @@
 	ret = smd_open(rmnet_ctl_ch, &dev->smd_ctl.ch,
 			&dev->smd_ctl, rmnet_smd_event_notify);
 	if (ret) {
-		ERROR(cdev, "Unable to open control smd channel\n");
+		ERROR(cdev, "Unable to open control smd channel: %d\n", ret);
+		/*
+		 * Register platform driver to be notified in case SMD channels
+		 * later becomes ready to be opened.
+		 */
+		ret = platform_driver_register(&dev->pdrv);
+		if (ret)
+			ERROR(cdev, "Platform driver %s register failed %d\n",
+					dev->pdrv.driver.name, ret);
+		else
+			dev->is_pdrv_used = 1;
+
 		return;
 	}
 	wait_event(dev->smd_ctl.wait, test_bit(CH_OPENED,
@@ -916,6 +935,15 @@
 	rmnet_smd_start_rx(dev);
 }
 
+static int rmnet_smd_ch_probe(struct platform_device *pdev)
+{
+	DBG(rmnet_smd->cdev, "Probe called for device: %s\n", pdev->name);
+
+	queue_work(rmnet_smd->wq, &rmnet_smd->connect_work);
+
+	return 0;
+}
+
 /* SMD open may sleep.
  * Schedule a work to open smd channels and enable
  * endpoints if smd channels are opened successfully.
@@ -1272,6 +1300,8 @@
 	if (!dev)
 		return -ENOMEM;
 
+	rmnet_smd = dev;
+
 	dev->wq = create_singlethread_workqueue("k_rmnet_work");
 	if (!dev->wq) {
 		ret = -ENOMEM;
@@ -1299,6 +1329,10 @@
 	init_waitqueue_head(&dev->smd_ctl.wait);
 	init_waitqueue_head(&dev->smd_data.wait);
 
+	dev->pdrv.probe = rmnet_smd_ch_probe;
+	dev->pdrv.driver.name = CONFIG_RMNET_SMD_CTL_CHANNEL;
+	dev->pdrv.driver.owner = THIS_MODULE;
+
 	INIT_LIST_HEAD(&dev->qmi_req_pool);
 	INIT_LIST_HEAD(&dev->qmi_req_q);
 	INIT_LIST_HEAD(&dev->qmi_resp_pool);
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
index d9a901b..de8c8ed 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -477,7 +477,6 @@
 	if (gser->notify->driver_data) {
 		DBG(cdev, "reset generic ctl ttyGS%d\n", gser->port_num);
 		usb_ep_disable(gser->notify);
-		gser->notify->driver_data = NULL;
 	}
 	gser->notify_desc = ep_choose(cdev->gadget,
 			gser->hs.notify,
@@ -520,7 +519,6 @@
 #ifdef CONFIG_MODEM_SUPPORT
 	usb_ep_fifo_flush(gser->notify);
 	usb_ep_disable(gser->notify);
-	gser->notify->driver_data = NULL;
 #endif
 	gser->online = 0;
 }
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index ca298cd..0360f56 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -2766,17 +2766,14 @@
 	if (fsg->bulk_in_enabled) {
 		usb_ep_disable(fsg->bulk_in);
 		fsg->bulk_in_enabled = 0;
-		fsg_bulk_in->driver_data = NULL;
 	}
 	if (fsg->bulk_out_enabled) {
 		usb_ep_disable(fsg->bulk_out);
 		fsg->bulk_out_enabled = 0;
-		fsg_bulk_out->driver_data = NULL;
 	}
 	if (fsg->intr_in_enabled) {
 		usb_ep_disable(fsg->intr_in);
 		fsg->intr_in_enabled = 0;
-		fsg_intr_in->driver_data = NULL;
 	}
 
 	fsg->running = 0;
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 30f30cf..6299cdd 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -29,7 +29,7 @@
 #include "u_rmnet.h"
 
 #define BAM_N_PORTS	1
-#define BAM2BAM_N_PORTS	1
+#define BAM2BAM_N_PORTS	3
 
 static struct workqueue_struct *gbam_wq;
 static int n_bam_ports;
diff --git a/drivers/usb/gadget/u_rmnet_ctrl_smd.c b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
index a55fc77..8671669 100644
--- a/drivers/usb/gadget/u_rmnet_ctrl_smd.c
+++ b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
@@ -24,9 +24,9 @@
 
 #include "u_rmnet.h"
 
-#define NR_CTRL_SMD_PORTS	1
+#define NR_CTRL_SMD_PORTS	3
 static int n_rmnet_ctrl_ports;
-static char *rmnet_ctrl_names[] = { "DATA40_CNTL" };
+static char *rmnet_ctrl_names[] = {"DATA40_CNTL", "DATA39_CNTL", "DATA38_CNTL"};
 static struct workqueue_struct *grmnet_ctrl_wq;
 
 #define SMD_CH_MAX_LEN	20
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 5caecfb..00e4fda 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -609,7 +609,6 @@
 	int cnt = 0;
 	bool host_bus_suspend;
 	u32 phy_ctrl_val = 0, cmd_val;
-	unsigned ret;
 	u32 portsc;
 
 	if (atomic_read(&motg->in_lpm))
@@ -706,10 +705,7 @@
 	clk_disable(motg->core_clk);
 
 	/* usb phy no more require TCXO clock, hence vote for TCXO disable */
-	ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
-	if (ret)
-		dev_err(otg->dev, "%s failed to devote for "
-			"TCXO D0 buffer%d\n", __func__, ret);
+	clk_disable_unprepare(motg->xo_handle);
 
 	if (motg->caps & ALLOW_PHY_POWER_COLLAPSE && !host_bus_suspend) {
 		msm_hsusb_ldo_enable(motg, 0);
@@ -753,7 +749,7 @@
 	wake_lock(&motg->wlock);
 
 	/* Vote for TCXO when waking up the phy */
-	ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_ON);
+	ret = clk_prepare_enable(motg->xo_handle);
 	if (ret)
 		dev_err(otg->dev, "%s failed to vote for "
 			"TCXO D0 buffer%d\n", __func__, ret);
@@ -1864,7 +1860,6 @@
 					otg->state = OTG_STATE_B_PERIPHERAL;
 					break;
 				case USB_SDP_CHARGER:
-					msm_otg_notify_charger(motg, IUNIT);
 					msm_otg_start_peripheral(otg, 1);
 					otg->state = OTG_STATE_B_PERIPHERAL;
 					break;
@@ -2484,7 +2479,7 @@
 		goto free_regs;
 	}
 
-	motg->xo_handle = msm_xo_get(MSM_XO_CXO, "usb");
+	motg->xo_handle = clk_get(&pdev->dev, "xo");
 	if (IS_ERR(motg->xo_handle)) {
 		dev_err(&pdev->dev, "%s not able to get the handle "
 			"to vote for TCXO D0 buffer\n", __func__);
@@ -2492,7 +2487,7 @@
 		goto free_regs;
 	}
 
-	ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_ON);
+	ret = clk_prepare_enable(motg->xo_handle);
 	if (ret) {
 		dev_err(&pdev->dev, "%s failed to vote for TCXO "
 			"D0 buffer%d\n", __func__, ret);
@@ -2622,9 +2617,9 @@
 	msm_hsusb_init_vddcx(motg, 0);
 devote_xo_handle:
 	clk_disable(motg->pclk);
-	msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
+	clk_disable_unprepare(motg->xo_handle);
 free_xo_handle:
-	msm_xo_put(motg->xo_handle);
+	clk_put(motg->xo_handle);
 free_regs:
 	iounmap(motg->regs);
 put_pclk:
@@ -2690,7 +2685,7 @@
 
 	clk_disable(motg->pclk);
 	clk_disable(motg->core_clk);
-	msm_xo_put(motg->xo_handle);
+	clk_put(motg->xo_handle);
 	msm_hsusb_ldo_enable(motg, 0);
 	msm_hsusb_ldo_init(motg, 0);
 	msm_hsusb_init_vddcx(motg, 0);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index d2969b6..51a72c8 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.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
@@ -1457,6 +1457,7 @@
 			vcd_status = VCD_S_SUCCESS;
 		}
 	}
+	break;
 	case VCD_I_INTRA_REFRESH:
 	{
 		struct vcd_property_intra_refresh_mb_number
diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
index f56e12c..70d88ef 100644
--- a/fs/yaffs2/yaffs_vfs.c
+++ b/fs/yaffs2/yaffs_vfs.c
@@ -53,6 +53,7 @@
 #include <linux/kthread.h>
 #include <linux/delay.h>
 #include <linux/freezer.h>
+#include <linux/cleancache.h>
 
 #include <asm/div64.h>
 
@@ -1139,6 +1140,10 @@
 		(unsigned)(pg->index << PAGE_CACHE_SHIFT),
 		(unsigned)PAGE_CACHE_SIZE);
 
+	ret = cleancache_get_page(pg);
+	if (!ret)
+		goto cleancache_got;
+
 	obj = yaffs_dentry_to_obj(f->f_dentry);
 
 	dev = obj->my_dev;
@@ -1158,11 +1163,13 @@
 	if (ret >= 0)
 		ret = 0;
 
+cleancache_got:
 	if (ret) {
 		ClearPageUptodate(pg);
 		SetPageError(pg);
 	} else {
 		SetPageUptodate(pg);
+		SetPageMappedToDisk(pg);
 		ClearPageError(pg);
 	}
 
@@ -2364,6 +2371,7 @@
 		dev->is_checkpointed);
 
 	yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_super: done");
+	cleancache_init_fs(sb);
 	return sb;
 }
 
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index d1c7733..1cb5401 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -53,7 +53,12 @@
 #define APQ8060_TOOLS_ID	4062
 #define AO8960_TOOLS_ID		4064
 #define APQ8064_TOOLS_ID	4072
-#define MSM8930_TOOLS_ID	4072
+#define MSM8930_TOOLS_ID	4076
+#define MSM8630_TOOLS_ID	4077
+#define MSM8230_TOOLS_ID	4078
+#define APQ8030_TOOLS_ID	4079
+#define MSM8627_TOOLS_ID	4080
+#define MSM8227_TOOLS_ID	4081
 #define MSM8974_TOOLS_ID	4072
 
 #define MSG_MASK_0			(0x00000001)
diff --git a/include/linux/fmem.h b/include/linux/fmem.h
index c9e36b5..aebeec4 100644
--- a/include/linux/fmem.h
+++ b/include/linux/fmem.h
@@ -1,6 +1,6 @@
 /*
  *
- * 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
@@ -20,6 +20,7 @@
 struct fmem_platform_data {
 	unsigned long phys;
 	unsigned long size;
+	unsigned long reserved_size;
 };
 
 struct fmem_data {
@@ -27,6 +28,7 @@
 	void *virt;
 	struct vm_struct *area;
 	unsigned long size;
+	unsigned long reserved_size;
 };
 
 enum fmem_state {
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index 7ae8342..500ee6b 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -46,6 +46,8 @@
 
 	unsigned int x_size;
 	unsigned int y_size;
+	unsigned int touch_x_size;
+	unsigned int touch_y_size;
 	unsigned long irqflags;
 	bool	i2c_pull_up;
 	bool	digital_pwr_regulator;
diff --git a/include/linux/ion.h b/include/linux/ion.h
index 41f99e4..ade87e6 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -99,6 +99,7 @@
 #define ION_WB_HEAP_NAME	"wb"
 #define ION_MM_FIRMWARE_HEAP_NAME	"mm_fw"
 #define ION_QSECOM_HEAP_NAME	"qsecom"
+#define ION_FMEM_HEAP_NAME	"fmem"
 
 #define CACHED          1
 #define UNCACHED        0
@@ -123,6 +124,7 @@
    be converted to phys_addr_t.  For the time being many kernel interfaces
    do not accept phys_addr_t's that would have to */
 #define ion_phys_addr_t unsigned long
+#define ion_virt_addr_t unsigned long
 
 /**
  * struct ion_platform_heap - defines a heap in the given platform
@@ -132,15 +134,8 @@
  * @name:	used for debug purposes
  * @base:	base address of heap in physical memory if applicable
  * @size:	size of the heap in bytes if applicable
- * @memory_type:	Memory type used for the heap
- * @ion_memory_id:		Memory ID used to identify the memory to TZ
- * @request_region: function to be called when the number of allocations goes
- *						from 0 -> 1
- * @release_region: function to be called when the number of allocations goes
- *						from 1 -> 0
- * @setup_region:   function to be called upon ion registration
- *
- * Provided by the board file.
+ * @memory_type:Memory type used for the heap
+ * @extra_data:	Extra data specific to each heap type
  */
 struct ion_platform_heap {
 	enum ion_heap_type type;
@@ -152,16 +147,50 @@
 	void *extra_data;
 };
 
+/**
+ * struct ion_cp_heap_pdata - defines a content protection heap in the given
+ * platform
+ * @permission_type:	Memory ID used to identify the memory to TZ
+ * @align:		Alignment requirement for the memory
+ * @secure_base:	Base address for securing the heap.
+ *			Note: This might be different from actual base address
+ *			of this heap in the case of a shared heap.
+ * @secure_size:	Memory size for securing the heap.
+ *			Note: This might be different from actual size
+ *			of this heap in the case of a shared heap.
+ * @reusable		Flag indicating whether this heap is reusable of not.
+ *			(see FMEM)
+ * @virt_addr:		Virtual address used when using fmem.
+ * @request_region:	function to be called when the number of allocations
+ *			goes from 0 -> 1
+ * @release_region:	function to be called when the number of allocations
+ *			goes from 1 -> 0
+ * @setup_region:	function to be called upon ion registration
+ *
+ */
 struct ion_cp_heap_pdata {
 	enum ion_permission_type permission_type;
 	unsigned int align;
 	ion_phys_addr_t secure_base; /* Base addr used when heap is shared */
 	size_t secure_size; /* Size used for securing heap when heap is shared*/
+	int reusable;
+	ion_virt_addr_t *virt_addr;
 	int (*request_region)(void *);
 	int (*release_region)(void *);
 	void *(*setup_region)(void);
 };
 
+/**
+ * struct ion_co_heap_pdata - defines a carveout heap in the given platform
+ * @adjacent_mem_id:	Id of heap that this heap must be adjacent to.
+ * @align:		Alignment requirement for the memory
+ * @request_region:	function to be called when the number of allocations
+ *			goes from 0 -> 1
+ * @release_region:	function to be called when the number of allocations
+ *			goes from 1 -> 0
+ * @setup_region:	function to be called upon ion registration
+ *
+ */
 struct ion_co_heap_pdata {
 	int adjacent_mem_id;
 	unsigned int align;
diff --git a/include/linux/mfd/pm8xxx/misc.h b/include/linux/mfd/pm8xxx/misc.h
index f9fc498..c4f601b 100644
--- a/include/linux/mfd/pm8xxx/misc.h
+++ b/include/linux/mfd/pm8xxx/misc.h
@@ -172,6 +172,15 @@
  */
 int pm8xxx_preload_dVdd(void);
 
+/**
+ * pm8xxx_usb_id_pullup - Control a pullup for USB ID
+ *
+ * @enable: enable (1) or disable (0) the pullup
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_usb_id_pullup(int enable);
+
 #else
 
 static inline int pm8xxx_reset_pwr_off(int reset)
@@ -212,6 +221,10 @@
 {
 	return -ENODEV;
 }
+static inline int pm8xxx_usb_id_pullup(int enable)
+{
+	return -ENODEV;
+}
 #endif
 
 #endif
diff --git a/include/linux/mfd/pm8xxx/pm8018.h b/include/linux/mfd/pm8xxx/pm8018.h
index e0ec0b4..20c9d26 100644
--- a/include/linux/mfd/pm8xxx/pm8018.h
+++ b/include/linux/mfd/pm8xxx/pm8018.h
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -57,6 +57,8 @@
 #define PM8018_ADC_BATT_TEMP_WARM_IRQ	PM8018_IRQ_BLOCK_BIT(9, 1)
 #define PM8018_ADC_BATT_TEMP_COLD_IRQ	PM8018_IRQ_BLOCK_BIT(9, 0)
 
+#define PM8018_LVS1_OCP_IRQ		PM8921_IRQ_BLOCK_BIT(13, 0)
+
 struct pm8018_platform_data {
 	struct pm8xxx_irq_platform_data		*irq_pdata;
 	struct pm8xxx_gpio_platform_data	*gpio_pdata;
diff --git a/include/linux/mfd/pm8xxx/pm8921.h b/include/linux/mfd/pm8xxx/pm8921.h
index ee1216d..22293fe 100644
--- a/include/linux/mfd/pm8xxx/pm8921.h
+++ b/include/linux/mfd/pm8xxx/pm8921.h
@@ -112,6 +112,16 @@
 #define PM8921_TEMPSTAT_IRQ		PM8921_IRQ_BLOCK_BIT(6, 7)
 #define PM8921_RESOUT_IRQ		PM8921_IRQ_BLOCK_BIT(6, 4)
 
+#define PM8921_USB_OTG_OCP_IRQ		PM8921_IRQ_BLOCK_BIT(6, 0)
+#define PM8921_LVS7_OCP_IRQ		PM8921_IRQ_BLOCK_BIT(13, 7)
+#define PM8921_LVS6_OCP_IRQ		PM8921_IRQ_BLOCK_BIT(13, 6)
+#define PM8921_LVS5_OCP_IRQ		PM8921_IRQ_BLOCK_BIT(13, 5)
+#define PM8921_LVS4_OCP_IRQ		PM8921_IRQ_BLOCK_BIT(13, 4)
+#define PM8921_LVS3_OCP_IRQ		PM8921_IRQ_BLOCK_BIT(13, 3)
+#define PM8921_LVS2_OCP_IRQ		PM8921_IRQ_BLOCK_BIT(13, 2)
+#define PM8921_LVS1_OCP_IRQ		PM8921_IRQ_BLOCK_BIT(13, 1)
+#define PM8921_HDMI_MVS_OCP_IRQ		PM8921_IRQ_BLOCK_BIT(13, 0)
+
 /* PMIC I/O Resources */
 #define PM8921_RTC_BASE 0x11D
 
diff --git a/include/linux/mfd/pm8xxx/regulator.h b/include/linux/mfd/pm8xxx/regulator.h
index 38700cb..9e0ce86 100644
--- a/include/linux/mfd/pm8xxx/regulator.h
+++ b/include/linux/mfd/pm8xxx/regulator.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
@@ -227,20 +227,22 @@
 		.prev_write_count = -1, \
 	}
 
-#define VS(_name, _pc_name, _ctrl_addr) \
+#define VS(_name, _pc_name, _ctrl_addr, _test_addr) \
 	{ \
 		.type		= PM8XXX_REGULATOR_TYPE_VS, \
 		.ctrl_addr	= _ctrl_addr, \
+		.test_addr	= _test_addr, \
 		.rdesc.name	= _name, \
 		.rdesc_pc.name	= _pc_name, \
 		.write_count	= 0, \
 		.prev_write_count = -1, \
 	}
 
-#define VS300(_name, _ctrl_addr) \
+#define VS300(_name, _ctrl_addr, _test_addr) \
 	{ \
 		.type		= PM8XXX_REGULATOR_TYPE_VS300, \
 		.ctrl_addr	= _ctrl_addr, \
+		.test_addr	= _test_addr, \
 		.rdesc.name	= _name, \
 		.write_count	= 0, \
 		.prev_write_count = -1, \
diff --git a/include/linux/mfd/wcd9310/core.h b/include/linux/mfd/wcd9310/core.h
index 0eb875c..982803d 100644
--- a/include/linux/mfd/wcd9310/core.h
+++ b/include/linux/mfd/wcd9310/core.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
@@ -22,6 +22,13 @@
 #define TABLA_INTERFACE_TYPE_SLIMBUS	0x00
 #define TABLA_INTERFACE_TYPE_I2C	0x01
 
+#define TABLA_VERSION_1_0	0
+#define TABLA_VERSION_1_1	1
+#define TABLA_VERSION_2_0	2
+#define TABLA_IS_1_X(ver) \
+	(((ver == TABLA_VERSION_1_0) || (ver == TABLA_VERSION_1_1)) ? 1 : 0)
+#define TABLA_IS_2_0(ver) ((ver == TABLA_VERSION_2_0) ? 1 : 0)
+
 enum {
 	TABLA_IRQ_SLIMBUS = 0,
 	TABLA_IRQ_MBHC_REMOVAL,
@@ -55,6 +62,7 @@
 	struct mutex io_lock;
 	struct mutex xfer_lock;
 	struct mutex irq_lock;
+	u8 version;
 
 	unsigned int irq_base;
 	unsigned int irq;
diff --git a/include/linux/mfd/wcd9310/registers.h b/include/linux/mfd/wcd9310/registers.h
index fde4129..ef27c08 100644
--- a/include/linux/mfd/wcd9310/registers.h
+++ b/include/linux/mfd/wcd9310/registers.h
@@ -208,11 +208,14 @@
 #define TABLA_A_MICB_3_INT_RBIAS__POR			(0x00000000)
 #define TABLA_A_MICB_3_MBHC			(0x0139)
 #define TABLA_A_MICB_3_MBHC__POR			(0x00000000)
-#define TABLA_A_MICB_4_CTL			(0x013A)
+#define TABLA_1_A_MICB_4_CTL			(0x013A)
+#define TABLA_2_A_MICB_4_CTL			(0x013D)
 #define TABLA_A_MICB_4_CTL__POR			(0x00000016)
-#define TABLA_A_MICB_4_INT_RBIAS			(0x013B)
+#define TABLA_1_A_MICB_4_INT_RBIAS			(0x013B)
+#define TABLA_2_A_MICB_4_INT_RBIAS			(0x013E)
 #define TABLA_A_MICB_4_INT_RBIAS__POR			(0x00000000)
-#define TABLA_A_MICB_4_MBHC			(0x013C)
+#define TABLA_1_A_MICB_4_MBHC			(0x013C)
+#define TABLA_2_A_MICB_4_MBHC			(0x013F)
 #define TABLA_A_MICB_4_MBHC__POR			(0x00000001)
 #define TABLA_A_TX_COM_BIAS			(0x014C)
 #define TABLA_A_TX_COM_BIAS__POR			(0x000000E0)
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 5e37c02..9eb6dda 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -9,6 +9,7 @@
 #define KGSL_CONTEXT_NO_GMEM_ALLOC	2
 #define KGSL_CONTEXT_SUBMIT_IB_LIST	4
 #define KGSL_CONTEXT_CTX_SWITCH	8
+#define KGSL_CONTEXT_PREAMBLE	16
 
 /* Memory allocayion flags */
 #define KGSL_MEMFLAGS_GPUREADONLY	0x01000000
diff --git a/include/linux/regulator/pm8xxx-regulator.h b/include/linux/regulator/pm8xxx-regulator.h
index 7c8d778..ddf1901 100644
--- a/include/linux/regulator/pm8xxx-regulator.h
+++ b/include/linux/regulator/pm8xxx-regulator.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
@@ -66,6 +66,11 @@
  * @enable_time:	time in us taken to enable a regulator to the maximum
  *			allowed voltage for the system.  This is dependent upon
  *			the load and capacitance for a regulator on the board.
+ * @ocp_enable:		enable over current protection logic (available for
+ *			LVS and MVS type switches)
+ * @ocp_enable_time:	time in us to delay between enabling the switch and then
+ *			enabling OCP for it.  This delay is needed to avoid
+ *			false triggering due to inrush current.
  */
 struct pm8xxx_regulator_platform_data {
 	struct regulator_init_data	init_data;
@@ -75,6 +80,8 @@
 	enum pm8xxx_vreg_pin_function	pin_fn;
 	int				system_uA;
 	int				enable_time;
+	unsigned			ocp_enable;
+	int				ocp_enable_time;
 };
 
 #endif
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index f4cc449..2cbe6ce 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -240,7 +240,7 @@
 	unsigned mA_port;
 	struct timer_list id_timer;
 	unsigned long caps;
-	struct msm_xo_voter *xo_handle;
+	struct clk *xo_handle;
 	/*
 	 * Allowing PHY power collpase turns off the HSUSB 3.3v and 1.8v
 	 * analog regulators while going to low power mode.
@@ -286,8 +286,6 @@
 
 struct msm_usb_bam_platform_data {
 	struct usb_bam_pipe_connect *connections;
-	unsigned long usb_bam_phy_base;
-	unsigned long usb_bam_phy_size;
 	int usb_active_bam;
 	int usb_bam_num_pipes;
 };
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 75fa487..ebd2b75 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -376,7 +376,16 @@
 #define V4L2_PIX_FMT_MJPEG    v4l2_fourcc('M', 'J', 'P', 'G') /* Motion-JPEG   */
 #define V4L2_PIX_FMT_JPEG     v4l2_fourcc('J', 'P', 'E', 'G') /* JFIF JPEG     */
 #define V4L2_PIX_FMT_DV       v4l2_fourcc('d', 'v', 's', 'd') /* 1394          */
-#define V4L2_PIX_FMT_MPEG     v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4    */
+#define V4L2_PIX_FMT_MPEG     v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4 Multiplexed */
+#define V4L2_PIX_FMT_H264     v4l2_fourcc('H', '2', '6', '4') /* H264 with start codes */
+#define V4L2_PIX_FMT_H264_NO_SC v4l2_fourcc('A', 'V', 'C', '1') /* H264 without start codes */
+#define V4L2_PIX_FMT_H263     v4l2_fourcc('H', '2', '6', '3') /* H263          */
+#define V4L2_PIX_FMT_MPEG1    v4l2_fourcc('M', 'P', 'G', '1') /* MPEG-1 ES     */
+#define V4L2_PIX_FMT_MPEG2    v4l2_fourcc('M', 'P', 'G', '2') /* MPEG-2 ES     */
+#define V4L2_PIX_FMT_MPEG4    v4l2_fourcc('M', 'P', 'G', '4') /* MPEG-4 ES     */
+#define V4L2_PIX_FMT_XVID     v4l2_fourcc('X', 'V', 'I', 'D') /* Xvid           */
+#define V4L2_PIX_FMT_VC1_ANNEX_G v4l2_fourcc('V', 'C', '1', 'G') /* SMPTE 421M Annex G compliant stream */
+#define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */
 
 /*  Vendor-specific formats   */
 #define V4L2_PIX_FMT_CPIA1    v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
@@ -703,6 +712,11 @@
 /*  Flags for 'capability' and 'capturemode' fields */
 #define V4L2_MODE_HIGHQUALITY	0x0001	/*  High quality imaging mode */
 #define V4L2_CAP_TIMEPERFRAME	0x1000	/*  timeperframe field is supported */
+#define V4L2_CAP_QCOM_FRAMESKIP	0x2000	/*  frame skipping is supported */
+
+struct v4l2_qcom_frameskip {
+	__u64		maxframeinterval;
+};
 
 struct v4l2_outputparm {
 	__u32		   capability;	 /*  Supported modes */
@@ -1156,7 +1170,7 @@
 #define V4L2_CID_MPEG_BASE 			(V4L2_CTRL_CLASS_MPEG | 0x900)
 #define V4L2_CID_MPEG_CLASS 			(V4L2_CTRL_CLASS_MPEG | 1)
 
-/*  MPEG streams */
+/*  MPEG streams, specific to multiplexed streams */
 #define V4L2_CID_MPEG_STREAM_TYPE 		(V4L2_CID_MPEG_BASE+0)
 enum v4l2_mpeg_stream_type {
 	V4L2_MPEG_STREAM_TYPE_MPEG2_PS   = 0, /* MPEG-2 program stream */
@@ -1178,7 +1192,7 @@
 	V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1,  /* VBI in private packets, IVTV format */
 };
 
-/*  MPEG audio */
+/*  MPEG audio controls specific to multiplexed streams  */
 #define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ 	(V4L2_CID_MPEG_BASE+100)
 enum v4l2_mpeg_audio_sampling_freq {
 	V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0,
@@ -1294,7 +1308,7 @@
 	V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18,
 };
 
-/*  MPEG video */
+/*  MPEG video controls specific to multiplexed streams */
 #define V4L2_CID_MPEG_VIDEO_ENCODING 		(V4L2_CID_MPEG_BASE+200)
 enum v4l2_mpeg_video_encoding {
 	V4L2_MPEG_VIDEO_ENCODING_MPEG_1     = 0,
diff --git a/include/media/tsop-ir.h b/include/media/gpio-ir-recv.h
similarity index 82%
rename from include/media/tsop-ir.h
rename to include/media/gpio-ir-recv.h
index e94ccb1..3eab611 100644
--- a/include/media/tsop-ir.h
+++ b/include/media/gpio-ir-recv.h
@@ -10,14 +10,14 @@
  * GNU General Public License for more details.
  */
 
-#ifndef __TSOP_IR_H__
-#define __TSOP_IR_H__
+#ifndef __GPIO_IR_RECV_H__
+#define __GPIO_IR_RECV_H__
 
-struct tsop_platform_data {
+struct gpio_ir_recv_platform_data {
 	unsigned int gpio_nr;
 	bool active_low;
 	bool can_wakeup;
 };
 
-#endif /* __TSOP_IR_H__ */
+#endif /* __GPIO_IR_RECV_H__ */
 
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index d905b22..8d2852b 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -1,3 +1,15 @@
+/* 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
 #ifndef __LINUX_MSM_CAMERA_H
 #define __LINUX_MSM_CAMERA_H
 
@@ -168,6 +180,15 @@
 #define MSM_CAM_IOCTL_GET_KERNEL_SYSTEM_TIME \
 	_IOW(MSM_CAM_IOCTL_MAGIC, 50, struct timeval *)
 
+#define MSM_CAM_IOCTL_SET_VFE_OUTPUT_TYPE \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 51, uint32_t *)
+
+#define MSM_CAM_IOCTL_GET_MCTL_INFO \
+	_IOR(MSM_CAM_IOCTL_MAGIC, 51, struct msm_mctl_node_info *)
+
+#define MSM_CAM_IOCTL_MCTL_DIVERT_DONE \
+	_IOR(MSM_CAM_IOCTL_MAGIC, 52, struct msm_cam_evt_divert_frame *)
+
 struct msm_mctl_pp_cmd {
 	int32_t  id;
 	uint16_t length;
@@ -265,6 +286,7 @@
 struct msm_pp_frame {
 	uint32_t       handle; /* stores vb cookie */
 	uint32_t       frame_id;
+	unsigned short buf_idx;
 	int            path;
 	unsigned short image_type;
 	unsigned short num_planes; /* 1 for sp */
@@ -403,6 +425,11 @@
 #define CMD_AXI_CFG_VIDEO_ALL_CHNLS 50
 #define CMD_VFE_BUFFER_RELEASE 51
 
+#define CMD_AXI_CFG_PRIM		0xF1
+#define CMD_AXI_CFG_PRIM_ALL_CHNLS	0xF2
+#define CMD_AXI_CFG_SEC			0xF4
+#define CMD_AXI_CFG_SEC_ALL_CHNLS	0xF8
+
 /* vfe config command: config command(from config thread)*/
 struct msm_vfe_cfg_cmd {
 	int cmd_type;
@@ -495,6 +522,12 @@
 #define OUTPUT_ZSL_ALL_CHNLS 10
 #define LAST_AXI_OUTPUT_MODE_ENUM = OUTPUT_ZSL_ALL_CHNLS
 
+#define OUTPUT_PRIM		0xF1
+#define OUTPUT_PRIM_ALL_CHNLS	0xF2
+#define OUTPUT_SEC		0xF4
+#define OUTPUT_SEC_ALL_CHNLS	0xF8
+
+
 #define MSM_FRAME_PREV_1	0
 #define MSM_FRAME_PREV_2	1
 #define MSM_FRAME_ENC		2
@@ -640,7 +673,8 @@
 #define MSM_V4L2_PID_STROBE_FLASH           (V4L2_CID_PRIVATE_BASE+15)
 #define MSM_V4L2_PID_MMAP_ENTRY             (V4L2_CID_PRIVATE_BASE+16)
 #define MSM_V4L2_PID_MMAP_INST              (V4L2_CID_PRIVATE_BASE+17)
-#define MSM_V4L2_PID_MAX                    MSM_V4L2_PID_MMAP_INST
+#define MSM_V4L2_PID_PP_PLANE_INFO          (V4L2_CID_PRIVATE_BASE+18)
+#define MSM_V4L2_PID_MAX                    MSM_V4L2_PID_PP_PLANE_INFO
 
 /* camera operation mode for video recording - two frame output queues */
 #define MSM_V4L2_CAM_OP_DEFAULT         0
@@ -1143,6 +1177,11 @@
 	int config_dev_id[MSM_MAX_CAMERA_CONFIGS];
 };
 
+struct msm_mctl_node_info {
+	int num_mctl_nodes;
+	const char *mctl_node_name[MSM_MAX_CAMERA_SENSORS];
+};
+
 struct flash_ctrl_data {
 	int flashtype;
 	union {
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index dae4a12..7caafb6 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -1,6 +1,20 @@
+/* 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.
+ *
+ */
 #ifndef __MSM_ISP_H__
 #define __MSM_ISP_H__
 
+#define BIT(nr)			(1UL << (nr))
+
 /* ISP message IDs */
 #define MSG_ID_RESET_ACK                0
 #define MSG_ID_START_ACK                1
@@ -42,6 +56,8 @@
 #define MSG_ID_SOF_ACK                  37
 #define MSG_ID_STOP_REC_ACK             38
 #define MSG_ID_STATS_AWB_AEC            39
+#define MSG_ID_OUTPUT_PRIMARY           40
+#define MSG_ID_OUTPUT_SECONDARY         41
 
 /* ISP command IDs */
 #define VFE_CMD_DUMMY_0                                 0
@@ -180,6 +196,8 @@
 #define VFE_CMD_Y_GAMMA_CONFIG                          133
 #define VFE_CMD_SCALE_OUTPUT1_CONFIG                    134
 #define VFE_CMD_SCALE_OUTPUT2_CONFIG                    135
+#define VFE_CMD_CAPTURE_RAW                             136
+#define VFE_CMD_STOP_LIVESHOT                           137
 
 struct msm_isp_cmd {
 	int32_t  id;
@@ -199,8 +217,8 @@
 #define VPE_CMD_OUTPUT_PLANE_CFG                        9
 #define VPE_CMD_INPUT_PLANE_UPDATE                      10
 #define VPE_CMD_SCALE_CFG_TYPE                          11
-#define VPE_CMD_DIS_OFFSET_CFG                          12
 #define VPE_CMD_ZOOM                                    13
+#define VPE_CMD_MAX                                     14
 
 #define MSM_PP_CMD_TYPE_NOT_USED        0  /* not used */
 #define MSM_PP_CMD_TYPE_VPE             1  /* VPE cmd */
@@ -215,9 +233,9 @@
 #define MCTL_PP_EVENT_NOTUSED           0
 #define MCTL_PP_EVENT_CMD_ACK           1
 
-#define VPE_OPERATION_MODE_CFG_LEN      8
+#define VPE_OPERATION_MODE_CFG_LEN      4
 #define VPE_INPUT_PLANE_CFG_LEN         24
-#define VPE_OUTPUT_PLANE_CFG_LEN        24
+#define VPE_OUTPUT_PLANE_CFG_LEN        20
 #define VPE_INPUT_PLANE_UPDATE_LEN      12
 #define VPE_SCALER_CONFIG_LEN           260
 #define VPE_DIS_OFFSET_CFG_LEN          12
@@ -242,10 +260,6 @@
 	uint8_t scaler_cfg[VPE_SCALER_CONFIG_LEN];
 };
 
-struct msm_vpe_dis_offset_cfg {
-	uint8_t dis_offset_cfg[VPE_DIS_OFFSET_CFG_LEN];
-};
-
 struct msm_vpe_flush_frame_buffer {
 	uint32_t src_buf_handle;
 	uint32_t dest_buf_handle;
@@ -287,5 +301,15 @@
 	/* TBD: 3D related */
 };
 
+#define VFE_OUTPUTS_MAIN_AND_PREVIEW	BIT(0)
+#define VFE_OUTPUTS_MAIN_AND_VIDEO	BIT(1)
+#define VFE_OUTPUTS_MAIN_AND_THUMB	BIT(2)
+#define VFE_OUTPUTS_THUMB_AND_MAIN	BIT(3)
+#define VFE_OUTPUTS_PREVIEW_AND_VIDEO	BIT(4)
+#define VFE_OUTPUTS_VIDEO_AND_PREVIEW	BIT(5)
+#define VFE_OUTPUTS_PREVIEW		BIT(6)
+#define VFE_OUTPUTS_VIDEO		BIT(7)
+#define VFE_OUTPUTS_RAW			BIT(8)
+
 #endif /*__MSM_ISP_H__*/
 
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index 4918caa..0a3b91d 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -1158,6 +1158,7 @@
 		if (skb->len < sizeof(*grsp))
 			goto cpl_finished;
 		grsp = (struct a2mp_getinfo_rsp *) skb_pull(skb, sizeof(*hdr));
+		skb_pull(skb, sizeof(*grsp));
 		if (grsp->status)
 			goto cpl_finished;
 		if (grsp->id != ctx->d.cpl.remote_id)
@@ -1171,7 +1172,6 @@
 		ctrl->min_latency = le32_to_cpu(grsp->min_latency);
 		ctrl->pal_cap = le16_to_cpu(grsp->pal_cap);
 		ctrl->max_assoc_size = le16_to_cpu(grsp->assoc_size);
-		skb_pull(skb, sizeof(*grsp));
 
 		ctx->d.cpl.max_len = ctrl->max_assoc_size;
 
@@ -1191,8 +1191,6 @@
 			goto cpl_finished;
 		hdr = (void *) skb->data;
 		arsp = (void *) skb_pull(skb, sizeof(*hdr));
-		if (arsp->id != ctx->d.cpl.remote_id)
-			goto cpl_finished;
 		if (arsp->status != 0)
 			goto cpl_finished;
 
@@ -1200,12 +1198,12 @@
 		assoc = (u8 *) skb_pull(skb, sizeof(*arsp));
 		ctx->d.cpl.len_so_far = 0;
 		ctx->d.cpl.rem_len = hdr->len - sizeof(*arsp);
+		skb_pull(skb, ctx->d.cpl.rem_len);
 		rassoc = kmalloc(ctx->d.cpl.rem_len, GFP_ATOMIC);
 		if (!rassoc)
 			goto cpl_finished;
 		memcpy(rassoc, assoc, ctx->d.cpl.rem_len);
 		ctx->d.cpl.remote_assoc = rassoc;
-		skb_pull(skb, ctx->d.cpl.rem_len);
 
 		/* set up CPL command */
 		ctx->d.cpl.phy_handle = physlink_handle(ctx->hdev);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index ccf3623..f0f2ac1 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -909,7 +909,9 @@
 	if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn))
 		return;
 
-	if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF))
+	if (conn->mode != HCI_CM_ACTIVE ||
+		!(conn->link_policy & HCI_LP_SNIFF) ||
+		(hci_find_link_key(hdev, &conn->dst) == NULL))
 		return;
 
 	if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 675b34f..fec6f32 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1,6 +1,6 @@
 /*
    BlueZ - Bluetooth protocol stack for Linux
-   Copyright (c) 2000-2001, 2010-2011, Code Aurora Forum. All rights reserved.
+   Copyright (c) 2000-2001, 2010-2012, Code Aurora Forum. All rights reserved.
 
    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
 
@@ -2492,6 +2492,7 @@
 		hci_conn_hold(conn);
 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
 		hci_conn_put(conn);
+		hci_conn_enter_active_mode(conn, 0);
 	}
 
 	if (!test_bit(HCI_PAIRABLE, &hdev->flags))
@@ -2587,6 +2588,7 @@
 
 		pin_len = conn->pin_length;
 		hci_conn_put(conn);
+		hci_conn_enter_active_mode(conn, 0);
 	}
 
 	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 92d72b7..0719874 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -523,6 +523,7 @@
 	struct sock *sk = sock->sk;
 	struct hci_dev *hdev;
 	struct sk_buff *skb;
+	int reserve = 0;
 	int err;
 
 	BT_DBG("sock %p sk %p", sock, sk);
@@ -560,10 +561,18 @@
 		goto done;
 	}
 
-	skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err);
+	/* Allocate extra headroom for Qualcomm PAL */
+	if (hdev->dev_type == HCI_AMP && hdev->manufacturer == 0x001d)
+		reserve = BT_SKB_RESERVE_80211;
+
+	skb = bt_skb_send_alloc(sk, len + reserve,
+					msg->msg_flags & MSG_DONTWAIT, &err);
 	if (!skb)
 		goto done;
 
+	if (reserve)
+		skb_reserve(skb, reserve);
+
 	if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
 		err = -EFAULT;
 		goto drop;
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a570ff9..17a80bf 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -408,6 +408,7 @@
 bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev);
 
 /* internal helpers */
+bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher);
 int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
 				   struct key_params *params, int key_idx,
 				   bool pairwise, const u8 *mac_addr);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 0fc46b3..1a84262 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3947,23 +3947,6 @@
 				  NL80211_WPA_VERSION_2));
 }
 
-static bool nl80211_valid_akm_suite(u32 akm)
-{
-	return akm == WLAN_AKM_SUITE_8021X ||
-		akm == WLAN_AKM_SUITE_PSK;
-}
-
-static bool nl80211_valid_cipher_suite(u32 cipher)
-{
-	return cipher == WLAN_CIPHER_SUITE_WEP40 ||
-		cipher == WLAN_CIPHER_SUITE_WEP104 ||
-		cipher == WLAN_CIPHER_SUITE_TKIP ||
-		cipher == WLAN_CIPHER_SUITE_CCMP ||
-		cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
-		cipher == WLAN_CIPHER_SUITE_SMS4;
-}
-
-
 static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -4096,15 +4079,17 @@
 		memcpy(settings->ciphers_pairwise, data, len);
 
 		for (i = 0; i < settings->n_ciphers_pairwise; i++)
-			if (!nl80211_valid_cipher_suite(
-					settings->ciphers_pairwise[i]))
+			if (!cfg80211_supported_cipher_suite(
+				&rdev->wiphy,
+				settings->ciphers_pairwise[i]))
 				return -EINVAL;
 	}
 
 	if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) {
 		settings->cipher_group =
 			nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]);
-		if (!nl80211_valid_cipher_suite(settings->cipher_group))
+		if (!cfg80211_supported_cipher_suite(&rdev->wiphy,
+					settings->cipher_group))
 			return -EINVAL;
 	}
 
@@ -4117,7 +4102,7 @@
 
 	if (info->attrs[NL80211_ATTR_AKM_SUITES]) {
 		void *data;
-		int len, i;
+		int len;
 
 		data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]);
 		len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]);
@@ -4130,10 +4115,6 @@
 			return -EINVAL;
 
 		memcpy(settings->akm_suites, data, len);
-
-		for (i = 0; i < settings->n_akm_suites; i++)
-			if (!nl80211_valid_akm_suite(settings->akm_suites[i]))
-				return -EINVAL;
 	}
 
 	return 0;
diff --git a/net/wireless/util.c b/net/wireless/util.c
index c00a511..c69e653 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -150,12 +150,19 @@
 			set_mandatory_flags_band(wiphy->bands[band], band);
 }
 
+bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher)
+{
+	int i;
+	for (i = 0; i < wiphy->n_cipher_suites; i++)
+		if (cipher == wiphy->cipher_suites[i])
+			return true;
+	return false;
+}
+
 int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
 				   struct key_params *params, int key_idx,
 				   bool pairwise, const u8 *mac_addr)
 {
-	int i;
-
 	if (key_idx > 5)
 		return -EINVAL;
 
@@ -229,10 +236,7 @@
 		}
 	}
 
-	for (i = 0; i < rdev->wiphy.n_cipher_suites; i++)
-		if (params->cipher == rdev->wiphy.cipher_suites[i])
-			break;
-	if (i == rdev->wiphy.n_cipher_suites)
+	if (!cfg80211_supported_cipher_suite(&rdev->wiphy, params->cipher))
 		return -EINVAL;
 
 	return 0;
diff --git a/scripts/gcc-wrapper.py b/scripts/gcc-wrapper.py
index cbe2eae..65744e1 100755
--- a/scripts/gcc-wrapper.py
+++ b/scripts/gcc-wrapper.py
@@ -1,7 +1,7 @@
 #! /usr/bin/env python
 # -*- coding: utf-8 -*-
 
-# Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+# Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are met:
@@ -40,6 +40,7 @@
 # force LANG to be set to en_US.UTF-8 to get consistent warnings.
 
 allowed_warnings = set([
+    "alignment.c:298",
     "alignment.c:720",
     "async.c:122",
     "async.c:270",
@@ -59,6 +60,7 @@
     "nf_conntrack_netlink.c:790",
     "nf_nat_standalone.c:118",
     "return_address.c:62",
+    "sch_generic.c:678",
     "soc-core.c:1719",
     "xt_log.h:50",
     "vx6953.c:3124",
diff --git a/sound/soc/codecs/wcd9310-tables.c b/sound/soc/codecs/wcd9310-tables.c
index a97a981..c681771 100644
--- a/sound/soc/codecs/wcd9310-tables.c
+++ b/sound/soc/codecs/wcd9310-tables.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
@@ -117,9 +117,6 @@
 	[TABLA_A_MICB_3_CTL] = 1,
 	[TABLA_A_MICB_3_INT_RBIAS] = 1,
 	[TABLA_A_MICB_3_MBHC] = 1,
-	[TABLA_A_MICB_4_CTL] = 1,
-	[TABLA_A_MICB_4_INT_RBIAS] = 1,
-	[TABLA_A_MICB_4_MBHC] = 1,
 	[TABLA_A_TX_COM_BIAS] = 1,
 	[TABLA_A_MBHC_SCALING_MUX_1] = 1,
 	[TABLA_A_MBHC_SCALING_MUX_2] = 1,
@@ -538,6 +535,18 @@
 	[TABLA_A_CDC_MBHC_SPARE] = 1,
 };
 
+const unsigned int tabla_1_reg_readable[TABLA_1_X_ONLY_REGISTERS] = {
+	TABLA_1_A_MICB_4_CTL,
+	TABLA_1_A_MICB_4_INT_RBIAS,
+	TABLA_1_A_MICB_4_MBHC,
+};
+
+const unsigned int tabla_2_reg_readable[TABLA_2_HIGHER_ONLY_REGISTERS] = {
+	TABLA_2_A_MICB_4_CTL,
+	TABLA_2_A_MICB_4_INT_RBIAS,
+	TABLA_2_A_MICB_4_MBHC,
+};
+
 const u8 tabla_reg_defaults[TABLA_CACHE_SIZE] = {
 	[TABLA_A_CHIP_CTL] = TABLA_A_CHIP_CTL__POR,
 	[TABLA_A_CHIP_STATUS] = TABLA_A_CHIP_STATUS__POR,
@@ -643,9 +652,12 @@
 	[TABLA_A_MICB_3_CTL] = TABLA_A_MICB_3_CTL__POR,
 	[TABLA_A_MICB_3_INT_RBIAS] = TABLA_A_MICB_3_INT_RBIAS__POR,
 	[TABLA_A_MICB_3_MBHC] = TABLA_A_MICB_3_MBHC__POR,
-	[TABLA_A_MICB_4_CTL] = TABLA_A_MICB_4_CTL__POR,
-	[TABLA_A_MICB_4_INT_RBIAS] = TABLA_A_MICB_4_INT_RBIAS__POR,
-	[TABLA_A_MICB_4_MBHC] = TABLA_A_MICB_4_MBHC__POR,
+	[TABLA_1_A_MICB_4_CTL] = TABLA_A_MICB_4_CTL__POR,
+	[TABLA_1_A_MICB_4_INT_RBIAS] = TABLA_A_MICB_4_INT_RBIAS__POR,
+	[TABLA_1_A_MICB_4_MBHC] = TABLA_A_MICB_4_MBHC__POR,
+	[TABLA_2_A_MICB_4_CTL] = TABLA_A_MICB_4_CTL__POR,
+	[TABLA_2_A_MICB_4_INT_RBIAS] = TABLA_A_MICB_4_INT_RBIAS__POR,
+	[TABLA_2_A_MICB_4_MBHC] = TABLA_A_MICB_4_MBHC__POR,
 	[TABLA_A_TX_COM_BIAS] = TABLA_A_TX_COM_BIAS__POR,
 	[TABLA_A_MBHC_SCALING_MUX_1] = TABLA_A_MBHC_SCALING_MUX_1__POR,
 	[TABLA_A_MBHC_SCALING_MUX_2] = TABLA_A_MBHC_SCALING_MUX_2__POR,
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 50dede5..d4e9ecf 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -122,8 +122,15 @@
 	u8 nbounce_wait;
 };
 
+struct tabla_reg_address {
+	u16 micb_4_ctl;
+	u16 micb_4_int_rbias;
+	u16 micb_4_mbhc;
+};
+
 struct tabla_priv {
 	struct snd_soc_codec *codec;
+	struct tabla_reg_address reg_addr;
 	u32 mclk_freq;
 	u32 adc_count;
 	u32 cfilt1_cnt;
@@ -594,7 +601,6 @@
 	SOC_SINGLE("MICBIAS1 CAPLESS Switch", TABLA_A_MICB_1_CTL, 4, 1, 1),
 	SOC_SINGLE("MICBIAS2 CAPLESS Switch", TABLA_A_MICB_2_CTL, 4, 1, 1),
 	SOC_SINGLE("MICBIAS3 CAPLESS Switch", TABLA_A_MICB_3_CTL, 4, 1, 1),
-	SOC_SINGLE("MICBIAS4 CAPLESS Switch", TABLA_A_MICB_4_CTL, 4, 1, 1),
 
 	SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 0, 100, tabla_get_anc_slot,
 		tabla_put_anc_slot),
@@ -679,6 +685,14 @@
 	tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
 };
 
+static const struct snd_kcontrol_new tabla_1_x_snd_controls[] = {
+	SOC_SINGLE("MICBIAS4 CAPLESS Switch", TABLA_1_A_MICB_4_CTL, 4, 1, 1),
+};
+
+static const struct snd_kcontrol_new tabla_2_higher_snd_controls[] = {
+	SOC_SINGLE("MICBIAS4 CAPLESS Switch", TABLA_2_A_MICB_4_CTL, 4, 1, 1),
+};
+
 static const char *rx_mix1_text[] = {
 	"ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
 		"RX5", "RX6", "RX7"
@@ -1545,8 +1559,9 @@
 		cfilt_sel_val = tabla->pdata->micbias.bias3_cfilt_sel;
 		micb_line = TABLA_MICBIAS3;
 		break;
-	case TABLA_A_MICB_4_CTL:
-		micb_int_reg = TABLA_A_MICB_4_INT_RBIAS;
+	case TABLA_1_A_MICB_4_CTL:
+	case TABLA_2_A_MICB_4_CTL:
+		micb_int_reg = tabla->reg_addr.micb_4_int_rbias;
 		cfilt_sel_val = tabla->pdata->micbias.bias4_cfilt_sel;
 		micb_line = TABLA_MICBIAS4;
 		break;
@@ -1815,7 +1830,7 @@
 }
 
 static void tabla_get_mbhc_micbias_regs(struct snd_soc_codec *codec,
-		struct mbhc_micbias_regs *micbias_regs)
+					struct mbhc_micbias_regs *micbias_regs)
 {
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
 	unsigned int cfilt;
@@ -1841,9 +1856,9 @@
 		break;
 	case TABLA_MICBIAS4:
 		cfilt = tabla->pdata->micbias.bias4_cfilt_sel;
-		micbias_regs->mbhc_reg = TABLA_A_MICB_4_MBHC;
-		micbias_regs->int_rbias = TABLA_A_MICB_4_INT_RBIAS;
-		micbias_regs->ctl_reg = TABLA_A_MICB_4_CTL;
+		micbias_regs->mbhc_reg = tabla->reg_addr.micb_4_mbhc;
+		micbias_regs->int_rbias = tabla->reg_addr.micb_4_int_rbias;
+		micbias_regs->ctl_reg = tabla->reg_addr.micb_4_ctl;
 		break;
 	default:
 		/* Should never reach here */
@@ -2066,10 +2081,6 @@
 		tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", TABLA_A_MICB_4_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_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),
@@ -2201,6 +2212,20 @@
 	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,
+			       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			       SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget tabla_2_higher_dapm_widgets[] = {
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", TABLA_2_A_MICB_4_CTL, 7,
+			       0, tabla_codec_enable_micbias,
+			       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			       SND_SOC_DAPM_POST_PMD),
+};
+
 static const struct snd_soc_dapm_route audio_i2s_map[] = {
 	{"RX_I2S_CLK", NULL, "CDC_CONN"},
 	{"SLIM RX1", NULL, "RX_I2S_CLK"},
@@ -2519,6 +2544,21 @@
 
 static int tabla_readable(struct snd_soc_codec *ssc, unsigned int reg)
 {
+	int i;
+	struct tabla *tabla_core = dev_get_drvdata(ssc->dev->parent);
+
+	if (TABLA_IS_1_X(tabla_core->version)) {
+		for (i = 0; i < ARRAY_SIZE(tabla_1_reg_readable); i++) {
+			if (tabla_1_reg_readable[i] == reg)
+				return 1;
+		}
+	} else {
+		for (i = 0; i < ARRAY_SIZE(tabla_2_reg_readable); i++) {
+			if (tabla_2_reg_readable[i] == reg)
+				return 1;
+		}
+	}
+
 	return tabla_reg_readable[reg];
 }
 
@@ -3283,7 +3323,8 @@
 			snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE1, 0x1, 0);
 	}
 
-	snd_soc_update_bits(codec, TABLA_A_MICB_4_MBHC, 0x3, tabla->micbias);
+	snd_soc_update_bits(codec, tabla->reg_addr.micb_4_mbhc, 0x3,
+			    tabla->micbias);
 
 	tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
@@ -3441,7 +3482,6 @@
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x0A);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x02);
-	snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
 	snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x81);
 	usleep_range(100, 100);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
@@ -3461,7 +3501,6 @@
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x0A);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x02);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x02);
-	snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x02);
 	snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x81);
 	usleep_range(100, 100);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x02);
@@ -3612,7 +3651,8 @@
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x78,
 			    btn_det->mbhc_nsc << 3);
 
-	snd_soc_update_bits(codec, TABLA_A_MICB_4_MBHC, 0x03, TABLA_MICBIAS2);
+	snd_soc_update_bits(codec, tabla->reg_addr.micb_4_mbhc, 0x03,
+			    TABLA_MICBIAS2);
 
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x02, 0x02);
 }
@@ -4418,8 +4458,8 @@
 		(pdata->micbias.bias2_cfilt_sel << 5));
 	snd_soc_update_bits(codec, TABLA_A_MICB_3_CTL, 0x60,
 		(pdata->micbias.bias3_cfilt_sel << 5));
-	snd_soc_update_bits(codec, TABLA_A_MICB_4_CTL, 0x60,
-		(pdata->micbias.bias4_cfilt_sel << 5));
+	snd_soc_update_bits(codec, tabla->reg_addr.micb_4_ctl, 0x60,
+			    (pdata->micbias.bias4_cfilt_sel << 5));
 
 	for (i = 0; i < 6; j++, i += 2) {
 		if (flag & (0x01 << i)) {
@@ -4478,7 +4518,6 @@
 	TABLA_REG_VAL(TABLA_A_MICB_1_INT_RBIAS, 0x24),
 	TABLA_REG_VAL(TABLA_A_MICB_2_INT_RBIAS, 0x24),
 	TABLA_REG_VAL(TABLA_A_MICB_3_INT_RBIAS, 0x24),
-	TABLA_REG_VAL(TABLA_A_MICB_4_INT_RBIAS, 0x24),
 
 	/* Tabla 1.1 HPH changes */
 	TABLA_REG_VAL(TABLA_A_RX_HPH_BIAS_PA, 0x57),
@@ -4517,14 +4556,22 @@
 };
 
 static const struct tabla_reg_mask_val tabla_2_0_reg_defaults[] = {
-
 	/* Tabla 2.0 MICBIAS changes */
 	TABLA_REG_VAL(TABLA_A_MICB_2_MBHC, 0x02),
 };
 
+static const struct tabla_reg_mask_val tabla_1_x_only_reg_2_0_defaults[] = {
+	TABLA_REG_VAL(TABLA_1_A_MICB_4_INT_RBIAS, 0x24),
+};
+
+static const struct tabla_reg_mask_val tabla_2_only_reg_2_0_defaults[] = {
+	TABLA_REG_VAL(TABLA_2_A_MICB_4_INT_RBIAS, 0x24),
+};
+
 static void tabla_update_reg_defaults(struct snd_soc_codec *codec)
 {
 	u32 i;
+	struct tabla *tabla_core = dev_get_drvdata(codec->dev->parent);
 
 	for (i = 0; i < ARRAY_SIZE(tabla_1_1_reg_defaults); i++)
 		snd_soc_write(codec, tabla_1_1_reg_defaults[i].reg,
@@ -4533,6 +4580,19 @@
 	for (i = 0; i < ARRAY_SIZE(tabla_2_0_reg_defaults); i++)
 		snd_soc_write(codec, tabla_2_0_reg_defaults[i].reg,
 				tabla_2_0_reg_defaults[i].val);
+
+	if (TABLA_IS_1_X(tabla_core->version)) {
+		for (i = 0; i < ARRAY_SIZE(tabla_1_x_only_reg_2_0_defaults);
+		     i++)
+			snd_soc_write(codec,
+				      tabla_1_x_only_reg_2_0_defaults[i].reg,
+				      tabla_1_x_only_reg_2_0_defaults[i].val);
+	} else {
+		for (i = 0; i < ARRAY_SIZE(tabla_2_only_reg_2_0_defaults); i++)
+			snd_soc_write(codec,
+				      tabla_2_only_reg_2_0_defaults[i].reg,
+				      tabla_2_only_reg_2_0_defaults[i].val);
+	}
 }
 
 static const struct tabla_reg_mask_val tabla_codec_reg_init_val[] = {
@@ -4556,7 +4616,6 @@
 	{TABLA_A_MICB_1_INT_RBIAS, 0x24, 0x24},
 	{TABLA_A_MICB_2_INT_RBIAS, 0x24, 0x24},
 	{TABLA_A_MICB_3_INT_RBIAS, 0x24, 0x24},
-	{TABLA_A_MICB_4_INT_RBIAS, 0x24, 0x24},
 
 	{TABLA_A_CDC_CONN_CLSG_CTL, 0x3C, 0x14},
 
@@ -4591,14 +4650,55 @@
 	{TABLA_A_CDC_TX10_MUX_CTL, 0x8, 0x0},
 };
 
+static const struct tabla_reg_mask_val tabla_1_x_codec_reg_init_val[] = {
+	/* Initialize mic biases to differential mode */
+	{TABLA_1_A_MICB_4_INT_RBIAS, 0x24, 0x24},
+};
+
+static const struct tabla_reg_mask_val tabla_2_higher_codec_reg_init_val[] = {
+	/* Initialize mic biases to differential mode */
+	{TABLA_2_A_MICB_4_INT_RBIAS, 0x24, 0x24},
+};
+
 static void tabla_codec_init_reg(struct snd_soc_codec *codec)
 {
 	u32 i;
+	struct tabla *tabla_core = dev_get_drvdata(codec->dev->parent);
 
 	for (i = 0; i < ARRAY_SIZE(tabla_codec_reg_init_val); i++)
 		snd_soc_update_bits(codec, tabla_codec_reg_init_val[i].reg,
 				tabla_codec_reg_init_val[i].mask,
 				tabla_codec_reg_init_val[i].val);
+	if (TABLA_IS_1_X(tabla_core->version)) {
+		for (i = 0; i < ARRAY_SIZE(tabla_1_x_codec_reg_init_val); i++)
+			snd_soc_update_bits(codec,
+					   tabla_1_x_codec_reg_init_val[i].reg,
+					   tabla_1_x_codec_reg_init_val[i].mask,
+					   tabla_1_x_codec_reg_init_val[i].val);
+	} else {
+		for (i = 0; i < ARRAY_SIZE(tabla_2_higher_codec_reg_init_val);
+		     i++)
+			snd_soc_update_bits(codec,
+				      tabla_2_higher_codec_reg_init_val[i].reg,
+				      tabla_2_higher_codec_reg_init_val[i].mask,
+				      tabla_2_higher_codec_reg_init_val[i].val);
+	}
+}
+
+static void tabla_update_reg_address(struct tabla_priv *priv)
+{
+	struct tabla *tabla_core = dev_get_drvdata(priv->codec->dev->parent);
+	struct tabla_reg_address *reg_addr = &priv->reg_addr;
+
+	if (TABLA_IS_1_X(tabla_core->version)) {
+		reg_addr->micb_4_ctl = TABLA_1_A_MICB_4_CTL;
+		reg_addr->micb_4_int_rbias = TABLA_1_A_MICB_4_INT_RBIAS;
+		reg_addr->micb_4_int_rbias = TABLA_1_A_MICB_4_INT_RBIAS;
+	} else if (TABLA_IS_2_0(tabla_core->version)) {
+		reg_addr->micb_4_ctl = TABLA_2_A_MICB_4_CTL;
+		reg_addr->micb_4_int_rbias = TABLA_2_A_MICB_4_INT_RBIAS;
+		reg_addr->micb_4_int_rbias = TABLA_2_A_MICB_4_INT_RBIAS;
+	}
 }
 
 static int tabla_codec_probe(struct snd_soc_codec *codec)
@@ -4608,7 +4708,6 @@
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int ret = 0;
 	int i;
-	u8 tabla_version;
 
 	codec->control_data = dev_get_drvdata(codec->dev->parent);
 	control = codec->control_data;
@@ -4646,9 +4745,9 @@
 	atomic_set(&tabla->pm_cnt, 1);
 	init_waitqueue_head(&tabla->pm_wq);
 
+	tabla_update_reg_address(tabla);
 	tabla_update_reg_defaults(codec);
 	tabla_codec_init_reg(codec);
-
 	ret = tabla_handle_pdata(tabla);
 	if (IS_ERR_VALUE(ret)) {
 		pr_err("%s: bad pdata\n", __func__);
@@ -4656,9 +4755,23 @@
 	}
 
 	snd_soc_add_controls(codec, tabla_snd_controls,
-		ARRAY_SIZE(tabla_snd_controls));
+			     ARRAY_SIZE(tabla_snd_controls));
+	if (TABLA_IS_1_X(control->version))
+		snd_soc_add_controls(codec, tabla_1_x_snd_controls,
+				     ARRAY_SIZE(tabla_1_x_snd_controls));
+	else
+		snd_soc_add_controls(codec, tabla_2_higher_snd_controls,
+				     ARRAY_SIZE(tabla_2_higher_snd_controls));
+
 	snd_soc_dapm_new_controls(dapm, tabla_dapm_widgets,
-		ARRAY_SIZE(tabla_dapm_widgets));
+				  ARRAY_SIZE(tabla_dapm_widgets));
+	if (TABLA_IS_1_X(control->version))
+		snd_soc_dapm_new_controls(dapm, tabla_1_x_dapm_widgets,
+					  ARRAY_SIZE(tabla_1_x_dapm_widgets));
+	else
+		snd_soc_dapm_new_controls(dapm, tabla_2_higher_dapm_widgets,
+				    ARRAY_SIZE(tabla_2_higher_dapm_widgets));
+
 	if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
 		snd_soc_dapm_new_controls(dapm, tabla_dapm_i2s_widgets,
 			ARRAY_SIZE(tabla_dapm_i2s_widgets));
@@ -4667,24 +4780,15 @@
 	}
 	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-	tabla_version = snd_soc_read(codec, TABLA_A_CHIP_VERSION);
-	pr_info("%s : Tabla version reg 0x%2x\n", __func__,
-			(u32)tabla_version);
-
-	tabla_version &=  0x1F;
-	pr_info("%s : Tabla version %u\n", __func__, (u32)tabla_version);
-
-	if ((tabla_version == TABLA_VERSION_1_0) ||
-		(tabla_version == TABLA_VERSION_1_1)) {
+	if (TABLA_IS_1_X(control->version)) {
 		snd_soc_dapm_add_routes(dapm, tabla_1_x_lineout_2_to_4_map,
-			 ARRAY_SIZE(tabla_1_x_lineout_2_to_4_map));
-
-	} else if (tabla_version == TABLA_VERSION_2_0) {
+				      ARRAY_SIZE(tabla_1_x_lineout_2_to_4_map));
+	} else if (TABLA_IS_2_0(control->version)) {
 		snd_soc_dapm_add_routes(dapm, tabla_2_x_lineout_2_to_4_map,
-			 ARRAY_SIZE(tabla_2_x_lineout_2_to_4_map));
+				      ARRAY_SIZE(tabla_2_x_lineout_2_to_4_map));
 	} else  {
 		pr_err("%s : ERROR.  Unsupported Tabla version 0x%2x\n",
-				__func__, (u32)tabla_version);
+		       __func__, control->version);
 		goto err_pdata;
 	}
 
diff --git a/sound/soc/codecs/wcd9310.h b/sound/soc/codecs/wcd9310.h
index 6f77e9f..6ddc471 100644
--- a/sound/soc/codecs/wcd9310.h
+++ b/sound/soc/codecs/wcd9310.h
@@ -12,13 +12,11 @@
 #include <sound/soc.h>
 #include <sound/jack.h>
 
-#define TABLA_VERSION_1_0	0
-#define TABLA_VERSION_1_1	1
-#define TABLA_VERSION_2_0	2
-
 #define TABLA_NUM_REGISTERS 0x400
 #define TABLA_MAX_REGISTER (TABLA_NUM_REGISTERS-1)
 #define TABLA_CACHE_SIZE TABLA_NUM_REGISTERS
+#define TABLA_1_X_ONLY_REGISTERS 3
+#define TABLA_2_HIGHER_ONLY_REGISTERS 3
 
 #define TABLA_REG_VAL(reg, val)		{reg, 0, val}
 
@@ -35,6 +33,8 @@
 				SND_JACK_BTN_6 | SND_JACK_BTN_7)
 
 extern const u8 tabla_reg_readable[TABLA_CACHE_SIZE];
+extern const u32 tabla_1_reg_readable[TABLA_1_X_ONLY_REGISTERS];
+extern const u32 tabla_2_reg_readable[TABLA_2_HIGHER_ONLY_REGISTERS];
 extern const u8 tabla_reg_defaults[TABLA_CACHE_SIZE];
 
 enum tabla_micbias_num {
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 96260ab..27a27ec 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -420,6 +420,7 @@
 	switch (dai->id) {
 	case PRIMARY_I2S_TX:
 	case PRIMARY_I2S_RX:
+	case SECONDARY_I2S_RX:
 		rc = msm_dai_q6_cdc_hw_params(params, dai, substream->stream);
 		break;
 	case MI2S_RX:
@@ -820,6 +821,7 @@
 	case PRIMARY_I2S_TX:
 	case PRIMARY_I2S_RX:
 	case MI2S_RX:
+	case SECONDARY_I2S_RX:
 		rc = msm_dai_q6_cdc_set_fmt(dai, fmt);
 		break;
 	default:
@@ -1086,6 +1088,7 @@
 
 	switch (pdev->id) {
 	case PRIMARY_I2S_RX:
+	case SECONDARY_I2S_RX:
 		rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_rx_dai);
 		break;
 	case PRIMARY_I2S_TX:
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 1331ebf..94ed504 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -118,6 +118,7 @@
 	{ VOICE_RECORD_RX, 0, NULL, 0, 0},
 	{ VOICE_RECORD_TX, 0, NULL, 0, 0},
 	{ MI2S_RX, 0, NULL, 0, 0},
+	{ SECONDARY_I2S_RX, 0, NULL, 0, 0},
 };
 
 
@@ -668,6 +669,21 @@
 	msm_routing_put_audio_mixer),
 };
 
+static const struct snd_kcontrol_new sec_i2s_rx_mixer_controls[] = {
+	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SEC_I2S_RX ,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+
 static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
 	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
 	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -824,6 +840,15 @@
 	msm_routing_put_voice_mixer),
 };
 
+static const struct snd_kcontrol_new sec_i2s_rx_voice_mixer_controls[] = {
+	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+};
+
 static const struct snd_kcontrol_new slimbus_rx_voice_mixer_controls[] = {
 	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SLIMBUS_0_RX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
@@ -1134,6 +1159,8 @@
 	/* Stream name equals to backend dai link stream name
 	 */
 	SND_SOC_DAPM_AIF_OUT("PRI_I2S_RX", "Primary I2S Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("SEC_I2S_RX", "Secondary I2S Playback",
+				0, 0, 0 , 0),
 	SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("HDMI", "HDMI Playback", 0, 0, 0 , 0),
 	SND_SOC_DAPM_AIF_OUT("MI2S_RX", "MI2S Playback", 0, 0, 0, 0),
@@ -1166,6 +1193,8 @@
 	/* Mixer definitions */
 	SND_SOC_DAPM_MIXER("PRI_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 	pri_i2s_rx_mixer_controls, ARRAY_SIZE(pri_i2s_rx_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SEC_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
+	sec_i2s_rx_mixer_controls, ARRAY_SIZE(sec_i2s_rx_mixer_controls)),
 	SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 	slimbus_rx_mixer_controls, ARRAY_SIZE(slimbus_rx_mixer_controls)),
 	SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0,
@@ -1186,6 +1215,10 @@
 	SND_SOC_DAPM_MIXER("PRI_RX_Voice Mixer",
 				SND_SOC_NOPM, 0, 0, pri_rx_voice_mixer_controls,
 				ARRAY_SIZE(pri_rx_voice_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SEC_RX_Voice Mixer",
+				SND_SOC_NOPM, 0, 0,
+				sec_i2s_rx_voice_mixer_controls,
+				ARRAY_SIZE(sec_i2s_rx_voice_mixer_controls)),
 	SND_SOC_DAPM_MIXER("SLIM_0_RX_Voice Mixer",
 				SND_SOC_NOPM, 0, 0,
 				slimbus_rx_voice_mixer_controls,
@@ -1230,6 +1263,12 @@
 	{"PRI_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"PRI_I2S_RX", NULL, "PRI_RX Audio Mixer"},
 
+	{"SEC_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
+	{"SEC_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
+	{"SEC_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
+	{"SEC_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+	{"SEC_I2S_RX", NULL, "SEC_RX Audio Mixer"},
+
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
@@ -1295,6 +1334,10 @@
 	{"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"PRI_I2S_RX", NULL, "PRI_RX_Voice Mixer"},
 
+	{"SEC_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"SEC_RX_Voice Mixer", "Voip", "VOIP_DL"},
+	{"SEC_I2S_RX", NULL, "SEC_RX_Voice Mixer"},
+
 	{"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index a8d2d91..25efb58 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.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
@@ -29,6 +29,7 @@
 #define LPASS_BE_VOICE_PLAYBACK_TX "(Backend) VOICE_PLAYBACK_TX"
 #define LPASS_BE_INCALL_RECORD_RX "(Backend) INCALL_RECORD_TX"
 #define LPASS_BE_INCALL_RECORD_TX "(Backend) INCALL_RECORD_RX"
+#define LPASS_BE_SEC_I2S_RX "(Backend) SECONDARY_I2S_RX"
 
 #define LPASS_BE_MI2S_RX "(Backend) MI2S_RX"
 
@@ -71,6 +72,7 @@
 	MSM_BACKEND_DAI_INCALL_RECORD_RX,
 	MSM_BACKEND_DAI_INCALL_RECORD_TX,
 	MSM_BACKEND_DAI_MI2S_RX,
+	MSM_BACKEND_DAI_SEC_I2S_RX,
 	MSM_BACKEND_DAI_MAX,
 };