Merge "msm: 8064: Fix the valid master id limit" into msm-3.0
diff --git a/AndroidKernel.mk b/AndroidKernel.mk
index dcb81d7..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),)
 
@@ -8,6 +9,29 @@
 KERNEL_HEADERS_INSTALL := $(KERNEL_OUT)/usr
 KERNEL_MODULES_INSTALL := system
 KERNEL_MODULES_OUT := $(TARGET_OUT)/lib/modules
+KERNEL_IMG=$(KERNEL_OUT)/arch/arm/boot/Image
+
+MSM_ARCH ?= $(shell $(PERL) -e 'while (<>) {$$a = $$1 if /CONFIG_ARCH_((?:MSM|QSD)[a-zA-Z0-9]+)=y/; $$r = $$1 if /CONFIG_MSM_SOC_REV_(?!NONE)(\w+)=y/;} print lc("$$a$$r\n");' $(KERNEL_CONFIG))
+KERNEL_USE_OF ?= $(shell $(PERL) -e '$$of = "n"; while (<>) { if (/CONFIG_USE_OF=y/) { $$of = "y"; break; } } print $$of;' kernel/arch/arm/configs/$(KERNEL_DEFCONFIG))
+
+ifeq "$(KERNEL_USE_OF)" "y"
+KERNEL_ZIMG = $(KERNEL_OUT)/arch/arm/boot/zImage
+DTB_FILE = $(KERNEL_OUT)/arch/arm/boot/$(MSM_ARCH).dtb
+DTS_FILE = $(KERNEL_OUT)/../../../../../../kernel/arch/arm/boot/dts/$(MSM_ARCH).dts
+FULL_KERNEL = $(KERNEL_OUT)/arch/arm/boot/$(MSM_ARCH)-zImage
+DTC = $(KERNEL_OUT)/scripts/dtc/dtc
+
+define append-dtb
+md $(KERNEL_OUT)/arch/arm/boot;\
+$(DTC) -p 1024 -O dtb -o $(DTB_FILE) $(DTS_FILE);\
+cat $(KERNEL_ZIMG) $(DTB_FILE) > $(FULL_KERNEL)
+endef
+else
+FULL_KERNEL = $(KERNEL_IMG)
+
+define append-dtb
+endef
+endif
 
 ifeq ($(TARGET_USES_UNCOMPRESSED_KERNEL),true)
 $(info Using uncompressed kernel)
@@ -47,6 +71,7 @@
 	$(MAKE) -C kernel O=../$(KERNEL_OUT) INSTALL_MOD_PATH=../../$(KERNEL_MODULES_INSTALL) ARCH=arm CROSS_COMPILE=arm-eabi- modules_install
 	$(mv-modules)
 	$(clean-module-folder)
+	$(append-dtb)
 
 $(KERNEL_HEADERS_INSTALL): $(KERNEL_OUT) $(KERNEL_CONFIG)
 	$(MAKE) -C kernel O=../$(KERNEL_OUT) ARCH=arm CROSS_COMPILE=arm-eabi- headers_install
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/Documentation/arm/msm/tspp.txt b/Documentation/arm/msm/tspp.txt
new file mode 100644
index 0000000..a56f014
--- /dev/null
+++ b/Documentation/arm/msm/tspp.txt
@@ -0,0 +1,250 @@
+Introduction
+============
+The TSPP (Transport stream packet processor) is a hardware accelerator
+designed to process MPEG2 TS (transport stream) data. It is mainly used for
+broadcast terrestrial services to off-load the host CPU from real-time
+sensitive TS processing for high bandwidth streams (~20Mbps). Data is received
+either via TSIF (Transport stream interface) or system memory.
+The TSPP driver manages the TSIF 12Seg HW core, which consists of a TSPP, a
+BAM (Bus access manager, used for DMA) and two TSIF inputs.
+It is applicable to the TSIF 12Seg core found on select Qualcomm MSM chips.
+
+For more information on the TSIF interface, please refer to TSIF documentation
+(Documentation/arm/msm/tsif.txt).
+For more information on the BAM interface, please refer to SPS documentation
+(Documentation/dma/sps/sps_architecture.txt).
+
+Hardware description
+====================
+The TSPP unit expands the capabilities of the TSIF interface by adding MPEG2
+stream processing such as:
+	- Elementary Stream PID filtering and de-multiplexing
+	- Several TSP processing operation modes:
+		- TSP Raw processing (with or w/o suffix)
+		- TSP PES assembly
+	- Error handling
+	- Multi2 decryption
+
+    +-------------+  +------+
+  +>|ARM subsystem|  |Memory|
+  | +-------------+  +------+
+  |        |            |
+ I|        |            |
+ R|  ========================== System bus
+ Q|             |
+ s|             |  TSIF 12Seg
+  | +-----------------------+
+  | |  +---+                |
+  | |  |BAM|                |
+  | |  +---+                |  GPIOs
+  | |    |        +------+--|-------- TSIF 0 clk
+  | |  +----+     |TSIF 0|--|-------- TSIF 0 data
+  +-|  |    |-----+------+--|-------- TSIF 0 en
+    |  |TSPP|               |
+    |  |    |-----+------+--|-------- TSIF 1 clk
+    |  +----+     |TSIF 1|--|-------- TSIF 1 data
+    |             +------+--|-------- TSIF 1 en
+    +-----------------------+
+
+   The TSPP unit receives an MPEG2 transport stream either via the two TSIF
+	interfaces, or via system memory.
+   It uses the BAM interface to transfer data to and from system memory.
+   The ARM subsystem receives interrupts on various error conditions from TSPP
+   and TSIF units, and on data transfer events from the BAM.
+
+Software Description
+====================
+The TSPP driver is responsible for:
+ - TSPP/TSIF hardware configuration (using SPS driver to configure BAM
+   hardware)
+ - TSIF GPIO/Clocks configuration
+ - Memory resource management
+ - Handling TSIF/TSPP interrupts and BAM events
+ - TSPP Power management
+
+TSPP Terminology
+----------------
+Device - the TSPP hardware instance
+  - the device contains many streams
+Stream: All data that is received from a particular TS packet source
+  - For example, MPEG2 Transport Stream from TSIF0
+  - A stream can consist of many channels
+Channel: A channel routes part of a stream to a specified memory location
+  - For example, video and audio can be routed to different memory locations
+    using different channels
+  - Channel contents are defined by filters
+Filter: Enables TS packet filtering and routing according to PID (packet ID)
+  - The decision regarding which PIDs in the stream will be routed to a
+    channel is done via filters
+  - Several filters can be registered to the same channel
+  - Filters can pass TS packets as-is (Raw mode) or assemble them into PES
+    packets (PES mode)
+  - Groups of contiguous PIDs can be filtered together (i.e. PSI/SI 0x0-0x2F,
+    1Seg PMTs 0x1FC8-0x1FCF)
+  - Filters can be used to discard packets (e.g. eliminate processing of
+    unwanted channels)
+
+Init flow:
+----------
+Driver registers BAM (via SPS driver) and initializes TSIF/TSPP hardware.
+
+Control path:
+-------------
+1. Client opens a TSPP stream and channel
+2. Client notifies the driver of the source stream (TSIF0/TSIF1/Memory)
+  - TSPP driver allocates memory for the channel (circular buffer)
+  - As the amount of memory varies according to stream bandwidth (which the
+    driver doesn't know), a client can hint to the driver about the required
+	 memory or stream bandwidth
+  - TSPP driver configures TSIF/BAM hardware according to selected stream
+3. Client notifies the driver to filter a set of PIDs for the selected channel
+  - TSPP driver configures TSPP hardware filters accordingly
+4. Client can now read data received from the selected channel
+
+Optional: Scrambling keys can be configured for a filter to decrypt Multi2
+encrypted streams.  The scrambling keys are received encrypted in-stream every
+~2 seconds. The client uses a smart card and master key to decrypt the
+received scrambling keys.  The master key remains inside the smart card and is
+never revealed to software.
+
+Conceptual flow:
+Client                  TSPP Driver                 SPS Driver         Hardware
+ |                           |                           |                   |
+ |                           | Init TSIF/TSPP            |                   |
+ |                           |---------------------------|------------------>|
+ |                           | Register BAM              |                   |
+ |                           |-------------------------->|                   |
+ |                           |                           |                   |
+ | open(tspp.5)              |                           |                   |
+ |-------------------------->|                           |                   |
+ | ioctl(tspp.5,SOURCE,TSIF0)|                           |                   |
+ |-------------------------->|                           |                   |
+ |                           | buff[0..N] = alloc()      |                   |
+ |                           |---------->                |                   |
+ |                           | Connect(TSPP,MEM)         |                   |
+ |                           |-------------------------->|                   |
+ |                           | Transfer(buff[0..N])      |                   |
+ |                           |-------------------------->|                   |
+ |                           |                           |                   |
+ |                           | Configure TSIF0           |                   |
+ |                           |---------------------------|------------------>|
+ |                           |                           |                   |
+ | ioctl(tspp.5,FILTER,pid)  |                           |                   |
+ |-------------------------->|                           |                   |
+ |                           | Configure TSPP filters    |                   |
+ |                           |---------------------------|------------------>|
+ |                           |                           |                   |
+ |                           |                           |               INT |
+ |                           |                           |<------------------|
+ |                           |       notify(EOT,buff[x]) |                   |
+ |                           |<--------------------------|                   |
+ |                           | Transfer(buff[y])         |                   |
+ |                           |-------------------------->|                   |
+ |                           |                           |                   |
+ | read(tspp.5)              |                           |                   |
+ |-------------------------->|                           |                   |
+ |                           |                           |                   |
+
+
+Data path:
+----------
+The TSPP driver is not involved in data transfer, other than managing the
+circular buffer pointers when a transfer is complete.  Data loss can occur if
+a client cannot keep up with stream bandwidth.
+The driver does not notify the application if there is data loss.  It is
+assumed that the application will read data when the data is ready, and when
+the application is able.
+
+API
+===
+int tspp_open_stream(tspp_device *dev, void *stream, void *channel, tspp_mode
+	mode);
+int tspp_close_stream(tspp_device *dev, void *stream);
+int tspp_open_channel(tspp_device *dev, int dest, int bufsize, void *channel);
+int tspp_close_channel(tspp_device *dev, void *channel);
+int tspp_register_filter(tspp_device *dev, void *channel, tspp_filter *filter);
+int tspp_unregister_filter(tspp_device *dev, void *channel, int pid);
+
+Refer to chrdev implementation in kernel/drivers/misc/tspp.c for an example of
+how to use this api.
+
+Each stream is represented by a chrdev device
+16 available devices: /dev/tspp00 - /dev/tspp15
+Each device implements these functions:
+open()
+close()
+read()
+ioctl()
+
+ioctl() contains several sub-functions:
+0: select source
+1: add filter
+2: remove filter
+3: set decryption keys
+4: set initial cbc values (IV)
+5: set system keys
+6: set buffer size
+
+You can refer to include/linux/tspp.h for the details on the structures
+associated with these IOCTL calls.
+
+Design
+======
+Design is based on the existing TSIF driver, with added control functionality
+for the extra hardware features.
+
+Power Management
+===============
+TSPP driver prevents MSM from sleeping while TSPP hardware is active.
+To achieve this, the driver holds the wake lock.  When no channels are
+configured to receive data, the driver stops the clocks to save power.
+It will register for suspend/resume in the future.
+
+SMP/multi-core
+==============
+Driver is fully SMP aware.
+
+Performance
+===========
+Control flows are rare.
+Data path only involves maintaining the circular buffer pointers.
+
+Interface
+=========
+Driver exposes a char device interface to user-space for each channel.
+Control transactions are performed via ioctl on the channel. Data is read as
+any regular char device (blocking and non-blocking).  Please see sequence
+under software description for more info.
+
+Debugfs may be used for debug purposes.  Through debugfs, all of the TSIF
+registers can be accessed under /sys/kernel/debug/tsif0 and tsif1.  The
+TSPP registers are found under /sys/kernel/debug/tspp0.  If you cannot
+see these devices, then either the driver has been built without debugfs
+support (check the define TSPP_USE_DEBUGFS in tspp.c) or the debugfs has
+not been mounted correctly (or mounted in a different location).
+
+Driver Parameters
+=================
+TSPP driver has target-specific parameters:
+- Memory base addresses for TSIF/TSPP/BAM
+- TSIF/TSPP/BAM IRQ numbers
+- TSIF GPIO numbers
+
+Config Options
+==============
+To enable the driver, set CONFIG_TSPP (=y or =m) in the appropriate
+config file for the platform.
+
+Dependencies
+============
+The TSPP driver depends on the SPS driver to configure BAM hardware.
+
+User space utilities
+====================
+The TSPP test suite can be found in:
+vendor/qcom/proprietary/kernel-tests/tspp
+
+Known Issues
+============
+Currently PES processing mode cannot be configured for streams in which the PES
+length is 0. This is a HW limitation.
diff --git a/Documentation/devicetree/bindings/spmi/msm-spmi.txt b/Documentation/devicetree/bindings/spmi/msm-spmi.txt
new file mode 100644
index 0000000..fa91514
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/msm-spmi.txt
@@ -0,0 +1,72 @@
+* SPMI
+
+The spmi Device Tree support interprets up to two levels of Device Tree
+topology. The first level is required and specifies only a slave address.
+The second level is optional and allows for the specification of different
+offsets within the same 16-bit address space underneath a particular SPMI
+slave ID. Within the second level, any number of address ranges can be
+associated with a particular device within that 16-bit range.
+
+First level
+
+Required properites :
+
+ - reg: SPMI Slave ID (0-15) with no size cell.
+ - compatible : "qcom," prefixed string to match against the driver.
+
+Recommended properties :
+
+ - interrupts : <a b c> where a is the slave ID, b is the peripheral ID,
+   c is the device interrupt number (0-7). Each device supports any arbitrary
+   number of interrupts.
+ - interrupt-parent : the phandle for the interrupt controller that
+   services interrupts for this device.
+
+Second level
+
+Required properties :
+ - spmi-dev-container: Used by the parser to understand that this is the second
+   level of the tree.
+ - reg: <a b> where a is < 65536 and b is a size. Each device supports an
+   arbitrary number of address ranges.
+ - compatible : "qcom," prefixed string to match against the driver.
+
+Recommended properties :
+
+ - interrupts : <a b c> where a is the slave ID, b is is the peripheral ID,
+   c is the device interrupt number (0-7). Each device supports any arbitrary
+   number of interrupts.
+ - interrupt-parent : the phandle for the interrupt controller that
+   services interrupts for this device.
+
+Example:
+
+/ {
+	qcom,spmi@fc4c0000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-parent = <&qpnpint>;
+		pmic8941@d {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0xd>;
+			spmi-dev-container;
+
+			coincell@2800 {
+				compatible = "qcom,qpnp-coincell";
+				reg = <0x2800 0x4000>;
+				interrupts = <0xd 0x28 0x6  0xd 0x28 0x3>;
+
+			};
+			pon@800 {
+				compatible = "qcom,qpnp-pon";
+				reg = <0x800 0x4000>;
+			};
+		};
+		customer_dev@2 {
+			compatible = "qcom,qpnp-pon";
+			reg = <0x2>;
+			interrupts = <0x2 0x08 0x1  0x2 0x8 0x3>;
+		};
+	};
+};
diff --git a/Documentation/genlock.txt b/Documentation/genlock.txt
index d3a44e2..6f24a76 100644
--- a/Documentation/genlock.txt
+++ b/Documentation/genlock.txt
@@ -82,15 +82,13 @@
 Release a handle.
 
 * struct genlock * genlock_create_lock(struct genlock_handle *)
-Create a new lock and attach it to the handle.
+Create a new lock and attach it to the handle.  Once a lock is attached to a
+handle it stays attached until the handle is destroyed.
 
 * struct genlock * genlock_attach_lock(struct genlock_handle *handle, int fd)
 Given a valid file descriptor, get the lock associated with it and attach it to
 the handle.
 
-* void genlock_release_lock(struct genlock_handle *)
-Release a lock attached to a handle.
-
 * int genlock_lock(struct genlock_handle *, int op, int flags, u32 timeout)
 Lock or unlock the lock attached to the handle. A zero timeout value will
 be treated just like if the GENOCK_NOBLOCK flag is passed; if the lock
@@ -155,7 +153,4 @@
 -EINVAL if a zero timeout is passed, or -ETIMEDOUT if the timeout expires.
 
 * GENLOCK_IOC_RELEASE
-Use this to release an existing lock. This is useful if you wish to attach a
-different lock to the same handle. You do not need to call this under normal
-circumstances; when the handle is closed the reference to the lock is released.
-No data is passed from the user for this ioctl.
+This ioctl has been deprecated.  Do not use.
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/boot/dts/msmcopper.dts b/arch/arm/boot/dts/msmcopper.dts
index b00237a..57ad77a 100644
--- a/arch/arm/boot/dts/msmcopper.dts
+++ b/arch/arm/boot/dts/msmcopper.dts
@@ -10,26 +10,33 @@
 	intc: interrupt-controller@F9000000 {
 		compatible = "qcom,msm-qgic2";
 		interrupt-controller;
-		#interrupt-cells = <1>;
+		#interrupt-cells = <3>;
 		reg = <0xF9000000 0x1000>,
 		      <0xF9002000 0x1000>;
 	};
 
+	msmgpio: gpio@fd400000 {
+		compatible = "qcom,msm-gpio";
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		reg = <0xfd400000 0x4000>;
+	};
+
 	timer {
 		compatible = "qcom,msm-qtimer";
-		interrupts = <18>;
+		interrupts = <1 2 0>;
 	};
 
 	serial@F991F000 {
 		compatible = "qcom,msm-lsuart-v14";
 		reg = <0xF991F000 0x1000>;
-		interrupts = <109>;
+		interrupts = <0 109 0>;
 	};
 
 	usb@F9A55000 {
 		compatible = "qcom,hsusb-otg";
 		reg = <0xF9A55000 0x400>;
-		interrupts = <134>;
+		interrupts = <0 134 0>;
 
 		qcom,hsusb-otg-phy-type = <2>;
 		qcom,hsusb-otg-mode = <1>;
@@ -40,7 +47,7 @@
 		cell-index = <1>;
 		compatible = "qcom,msm-sdcc";
 		reg = <0xF980B000 0x1000>;
-		interrupts = <123>;
+		interrupts = <0 123 0>;
 
 		qcom,sdcc-clk-rates = <400000 24000000 48000000>;
 		qcom,sdcc-sup-voltages = <3300 3300>;
@@ -53,7 +60,7 @@
 		cell-index = <3>;
 		compatible = "qcom,msm-sdcc";
 		reg = <0xF984B000 0x1000>;
-		interrupts = <127>;
+		interrupts = <0 127 0>;
 
 		qcom,sdcc-clk-rates = <400000 24000000 48000000>;
 		qcom,sdcc-sup-voltages = <3300 3300>;
@@ -65,7 +72,7 @@
 		compatible = "qcom,msm_sps";
 		reg = <0xF9984000 0x15000>,
 		      <0xF9999000 0xB000>;
-		interrupts = <94>;
+		interrupts = <0 94 0>;
 
 		qcom,bam-dma-res-pipes = <6>;
 	};
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 0455878..bb4d971 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -65,6 +65,7 @@
 	u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
 	u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
 	u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
+	u32 saved_dist_pri[DIV_ROUND_UP(1020, 4)];
 	u32 __percpu *saved_ppi_enable;
 	u32 __percpu *saved_ppi_conf;
 #endif
@@ -79,6 +80,10 @@
 
 static DEFINE_RAW_SPINLOCK(irq_controller_lock);
 
+#ifdef CONFIG_CPU_PM
+static unsigned int saved_dist_ctrl, saved_cpu_ctrl;
+#endif
+
 /* Address of GIC 0 CPU interface */
 void __iomem *gic_cpu_base_addr __read_mostly;
 
@@ -151,6 +156,26 @@
 	return d->hwirq;
 }
 
+#ifdef CONFIG_CPU_V7
+static const inline bool is_cpu_secure(void)
+{
+	unsigned int dscr;
+
+	asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (dscr));
+
+	/* BIT(18) - NS bit; 1 = NS; 0 = S */
+	if (BIT(18) & dscr)
+		return false;
+	else
+		return true;
+}
+#else
+static const inline bool is_cpu_secure(void)
+{
+	return false;
+}
+#endif
+
 /*
  * Routines to acknowledge, disable and enable interrupts
  */
@@ -506,6 +531,14 @@
 		writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
 
 	/*
+	 * Set NS/S.
+	 */
+	if (is_cpu_secure())
+		for (i = 32; i < gic_irqs; i += 32)
+			writel_relaxed(0xFFFFFFFF,
+					base + GIC_DIST_ISR + i * 4 / 32);
+
+	/*
 	 * Set priority on all global interrupts.
 	 */
 	for (i = 32; i < gic_irqs; i += 4)
@@ -537,7 +570,11 @@
 
 	gic->max_irq = gic_irqs;
 
-	writel_relaxed(1, base + GIC_DIST_CTRL);
+	if (is_cpu_secure())
+		writel_relaxed(3, base + GIC_DIST_CTRL);
+	else
+		writel_relaxed(1, base + GIC_DIST_CTRL);
+
 	mb();
 }
 
@@ -554,6 +591,10 @@
 	writel_relaxed(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
 	writel_relaxed(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
 
+	/* Set NS/S */
+	if (is_cpu_secure())
+		writel_relaxed(0xFFFFFFFF, dist_base + GIC_DIST_ISR);
+
 	/*
 	 * Set priority on PPI and SGI interrupts
 	 */
@@ -561,7 +602,11 @@
 		writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
 
 	writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
-	writel_relaxed(1, base + GIC_CPU_CTRL);
+
+	if (is_cpu_secure())
+		writel_relaxed(0xF, base + GIC_CPU_CTRL);
+	else
+		writel_relaxed(1, base + GIC_CPU_CTRL);
     mb();
 }
 
@@ -587,6 +632,8 @@
 	if (!dist_base)
 		return;
 
+	saved_dist_ctrl = readl_relaxed(dist_base + GIC_DIST_CTRL);
+
 	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
 		gic_data[gic_nr].saved_spi_conf[i] =
 			readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
@@ -595,6 +642,10 @@
 		gic_data[gic_nr].saved_spi_target[i] =
 			readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
 
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+		gic_data[gic_nr].saved_dist_pri[i] =
+			readl_relaxed(dist_base + GIC_DIST_PRI + i * 4);
+
 	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
 		gic_data[gic_nr].saved_spi_enable[i] =
 			readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
@@ -629,7 +680,7 @@
 			dist_base + GIC_DIST_CONFIG + i * 4);
 
 	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
-		writel_relaxed(0xa0a0a0a0,
+		writel_relaxed(gic_data[gic_nr].saved_dist_pri[i],
 			dist_base + GIC_DIST_PRI + i * 4);
 
 	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
@@ -640,7 +691,7 @@
 		writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
 			dist_base + GIC_DIST_ENABLE_SET + i * 4);
 
-	writel_relaxed(1, dist_base + GIC_DIST_CTRL);
+	writel_relaxed(saved_dist_ctrl, dist_base + GIC_DIST_CTRL);
 }
 
 static void gic_cpu_save(unsigned int gic_nr)
@@ -659,6 +710,12 @@
 	if (!dist_base || !cpu_base)
 		return;
 
+	saved_cpu_ctrl = readl_relaxed(cpu_base + GIC_CPU_CTRL);
+
+	for (i = 0; i < DIV_ROUND_UP(32, 4); i++)
+		gic_data[gic_nr].saved_dist_pri[i] = readl_relaxed(dist_base +
+							GIC_DIST_PRI + i * 4);
+
 	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
 	for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
 		ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
@@ -694,10 +751,11 @@
 		writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);
 
 	for (i = 0; i < DIV_ROUND_UP(32, 4); i++)
-		writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4);
+		writel_relaxed(gic_data[gic_nr].saved_dist_pri[i],
+			dist_base + GIC_DIST_PRI + i * 4);
 
 	writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
-	writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
+	writel_relaxed(saved_cpu_ctrl, cpu_base + GIC_CPU_CTRL);
 }
 
 static int gic_notifier(struct notifier_block *self, unsigned long cmd,	void *v)
@@ -884,12 +942,17 @@
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 {
 	int cpu;
+	unsigned long sgir;
 	unsigned long map = 0;
 
 	/* Convert our logical CPU mask into a physical one. */
 	for_each_cpu(cpu, mask)
 		map |= 1 << cpu_logical_map(cpu);
 
+	sgir = (map << 16) | irq;
+	if (is_cpu_secure())
+		sgir |= (1 << 15);
+
 	/*
 	 * Ensure that stores to Normal memory are visible to the
 	 * other CPUs before issuing the IPI.
@@ -897,11 +960,40 @@
 	dsb();
 
 	/* this always happens on GIC0 */
-	writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
+	writel_relaxed(sgir,
+			gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
 	mb();
 }
 #endif
 
+void gic_set_irq_secure(unsigned int irq)
+{
+	unsigned int gicd_isr_reg, gicd_pri_reg;
+	unsigned int mask = 0xFFFFFF00;
+	struct gic_chip_data *gic_data = &gic_data[0];
+	struct irq_data *d = irq_get_irq_data(irq);
+
+	if (is_cpu_secure()) {
+		raw_spin_lock(&irq_controller_lock);
+		gicd_isr_reg = readl_relaxed(gic_dist_base(d) +
+				GIC_DIST_ISR + gic_irq(d) / 32 * 4);
+		gicd_isr_reg &= ~BIT(gic_irq(d) % 32);
+		writel_relaxed(gicd_isr_reg, gic_dist_base(d) +
+				GIC_DIST_ISR + gic_irq(d) / 32 * 4);
+		/* Also increase the priority of that irq */
+		gicd_pri_reg = readl_relaxed(gic_dist_base(d) +
+					GIC_DIST_PRI + (gic_irq(d) * 4 / 4));
+		gicd_pri_reg &= mask;
+		gicd_pri_reg |= 0x80; /* Priority of 0x80 > 0xA0 */
+		writel_relaxed(gicd_pri_reg, gic_dist_base(d) + GIC_DIST_PRI +
+				gic_irq(d) * 4 / 4);
+		mb();
+		raw_spin_unlock(&irq_controller_lock);
+	} else {
+		WARN(1, "Trying to run secure operation from Non-secure mode");
+	}
+}
+
 /* before calling this function the interrupts should be disabled
  * and the irq must be disabled at gic to avoid spurious interrupts */
 bool gic_is_spi_pending(unsigned int irq)
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index d69305c..a708fbc 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -1,6 +1,7 @@
 CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CGROUPS=y
@@ -32,6 +33,7 @@
 CONFIG_ARCH_MSMCOPPER=y
 CONFIG_MSM_KRAIT_TBB_ABORT_HANDLER=y
 # CONFIG_MSM_STACKED_MEMORY is not set
+CONFIG_KERNEL_PMEM_EBI_REGION=y
 CONFIG_CPU_HAS_L2_PMU=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
 # CONFIG_MSM_PROC_COMM is not set
@@ -98,6 +100,8 @@
 # CONFIG_BATTERY_MSM is not set
 # CONFIG_HWMON is not set
 # CONFIG_MFD_SUPPORT is not set
+CONFIG_ION=y
+CONFIG_ION_MSM=y
 # CONFIG_HID_SUPPORT is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_CI13XXX_MSM=y
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 00ff580..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
@@ -295,6 +296,7 @@
 CONFIG_MMC_MSM_CARD_HW_DETECTION=y
 CONFIG_MMC_MSM_SDC3_SUPPORT=y
 CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT=y
+CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_MSM_PDM=y
 CONFIG_SWITCH=y
 CONFIG_SWITCH_GPIO=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/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index cc9a1b7..b71df28 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -332,7 +332,7 @@
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
 CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
-CONFIG_MSM_KGSL_PAGE_TABLE_COUNT=16
+CONFIG_MSM_KGSL_PAGE_TABLE_COUNT=24
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
 CONFIG_FB_MSM=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index eb34964..9fd7e71 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -332,7 +332,7 @@
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
 CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
-CONFIG_MSM_KGSL_PAGE_TABLE_COUNT=16
+CONFIG_MSM_KGSL_PAGE_TABLE_COUNT=24
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
 CONFIG_FB_MSM=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 0780d20..eca2ffa 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -49,6 +49,9 @@
 CONFIG_MACH_MSM8627_MTP=y
 CONFIG_MACH_APQ8064_SIM=y
 CONFIG_MACH_APQ8064_RUMI3=y
+CONFIG_MACH_APQ8064_CDP=y
+CONFIG_MACH_APQ8064_MTP=y
+CONFIG_MACH_APQ8064_LIQUID=y
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_KERNEL_PMEM_EBI_REGION=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
@@ -63,6 +66,7 @@
 CONFIG_MSM_PIL_QDSP6V4=y
 CONFIG_MSM_PIL_RIVA=y
 CONFIG_MSM_PIL_TZAPPS=y
+CONFIG_MSM_PIL_GSS=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_MODEM_8960=y
 CONFIG_MSM_LPASS_8960=y
@@ -188,6 +192,8 @@
 CONFIG_IP6_NF_MANGLE=y
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_CLS_FW=y
 CONFIG_NET_CLS_U32=y
 CONFIG_CLS_U32_MARK=y
 CONFIG_NET_CLS_FLOW=y
@@ -249,8 +255,10 @@
 CONFIG_MSM_RMNET_BAM=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
 CONFIG_KEYBOARD_PMIC8XXX=y
 CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_XPAD=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MXT=y
 CONFIG_TOUCHSCREEN_CYTTSP_I2C=y
@@ -286,6 +294,7 @@
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8960=y
 CONFIG_THERMAL_PM8XXX=y
+CONFIG_THERMAL_MONITOR=y
 CONFIG_MFD_PM8921_CORE=y
 CONFIG_MFD_PM8821_CORE=y
 CONFIG_MFD_PM8038_CORE=y
@@ -303,6 +312,7 @@
 CONFIG_MSM_CAMERA_FLASH_SC628A=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_ACTUATOR=y
+CONFIG_S5K3L1YX=y
 CONFIG_MSM_GEMINI=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
@@ -310,7 +320,7 @@
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
 CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
-CONFIG_MSM_KGSL_PAGE_TABLE_COUNT=16
+CONFIG_MSM_KGSL_PAGE_TABLE_COUNT=24
 CONFIG_FB=y
 CONFIG_FB_VIRTUAL=y
 CONFIG_FB_MSM=y
@@ -319,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
@@ -427,6 +437,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 bd92fe3..18e9085 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -49,6 +49,9 @@
 CONFIG_MACH_MSM8627_MTP=y
 CONFIG_MACH_APQ8064_SIM=y
 CONFIG_MACH_APQ8064_RUMI3=y
+CONFIG_MACH_APQ8064_CDP=y
+CONFIG_MACH_APQ8064_MTP=y
+CONFIG_MACH_APQ8064_LIQUID=y
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_KERNEL_PMEM_EBI_REGION=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
@@ -63,6 +66,7 @@
 CONFIG_MSM_PIL_QDSP6V4=y
 CONFIG_MSM_PIL_RIVA=y
 CONFIG_MSM_PIL_TZAPPS=y
+CONFIG_MSM_PIL_GSS=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_MODEM_8960=y
 CONFIG_MSM_LPASS_8960=y
@@ -252,8 +256,10 @@
 CONFIG_MSM_RMNET_BAM=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
 CONFIG_KEYBOARD_PMIC8XXX=y
 CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_XPAD=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MXT=y
 CONFIG_TOUCHSCREEN_CYTTSP_I2C=y
@@ -289,6 +295,7 @@
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8960=y
 CONFIG_THERMAL_PM8XXX=y
+CONFIG_THERMAL_MONITOR=y
 CONFIG_MFD_PM8921_CORE=y
 CONFIG_MFD_PM8821_CORE=y
 CONFIG_MFD_PM8038_CORE=y
@@ -306,6 +313,7 @@
 CONFIG_MSM_CAMERA_FLASH_SC628A=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_ACTUATOR=y
+CONFIG_S5K3L1YX=y
 CONFIG_MSM_GEMINI=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
@@ -313,7 +321,7 @@
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
 CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
-CONFIG_MSM_KGSL_PAGE_TABLE_COUNT=16
+CONFIG_MSM_KGSL_PAGE_TABLE_COUNT=24
 CONFIG_FB=y
 CONFIG_FB_VIRTUAL=y
 CONFIG_FB_MSM=y
@@ -322,9 +330,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
@@ -425,6 +433,7 @@
 CONFIG_LOCKUP_DETECTOR=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_TIMER_STATS=y
+CONFIG_SLUB_DEBUG_ON=y
 CONFIG_DEBUG_KMEMLEAK=y
 CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
 # CONFIG_DEBUG_PREEMPT is not set
@@ -443,6 +452,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/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index d34f5df..543a4f9f 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -47,12 +47,13 @@
 # CONFIG_MSM_SYSMON_COMM is not set
 CONFIG_MSM_MODEM_8960=y
 CONFIG_MSM_LPASS_8960=y
+CONFIG_MSM_RPM_LOG=y
+CONFIG_MSM_RPM_STATS_LOG=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_MSM_BUS_SCALING=y
 CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y
 CONFIG_MSM_WATCHDOG=y
 CONFIG_MSM_DLOAD_MODE=y
-# CONFIG_MSM_JTAG_V7 is not set
 CONFIG_SWP_EMULATE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -73,6 +74,8 @@
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
 # CONFIG_INET_XFRM_MODE_TRANSPORT is not set
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
@@ -83,7 +86,62 @@
 # CONFIG_INET6_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET6_XFRM_MODE_BEET is not set
 # CONFIG_IPV6_SIT is not set
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
 # CONFIG_ANDROID_PARANOID_NETWORK is not set
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+CONFIG_NETFILTER_NETLINK_QUEUE=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NETFILTER_XT_MARK=y
+CONFIG_NETFILTER_XT_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_IP_SET=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_IP_NF_TARGET_ULOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_ECN=y
+CONFIG_IP_NF_TARGET_TTL=y
+CONFIG_IP_NF_RAW=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_AH=y
+CONFIG_IP6_NF_MATCH_FRAG=y
+CONFIG_IP6_NF_MATCH_OPTS=y
+CONFIG_IP6_NF_MATCH_HL=y
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+CONFIG_IP6_NF_MATCH_MH=y
+CONFIG_IP6_NF_MATCH_RT=y
+CONFIG_IP6_NF_TARGET_LOG=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
 CONFIG_CFG80211=y
 CONFIG_MTD=y
 CONFIG_MTD_TESTS=m
@@ -137,6 +195,8 @@
 CONFIG_SLIMBUS_MSM_CTRL=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_BATTERY_MSM is not set
 CONFIG_SENSORS_PM8XXX_ADC=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8960=y
@@ -168,8 +228,6 @@
 CONFIG_USB_G_ANDROID=y
 CONFIG_RMNET_SMD_CTL_CHANNEL="DATA36_CNTL"
 CONFIG_RMNET_SMD_DATA_CHANNEL="DATA36"
-CONFIG_POWER_SUPPLY=y
-# CONFIG_BATTERY_MSM is not set
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_UNSAFE_RESUME=y
@@ -230,5 +288,3 @@
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
-CONFIG_MSM_RPM_LOG=y
-CONFIG_MSM_RPM_STATS_LOG=y
diff --git a/arch/arm/include/asm/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/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 8bfbcfa..5bb5139 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -22,6 +22,7 @@
 
 #define GIC_DIST_CTRL			0x000
 #define GIC_DIST_CTR			0x004
+#define GIC_DIST_ISR			0x080
 #define GIC_DIST_ENABLE_SET		0x100
 #define GIC_DIST_ENABLE_CLEAR		0x180
 #define GIC_DIST_PENDING_SET		0x200
@@ -49,6 +50,7 @@
 void gic_enable_ppi(unsigned int);
 bool gic_is_spi_pending(unsigned int irq);
 void gic_clear_spi_pending(unsigned int irq);
+void gic_set_irq_secure(unsigned int irq);
 
 static inline void gic_init(unsigned int nr, int start,
 			    void __iomem *dist , void __iomem *cpu)
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 761c29e..c3b841a 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -27,6 +27,7 @@
 #include <asm/byteorder.h>
 #include <asm/memory.h>
 #include <asm/system.h>
+#include <mach/msm_rtb.h>
 
 /*
  * ISA I/O bus memory addresses are 1:1 with the physical address.
@@ -47,13 +48,85 @@
 extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
 extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
 
-#define __raw_writeb(v,a)	(__chk_io_ptr(a), *(volatile unsigned char __force  *)(a) = (v))
-#define __raw_writew(v,a)	(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v))
-#define __raw_writel(v,a)	(__chk_io_ptr(a), *(volatile unsigned int __force   *)(a) = (v))
+/*
+ * There may be cases when clients don't want to support or can't support the
+ * logging. The appropriate functions can be used but clients should carefully
+ * consider why they can't support the logging.
+ */
 
-#define __raw_readb(a)		(__chk_io_ptr(a), *(volatile unsigned char __force  *)(a))
-#define __raw_readw(a)		(__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
-#define __raw_readl(a)		(__chk_io_ptr(a), *(volatile unsigned int __force   *)(a))
+#define __raw_writeb_no_log(v, a)	(__chk_io_ptr(a), *(volatile unsigned char __force  *)(a) = (v))
+#define __raw_writew_no_log(v, a)	(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v))
+#define __raw_writel_no_log(v, a)	(__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v))
+
+#define __raw_writeb(v, a)	({ \
+	int _ret; \
+	void *_addr = (void *)(a); \
+	_ret = uncached_logk(LOGK_WRITEL, _addr); \
+	ETB_WAYPOINT; \
+	__raw_writeb_no_log(v, _addr); \
+	if (_ret) \
+		LOG_BARRIER; \
+	})
+
+#define __raw_writew(v, a)	({ \
+	int _ret; \
+	void *_addr = (void *)(a); \
+	_ret = uncached_logk(LOGK_WRITEL, _addr); \
+	ETB_WAYPOINT; \
+	__raw_writew_no_log(v, _addr); \
+	if (_ret) \
+		LOG_BARRIER; \
+	})
+
+#define __raw_writel(v, a)	({ \
+	int _ret; \
+	void *_addr = (void *)(a); \
+	_ret = uncached_logk(LOGK_WRITEL, _addr); \
+	ETB_WAYPOINT; \
+	__raw_writel_no_log(v, _addr); \
+	if (_ret) \
+		LOG_BARRIER; \
+	})
+
+#define __raw_readb_no_log(a)		(__chk_io_ptr(a), *(volatile unsigned char __force  *)(a))
+#define __raw_readw_no_log(a)		(__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
+#define __raw_readl_no_log(a)		(__chk_io_ptr(a), *(volatile unsigned int __force *)(a))
+
+#define __raw_readb(a)		({ \
+	unsigned char __a; \
+	void *_addr = (void *)(a); \
+	int _ret; \
+	_ret = uncached_logk(LOGK_READL, _addr); \
+	ETB_WAYPOINT; \
+	__a = __raw_readb_no_log(_addr);\
+	if (_ret) \
+		LOG_BARRIER; \
+	__a; \
+	})
+
+#define __raw_readw(a)		({ \
+	unsigned short __a; \
+	void *_addr = (void *)(a); \
+	int _ret; \
+	_ret = uncached_logk(LOGK_READL, _addr); \
+	ETB_WAYPOINT; \
+	__a = __raw_readw_no_log(_addr);\
+	if (_ret) \
+		LOG_BARRIER; \
+	__a; \
+	})
+
+#define __raw_readl(a)		({ \
+	unsigned int __a; \
+	void *_addr = (void *)(a); \
+	int _ret; \
+	_ret = uncached_logk(LOGK_READL, _addr); \
+	ETB_WAYPOINT; \
+	__a = __raw_readl_no_log(_addr);\
+	if (_ret) \
+		LOG_BARRIER; \
+	__a; \
+	})
 
 /*
  * Architecture ioremap implementation.
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index b44f46f..bd6df88 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -21,7 +21,7 @@
 	const char		**dt_compat;	/* array of device tree
 						 * 'compatible' strings	*/
 
-	unsigned int		nr_irqs;	/* number of IRQs */
+	int			nr_irqs;	/* number of IRQs */
 
 	unsigned int		video_start;	/* start of video RAM	*/
 	unsigned int		video_end;	/* end of video RAM	*/
diff --git a/arch/arm/include/asm/mach/mmc.h b/arch/arm/include/asm/mach/mmc.h
index 75ec143..3dfb62f 100644
--- a/arch/arm/include/asm/mach/mmc.h
+++ b/arch/arm/include/asm/mach/mmc.h
@@ -152,6 +152,7 @@
 	bool disable_bam;
 	bool disable_runtime_pm;
 	bool disable_cmd23;
+	u32 swfi_latency;
 };
 
 #endif
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 4468153..7561081 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -134,8 +134,18 @@
 #ifdef CONFIG_SPARSE_IRQ
 int __init arch_probe_nr_irqs(void)
 {
-	nr_irqs = machine_desc->nr_irqs ? machine_desc->nr_irqs : NR_IRQS;
-	return nr_irqs;
+	/*
+	 * machine_desc->nr_irqs < 0 is a special case that
+	 * specifies not to preallocate any irq_descs.
+	 */
+	if (machine_desc->nr_irqs < 0) {
+		nr_irqs = 0;
+		return nr_irqs;
+	} else {
+		nr_irqs = machine_desc->nr_irqs ?
+			  machine_desc->nr_irqs : NR_IRQS;
+		return nr_irqs;
+	}
 }
 #endif
 
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..4a8e276 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, IRQ_TYPE_EDGE_RISING);
 }
-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/kernel/smp.c b/arch/arm/kernel/smp.c
index 4328ac3..ea64ba6 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -468,9 +468,7 @@
 static void ipi_timer(void)
 {
 	struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
-	irq_enter();
 	evt->event_handler(evt);
-	irq_exit();
 }
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
@@ -624,7 +622,9 @@
 		/* Wake up from WFI/WFE using SGI */
 		break;
 	case IPI_TIMER:
+		irq_enter();
 		ipi_timer();
+		irq_exit();
 		break;
 
 	case IPI_RESCHEDULE:
@@ -632,15 +632,21 @@
 		break;
 
 	case IPI_CALL_FUNC:
+		irq_enter();
 		generic_smp_call_function_interrupt();
+		irq_exit();
 		break;
 
 	case IPI_CALL_FUNC_SINGLE:
+		irq_enter();
 		generic_smp_call_function_single_interrupt();
+		irq_exit();
 		break;
 
 	case IPI_CPU_STOP:
+		irq_enter();
 		ipi_cpu_stop(cpu);
+		irq_exit();
 		break;
 
 	case IPI_CPU_BACKTRACE:
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 9df90cd..f087fbc 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,8 @@
 	select MSM_SPM_V1
 	select MSM_SCM if SMP
 	select MULTI_IRQ_HANDLER
+	select MSM_MULTIMEDIA_USE_ION
+	select MSM_PM8X60 if PM
 
 config ARCH_MSM8960
 	bool "MSM8960"
@@ -159,6 +166,7 @@
 	select QCACHE
 	select MSM_MULTIMEDIA_USE_ION
 	select MULTI_IRQ_HANDLER
+	select MSM_PM8X60 if PM
 
 config ARCH_MSM8930
 	bool "MSM8930"
@@ -170,6 +178,7 @@
 	select MSM_SCM if SMP
 	select MSM_DIRECT_SCLK_ACCESS
 	select REGULATOR
+	select MSM_RPM_REGULATOR
 	select MSM_RPM
 	select MSM_XO
 	select MSM_QDSP6_APR
@@ -194,11 +203,11 @@
 	select FIX_MOVABLE_ZONE
 	select MSM_ULTRASOUND
 	select MULTI_IRQ_HANDLER
+	select MSM_PM8X60 if PM
 
 config ARCH_APQ8064
 	bool "APQ8064"
 	select ARCH_MSM_KRAITMP
-	select MACH_APQ8064_SIM if !MACH_APQ8064_RUMI3
 	select MSM_V2_TLMM
 	select ARM_GIC
 	select CPU_V7
@@ -209,6 +218,10 @@
 	select MSM_QDSP6_APR
 	select MSM_AUDIO_QDSP6 if SND_SOC
 	select MULTI_IRQ_HANDLER
+	select MSM_RPM
+	select MSM_SPM_V2
+	select MSM_L2_SPM
+	select MSM_PM8X60 if PM
 
 config ARCH_MSMCOPPER
 	bool "MSM Copper"
@@ -219,6 +232,7 @@
 	select MSM_SCM if SMP
 	select MSM_GPIOMUX
 	select MULTI_IRQ_HANDLER
+	select MSM_MULTIMEDIA_USE_ION
 
 config ARCH_FSM9XXX
 	bool "FSM9XXX"
@@ -243,7 +257,17 @@
 	select REGULATOR
 	select MSM_RPM_REGULATOR
 	select MULTI_IRQ_HANDLER
+	select MSM_PM8X60 if PM
+	select MSM_XO
 
+config ARCH_MSM8625
+	bool "MSM8625"
+	select ARCH_MSM_CORTEX_A5
+	select CPU_V7
+	select MSM_GPIOMUX
+	select ARM_GIC
+	select ARCH_MSM_CORTEXMP
+	select MULTI_IRQ_HANDLER
 endmenu
 
 choice
@@ -293,6 +317,10 @@
 	select MSM_SMP
 	bool
 
+config  ARCH_MSM_CORTEXMP
+	select MSM_SMP
+	bool
+
 config  ARCH_MSM_CORTEX_A5
 	bool
 	select HAVE_HW_BRKPT_RESERVED_RW_ACCESS
@@ -302,6 +330,8 @@
 	select MSM_DALRPC
 	select MSM_PROC_COMM_REGULATOR
 	select MULTI_IRQ_HANDLER
+	select ARM_GIC
+	select ARCH_MSM_CORTEXMP
 
 config  MSM_VIC
 	bool
@@ -423,6 +453,22 @@
         help
           Support for the Qualcomm MSM7627A Refrence Design.
 
+config MACH_MSM7627A_EVB
+        depends on ARCH_MSM7X27A
+        depends on !MSM_STACKED_MEMORY
+        default y
+        bool "MSM7627A EVB"
+        help
+          Support for the Qualcomm MSM7627A Reference Design.
+
+config MACH_MSM8625_RUMI3
+	depends on ARCH_MSM8625
+	depends on !MSM_STACKED_MEMORY
+	default y
+	bool "MSM8625 RUMI3"
+	help
+	  Support for the Qualcomm MSM8625 RUMI3 Emulation Platform.
+
 config MACH_MSM7X30_SURF
        depends on ARCH_MSM7X30
        depends on !MSM_STACKED_MEMORY
@@ -675,6 +721,24 @@
 	help
 	  Support for the Qualcomm APQ8064 RUMI3 emulator.
 
+config MACH_APQ8064_CDP
+	depends on ARCH_APQ8064
+	bool "APQ8064 CDP"
+	help
+	  Support for the Qualcomm APQ8064 CDP device.
+
+config MACH_APQ8064_MTP
+	depends on ARCH_APQ8064
+	bool "APQ8064 MTP"
+	help
+	  Support for the Qualcomm APQ8064 MTP device.
+
+config MACH_APQ8064_LIQUID
+	depends on ARCH_APQ8064
+	bool "APQ8064 LIQUID"
+	help
+	  Support for the Qualcomm APQ8064 LIQUID device.
+
 config MACH_FSM9XXX_SURF
 	depends on ARCH_FSM9XXX
 	depends on !MSM_STACKED_MEMORY
@@ -712,7 +776,7 @@
 config KERNEL_PMEM_EBI_REGION
 	bool "Enable in-kernel PMEM region for EBI"
 	default y if ARCH_MSM8X60
-	depends on ANDROID_PMEM && (ARCH_MSM8X60 || ARCH_MSM8960)
+	depends on ANDROID_PMEM && (ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_MSMCOPPER)
 	help
 	   Enable the in-kernel PMEM allocator to use EBI memory.
 
@@ -1643,6 +1707,13 @@
 	  used to decrypt data and perform secure operations on the behalf of
 	  the kernel.
 
+config MSM_PIL_GSS
+	tristate "GSS (Coretx A5) Boot Support"
+	depends on MSM_PIL
+	help
+	  Support for booting and shutting down Cortex A5 processors which run
+	  GPS subsystem firmware.
+
 config MSM_SCM
 	bool "Secure Channel Manager (SCM) support"
 	default n
@@ -1788,6 +1859,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
@@ -1965,4 +2052,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 8b866d8..19a316e 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -71,6 +71,7 @@
 obj-$(CONFIG_MSM_PIL_RIVA) += pil-riva.o
 obj-$(CONFIG_MSM_PIL_TZAPPS) += pil-tzapps.o
 obj-$(CONFIG_MSM_PIL_MODEM) += pil-modem.o
+obj-$(CONFIG_MSM_PIL_GSS) += pil-gss.o
 obj-$(CONFIG_ARCH_QSD8X50) += sirc.o
 obj-$(CONFIG_ARCH_FSM9XXX) += sirc-fsm9xxx.o
 obj-$(CONFIG_MSM_FIQ_SUPPORT) += fiq_glue.o
@@ -140,20 +141,11 @@
 obj-$(CONFIG_MSM8X60_AUDIO) += qdsp6v2/
 obj-$(CONFIG_MSM_AUDIO_QDSP6) += qdsp6v2/
 obj-$(CONFIG_MSM_HW3D) += hw3d.o
-ifdef CONFIG_PM
-	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
@@ -179,6 +171,7 @@
 obj-$(CONFIG_ARCH_MSM8X60) += rpm-regulator-8660.o
 obj-$(CONFIG_ARCH_MSM8960) += rpm-regulator-8960.o
 obj-$(CONFIG_ARCH_MSM9615) += rpm-regulator-9615.o
+obj-$(CONFIG_ARCH_MSM8930) += rpm-regulator-8930.o
 endif
 
 ifdef CONFIG_MSM_SUBSYSTEM_RESTART
@@ -193,6 +186,7 @@
 obj-$(CONFIG_MSM_WCNSS_SSR_8960) += wcnss-ssr-8960.o
 
 ifdef CONFIG_CPU_IDLE
+	obj-$(CONFIG_ARCH_APQ8064) += cpuidle.o
 	obj-$(CONFIG_ARCH_MSM8960) += cpuidle.o
 	obj-$(CONFIG_ARCH_MSM8X60) += cpuidle.o
 	obj-$(CONFIG_ARCH_MSM9615) += cpuidle.o
@@ -219,10 +213,13 @@
 obj-$(CONFIG_MACH_MSM7X27_SURF) += board-msm7x27.o devices-msm7x27.o
 obj-$(CONFIG_MACH_MSM7X27_FFA) += board-msm7x27.o devices-msm7x27.o
 obj-$(CONFIG_ARCH_MSM7X27A) += clock-pcom-lookup.o devices-msm7x27a.o
-obj-$(CONFIG_MACH_MSM7X27A_RUMI3) += board-msm7x27a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o
-obj-$(CONFIG_MACH_MSM7X27A_SURF) += board-msm7x27a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o
-obj-$(CONFIG_MACH_MSM7X27A_FFA) += board-msm7x27a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o
-obj-$(CONFIG_MACH_MSM7627A_QRD1) += board-qrd7627a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o
+obj-$(CONFIG_MACH_MSM7X27A_RUMI3) += board-msm7x27a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
+obj-$(CONFIG_MACH_MSM7X27A_SURF) += board-msm7x27a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
+obj-$(CONFIG_MACH_MSM7X27A_FFA) += board-msm7x27a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
+obj-$(CONFIG_MACH_MSM7627A_QRD1) += board-qrd7627a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
+obj-$(CONFIG_MACH_MSM7627A_EVB) += board-qrd7627a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
+obj-$(CONFIG_ARCH_MSM8625) += devices-msm7x27a.o clock-pcom-lookup.o
+obj-$(CONFIG_MACH_MSM8625_RUMI3) += board-msm7x27a.o
 obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o memory_topology.o
 obj-$(CONFIG_ARCH_MSM7X30) += clock-local.o clock-7x30.o acpuclock-7x30.o
 obj-$(CONFIG_MACH_MSM7X25_SURF) += board-msm7x27.o devices-msm7x25.o
@@ -235,8 +232,8 @@
 obj-$(CONFIG_ARCH_MSM8960) += devices-8960.o
 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
-board-8064-all-objs += board-8064.o board-8064-pmic.o board-8064-storage.o board-8064-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-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
@@ -318,3 +315,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/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index bc15a01..7ac2d9f 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -17,6 +17,10 @@
    zreladdr-$(CONFIG_ARCH_MSM7X27A)	:= 0x00208000
 params_phys-$(CONFIG_ARCH_MSM7X27A)	:= 0x00200100
 
+# MSM8625
+   zreladdr-$(CONFIG_ARCH_MSM8625)	:= 0x00208000
+params_phys-$(CONFIG_ARCH_MSM8625)	:= 0x00200100
+
 # MSM7x30
    zreladdr-$(CONFIG_ARCH_MSM7X30)	:= 0x00208000
 params_phys-$(CONFIG_ARCH_MSM7X30)	:= 0x00200100
diff --git a/arch/arm/mach-msm/acpuclock-7201.c b/arch/arm/mach-msm/acpuclock-7201.c
index 23d03ef..6140559 100644
--- a/arch/arm/mach-msm/acpuclock-7201.c
+++ b/arch/arm/mach-msm/acpuclock-7201.c
@@ -369,34 +369,39 @@
 };
 
 #ifdef CONFIG_CPU_FREQ_MSM
-static struct cpufreq_frequency_table freq_table[20];
+static struct cpufreq_frequency_table freq_table[NR_CPUS][20];
 
 static void __init cpufreq_table_init(void)
 {
-	unsigned int i;
-	unsigned int freq_cnt = 0;
+	int cpu;
+	for_each_possible_cpu(cpu) {
+		unsigned int i, freq_cnt = 0;
 
-	/* Construct the freq_table table from acpu_freq_tbl since the
-	 * freq_table values need to match frequencies specified in
-	 * acpu_freq_tbl and acpu_freq_tbl needs to be fixed up during init.
-	 */
-	for (i = 0; acpu_freq_tbl[i].a11clk_khz != 0
-			&& freq_cnt < ARRAY_SIZE(freq_table)-1; i++) {
-		if (acpu_freq_tbl[i].use_for_scaling) {
-			freq_table[freq_cnt].index = freq_cnt;
-			freq_table[freq_cnt].frequency
-				= acpu_freq_tbl[i].a11clk_khz;
-			freq_cnt++;
+		/* Construct the freq_table table from acpu_freq_tbl since
+		 * the freq_table values need to match frequencies specified
+		 * in acpu_freq_tbl and acpu_freq_tbl needs to be fixed up
+		 * during init.
+		 */
+		for (i = 0; acpu_freq_tbl[i].a11clk_khz != 0
+				&& freq_cnt < ARRAY_SIZE(*freq_table)-1; i++) {
+			if (acpu_freq_tbl[i].use_for_scaling) {
+				freq_table[cpu][freq_cnt].index = freq_cnt;
+				freq_table[cpu][freq_cnt].frequency
+					= acpu_freq_tbl[i].a11clk_khz;
+				freq_cnt++;
+			}
 		}
+
+		/* freq_table not big enough to store all usable freqs. */
+		BUG_ON(acpu_freq_tbl[i].a11clk_khz != 0);
+
+		freq_table[cpu][freq_cnt].index = freq_cnt;
+		freq_table[cpu][freq_cnt].frequency = CPUFREQ_TABLE_END;
+		/* Register table with CPUFreq. */
+		cpufreq_frequency_table_get_attr(freq_table[cpu], cpu);
+		pr_info("CPU%d: %d scaling frequencies supported.\n",
+			cpu, freq_cnt);
 	}
-
-	/* freq_table not big enough to store all usable freqs. */
-	BUG_ON(acpu_freq_tbl[i].a11clk_khz != 0);
-
-	freq_table[freq_cnt].index = freq_cnt;
-	freq_table[freq_cnt].frequency = CPUFREQ_TABLE_END;
-
-	pr_info("%d scaling frequencies supported.\n", freq_cnt);
 }
 #endif
 
@@ -995,7 +1000,6 @@
 
 #ifdef CONFIG_CPU_FREQ_MSM
 	cpufreq_table_init();
-	cpufreq_frequency_table_get_attr(freq_table, smp_processor_id());
 #endif
 	return 0;
 }
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 87c5047..02b2c33 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -68,7 +68,8 @@
 #define STBY_KHZ		1
 
 #define HFPLL_NOMINAL_VDD	1050000
-#define HFPLL_LOW_VDD		 850000
+#define HFPLL_LOW_VDD_8960	 850000
+#define HFPLL_LOW_VDD		 945000
 #define HFPLL_LOW_VDD_PLL_L_MAX	0x28
 
 #define SECCLKAGD		BIT(4)
@@ -200,6 +201,9 @@
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8921_S3 },
+			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+					     RPM_VREG_VOTER1,
+					     RPM_VREG_ID_PM8921_LVS7 },
 		},
 	[CPU1] = {
 			.hfpll_base      = MSM_HFPLL_BASE + 0x240,
@@ -212,6 +216,9 @@
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_S3 },
+			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+					     RPM_VREG_VOTER2,
+					     RPM_VREG_ID_PM8921_LVS7 },
 		},
 	[CPU2] = {
 			.hfpll_base      = MSM_HFPLL_BASE + 0x280,
@@ -224,6 +231,9 @@
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER4,
 					     RPM_VREG_ID_PM8921_S3 },
+			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+					     RPM_VREG_VOTER4,
+					     RPM_VREG_ID_PM8921_LVS7 },
 		},
 	[CPU3] = {
 			.hfpll_base      = MSM_HFPLL_BASE + 0x2C0,
@@ -236,15 +246,20 @@
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER5,
 					     RPM_VREG_ID_PM8921_S3 },
+			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+					     RPM_VREG_VOTER5,
+					     RPM_VREG_ID_PM8921_LVS7 },
 		},
 	[L2] = {
 			.hfpll_base   = MSM_HFPLL_BASE    + 0x300,
 			.aux_clk_sel  = MSM_APCS_GCC_BASE + 0x028,
 			.l2cpmr_iaddr = L2CPMR_IADDR,
+			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+					     RPM_VREG_VOTER6,
+					     RPM_VREG_ID_PM8921_LVS7 },
 		},
 };
 
-/*TODO: Update the rpm vreg id when the rpm driver is ready */
 static struct scalable scalable_8930[] = {
 	[CPU0] = {
 			.hfpll_base      = MSM_HFPLL_BASE + 0x200,
@@ -253,16 +268,13 @@
 			.vreg[VREG_CORE] = { "krait0",     1300000 },
 			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
 					     RPM_VREG_VOTER1,
-					     RPM_VREG_ID_PM8921_L24 },
+					     RPM_VREG_ID_PM8038_L24 },
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER1,
-					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
-					     RPM_VREG_VOTER1,
-					     RPM_VREG_ID_PM8921_S8 },
+					     RPM_VREG_ID_PM8038_S1 },
 			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
 					     RPM_VREG_VOTER1,
-					     RPM_VREG_ID_PM8921_L23 },
+					     RPM_VREG_ID_PM8038_L23 },
 		},
 	[CPU1] = {
 			.hfpll_base      = MSM_HFPLL_BASE + 0x300,
@@ -271,27 +283,21 @@
 			.vreg[VREG_CORE] = { "krait1",     1300000 },
 			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
 					     RPM_VREG_VOTER2,
-					     RPM_VREG_ID_PM8921_L24 },
+					     RPM_VREG_ID_PM8038_L24 },
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER2,
-					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
-					     RPM_VREG_VOTER2,
-					     RPM_VREG_ID_PM8921_S8 },
+					     RPM_VREG_ID_PM8038_S1 },
 			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
 					     RPM_VREG_VOTER2,
-					     RPM_VREG_ID_PM8921_L23 },
+					     RPM_VREG_ID_PM8038_L23 },
 		},
 	[L2] = {
 			.hfpll_base   = MSM_HFPLL_BASE    + 0x400,
 			.aux_clk_sel  = MSM_APCS_GCC_BASE + 0x028,
 			.l2cpmr_iaddr = L2CPMR_IADDR,
-			.vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
-					     RPM_VREG_VOTER6,
-					     RPM_VREG_ID_PM8921_S8 },
 			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
 					     RPM_VREG_VOTER6,
-					     RPM_VREG_ID_PM8921_L23 },
+					     RPM_VREG_ID_PM8038_L23 },
 		},
 };
 
@@ -304,16 +310,13 @@
 			.vreg[VREG_CORE] = { "krait0",     1300000 },
 			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
 					     RPM_VREG_VOTER1,
-					     RPM_VREG_ID_PM8921_L24 },
+					     RPM_VREG_ID_PM8038_L24 },
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER1,
-					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
-					     RPM_VREG_VOTER1,
-					     RPM_VREG_ID_PM8921_S8 },
+					     RPM_VREG_ID_PM8038_S1 },
 			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
 					     RPM_VREG_VOTER1,
-					     RPM_VREG_ID_PM8921_L23 },
+					     RPM_VREG_ID_PM8038_L23 },
 		},
 	[CPU1] = {
 			.hfpll_base      = MSM_HFPLL_BASE + 0x300,
@@ -322,27 +325,21 @@
 			.vreg[VREG_CORE] = { "krait1",     1300000 },
 			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
 					     RPM_VREG_VOTER2,
-					     RPM_VREG_ID_PM8921_L24 },
+					     RPM_VREG_ID_PM8038_L24 },
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER2,
-					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
-					     RPM_VREG_VOTER2,
-					     RPM_VREG_ID_PM8921_S8 },
+					     RPM_VREG_ID_PM8038_S1 },
 			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
 					     RPM_VREG_VOTER2,
-					     RPM_VREG_ID_PM8921_L23 },
+					     RPM_VREG_ID_PM8038_L23 },
 		},
 	[L2] = {
 			.hfpll_base   = MSM_HFPLL_BASE    + 0x400,
 			.aux_clk_sel  = MSM_APCS_GCC_BASE + 0x028,
 			.l2cpmr_iaddr = L2CPMR_IADDR,
-			.vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
-					     RPM_VREG_VOTER6,
-					     RPM_VREG_ID_PM8921_S8 },
 			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
 					     RPM_VREG_VOTER6,
-					     RPM_VREG_ID_PM8921_L23 },
+					     RPM_VREG_ID_PM8038_L23 },
 		},
 };
 
@@ -481,12 +478,12 @@
 	{ 1, {  1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1175000 },
 	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1175000 },
 	{ 1, {  1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1200000 },
-	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(19), 1200000 },
-	{ 1, {  1296000, HFPLL, 1, 0, 0x30 }, L2(19), 1225000 },
-	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(19), 1225000 },
-	{ 1, {  1404000, HFPLL, 1, 0, 0x34 }, L2(19), 1237500 },
-	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(19), 1237500 },
-	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(19), 1250000 },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1200000 },
+	{ 1, {  1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1225000 },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1225000 },
+	{ 1, {  1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1237500 },
+	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(16), 1237500 },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(16), 1250000 },
 	{ 0, { 0 } }
 };
 
@@ -508,12 +505,12 @@
 	{ 1, {  1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1125000 },
 	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1125000 },
 	{ 1, {  1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1150000 },
-	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(19), 1150000 },
-	{ 1, {  1296000, HFPLL, 1, 0, 0x30 }, L2(19), 1175000 },
-	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(19), 1175000 },
-	{ 1, {  1404000, HFPLL, 1, 0, 0x34 }, L2(19), 1187500 },
-	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(19), 1187500 },
-	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(19), 1200000 },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1150000 },
+	{ 1, {  1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1175000 },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1175000 },
+	{ 1, {  1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1187500 },
+	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(16), 1187500 },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(16), 1200000 },
 	{ 0, { 0 } }
 };
 
@@ -535,12 +532,12 @@
 	{ 1, {  1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1075000 },
 	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1075000 },
 	{ 1, {  1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1100000 },
-	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(19), 1100000 },
-	{ 1, {  1296000, HFPLL, 1, 0, 0x30 }, L2(19), 1125000 },
-	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(19), 1125000 },
-	{ 1, {  1404000, HFPLL, 1, 0, 0x34 }, L2(19), 1137500 },
-	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(19), 1137500 },
-	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(19), 1150000 },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1100000 },
+	{ 1, {  1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1125000 },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1125000 },
+	{ 1, {  1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1137500 },
+	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(16), 1137500 },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(16), 1150000 },
 	{ 0, { 0 } }
 };
 
@@ -737,17 +734,21 @@
 }
 
 /* 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() || cpu_is_msm8930() || cpu_is_msm8627()) {
-		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);
+	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);
@@ -755,7 +756,6 @@
 			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);
 
@@ -778,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;
 
@@ -788,19 +788,23 @@
 	 */
 	writel_relaxed(0, sc->hfpll_base + HFPLL_MODE);
 
-	if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8627()) {
+	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_B].name, rc);
-		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);
+
+		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);
+		}
 	}
 }
 
@@ -864,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);
@@ -882,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
@@ -1026,9 +1030,12 @@
 		pll_vdd_dig = 0;
 	else if (tgt->l2_level->speed.pll_l_val > HFPLL_LOW_VDD_PLL_L_MAX)
 		pll_vdd_dig = HFPLL_NOMINAL_VDD;
-	else
-		pll_vdd_dig = HFPLL_LOW_VDD;
-
+	else {
+		if (cpu_is_msm8960())
+			pll_vdd_dig = HFPLL_LOW_VDD_8960;
+		else
+			pll_vdd_dig = HFPLL_LOW_VDD;
+	}
 	return max(tgt->l2_level->vdd_dig, pll_vdd_dig);
 }
 
@@ -1040,9 +1047,12 @@
 		pll_vdd_core = 0;
 	else if (tgt->speed.pll_l_val > HFPLL_LOW_VDD_PLL_L_MAX)
 		pll_vdd_core = HFPLL_NOMINAL_VDD;
-	else
-		pll_vdd_core = HFPLL_LOW_VDD;
-
+	else {
+		if (cpu_is_msm8960())
+			pll_vdd_core = HFPLL_LOW_VDD_8960;
+		else
+			pll_vdd_core = HFPLL_LOW_VDD;
+	}
 	return max(tgt->vdd_core, pll_vdd_core);
 }
 
@@ -1137,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);
@@ -1149,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;
@@ -1170,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"
@@ -1224,7 +1234,7 @@
 }
 
 /* Register with bus driver. */
-static void __init bus_init(void)
+static void __init bus_init(unsigned int init_bw)
 {
 	int ret;
 
@@ -1234,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);
 }
@@ -1439,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);
@@ -1459,3 +1470,7 @@
 struct acpuclk_soc_data acpuclk_8930_soc_data __initdata = {
 	.init = acpuclk_8960_init,
 };
+
+struct acpuclk_soc_data acpuclk_8064_soc_data __initdata = {
+	.init = acpuclk_8960_init,
+};
diff --git a/arch/arm/mach-msm/acpuclock.h b/arch/arm/mach-msm/acpuclock.h
index 6ea691b..ef6c359 100644
--- a/arch/arm/mach-msm/acpuclock.h
+++ b/arch/arm/mach-msm/acpuclock.h
@@ -2,7 +2,7 @@
  * MSM architecture CPU clock driver header
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2012, Code Aurora Forum. All rights reserved.
  * Author: San Mehat <san@android.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -109,5 +109,6 @@
 extern struct acpuclk_soc_data acpuclk_9xxx_soc_data;
 extern struct acpuclk_soc_data acpuclk_9615_soc_data;
 extern struct acpuclk_soc_data acpuclk_8930_soc_data;
+extern struct acpuclk_soc_data acpuclk_8064_soc_data;
 
 #endif
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 0e4c756..f1abde4 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -33,6 +33,7 @@
 #include <mach/msm_smsm.h>
 #include <mach/subsystem_notif.h>
 #include <mach/socinfo.h>
+#include <mach/subsystem_restart.h>
 
 #define BAM_CH_LOCAL_OPEN       0x1
 #define BAM_CH_REMOTE_OPEN      0x2
@@ -63,6 +64,7 @@
 static uint32_t bam_dmux_write_cpy_cnt;
 static uint32_t bam_dmux_write_cpy_bytes;
 static uint32_t bam_dmux_tx_sps_failure_cnt;
+static uint32_t bam_dmux_tx_stall_cnt;
 
 #define DBG(x...) do {		                 \
 		if (msm_bam_dmux_debug_enable)  \
@@ -96,12 +98,17 @@
 		bam_dmux_tx_sps_failure_cnt++;		\
 } while (0)
 
+#define DBG_INC_TX_STALL_CNT() do { \
+	bam_dmux_tx_stall_cnt++; \
+} while (0)
+
 #else
 #define DBG(x...) do { } while (0)
 #define DBG_INC_READ_CNT(x...) do { } while (0)
 #define DBG_INC_WRITE_CNT(x...) do { } while (0)
 #define DBG_INC_WRITE_CPY(x...) do { } while (0)
 #define DBG_INC_TX_SPS_FAILURE_CNT() do { } while (0)
+#define DBG_INC_TX_STALL_CNT() do { } while (0)
 #endif
 
 struct bam_ch_info {
@@ -158,6 +165,7 @@
 
 static LIST_HEAD(bam_rx_pool);
 static DEFINE_MUTEX(bam_rx_pool_mutexlock);
+static int bam_rx_pool_len;
 static LIST_HEAD(bam_tx_pool);
 static DEFINE_SPINLOCK(bam_tx_pool_spinlock);
 
@@ -199,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);
@@ -213,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 */
@@ -283,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',
@@ -294,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);
@@ -355,36 +367,78 @@
 {
 	void *ptr;
 	struct rx_pkt_info *info;
-
-	if (in_global_reset)
-		return;
-
-	info = kmalloc(sizeof(struct rx_pkt_info), GFP_KERNEL);
-	if (!info) {
-		pr_err("%s: unable to alloc rx_pkt_info\n", __func__);
-		return;
-	}
-
-	INIT_WORK(&info->work, handle_bam_mux_cmd);
-
-	info->skb = __dev_alloc_skb(BUFFER_SIZE, GFP_KERNEL);
-	if (info->skb == NULL) {
-		pr_err("%s: unable to alloc skb\n", __func__);
-		kfree(info);
-		return;
-	}
-	ptr = skb_put(info->skb, BUFFER_SIZE);
+	int ret;
+	int rx_len_cached;
 
 	mutex_lock(&bam_rx_pool_mutexlock);
-	list_add_tail(&info->list_node, &bam_rx_pool);
+	rx_len_cached = bam_rx_pool_len;
 	mutex_unlock(&bam_rx_pool_mutexlock);
 
-	/* need a way to handle error case */
-	info->dma_address = dma_map_single(NULL, ptr, BUFFER_SIZE,
-						DMA_FROM_DEVICE);
-	sps_transfer_one(bam_rx_pipe, info->dma_address,
-				BUFFER_SIZE, info,
-				SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
+	while (rx_len_cached < NUM_BUFFERS) {
+		if (in_global_reset)
+			goto fail;
+
+		info = kmalloc(sizeof(struct rx_pkt_info), GFP_KERNEL);
+		if (!info) {
+			pr_err("%s: unable to alloc rx_pkt_info\n", __func__);
+			goto fail;
+		}
+
+		INIT_WORK(&info->work, handle_bam_mux_cmd);
+
+		info->skb = __dev_alloc_skb(BUFFER_SIZE, GFP_KERNEL);
+		if (info->skb == NULL) {
+			DMUX_LOG_KERR("%s: unable to alloc skb\n", __func__);
+			goto fail_info;
+		}
+		ptr = skb_put(info->skb, BUFFER_SIZE);
+
+		info->dma_address = dma_map_single(NULL, ptr, BUFFER_SIZE,
+							DMA_FROM_DEVICE);
+		if (info->dma_address == 0 || info->dma_address == ~0) {
+			DMUX_LOG_KERR("%s: dma_map_single failure %p for %p\n",
+				__func__, (void *)info->dma_address, ptr);
+			goto fail_skb;
+		}
+
+		mutex_lock(&bam_rx_pool_mutexlock);
+		list_add_tail(&info->list_node, &bam_rx_pool);
+		rx_len_cached = ++bam_rx_pool_len;
+		mutex_unlock(&bam_rx_pool_mutexlock);
+
+		ret = sps_transfer_one(bam_rx_pipe, info->dma_address,
+			BUFFER_SIZE, info,
+			SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
+
+		if (ret) {
+			DMUX_LOG_KERR("%s: sps_transfer_one failed %d\n",
+				__func__, ret);
+			goto fail_transfer;
+		}
+	}
+	return;
+
+fail_transfer:
+	mutex_lock(&bam_rx_pool_mutexlock);
+	list_del(&info->list_node);
+	--bam_rx_pool_len;
+	rx_len_cached = bam_rx_pool_len;
+	mutex_unlock(&bam_rx_pool_mutexlock);
+
+	dma_unmap_single(NULL, info->dma_address, BUFFER_SIZE,
+				DMA_FROM_DEVICE);
+
+fail_skb:
+	dev_kfree_skb_any(info->skb);
+
+fail_info:
+	kfree(info);
+
+fail:
+	if (rx_len_cached == 0) {
+		DMUX_LOG_KERR("%s: RX queue failure\n", __func__);
+		in_global_reset = 1;
+	}
 }
 
 static void bam_mux_process_data(struct sk_buff *rx_skb)
@@ -551,16 +605,20 @@
 	INIT_WORK(&pkt->work, bam_mux_write_done);
 	spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
 	list_add_tail(&pkt->list_node, &bam_tx_pool);
-	spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
 	rc = sps_transfer_one(bam_tx_pipe, dma_address, len,
 				pkt, SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
 	if (rc) {
-		DBG("%s sps_transfer_one failed rc=%d\n", __func__, rc);
-		spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
+		DMUX_LOG_KERR("%s sps_transfer_one failed rc=%d\n",
+			__func__, rc);
 		list_del(&pkt->list_node);
 		DBG_INC_TX_SPS_FAILURE_CNT();
 		spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
+		dma_unmap_single(NULL, pkt->dma_address,
+					pkt->len,
+					DMA_TO_DEVICE);
 		kfree(pkt);
+	} else {
+		spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
 	}
 
 	ul_packet_written = 1;
@@ -662,6 +720,8 @@
 	if (!bam_is_connected) {
 		read_unlock(&ul_wakeup_lock);
 		ul_wakeup();
+		if (unlikely(in_global_reset == 1))
+			return -EFAULT;
 		read_lock(&ul_wakeup_lock);
 		notify_all(BAM_DMUX_UL_CONNECTED, (unsigned long)(NULL));
 	}
@@ -718,19 +778,21 @@
 	INIT_WORK(&pkt->work, bam_mux_write_done);
 	spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
 	list_add_tail(&pkt->list_node, &bam_tx_pool);
-	spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
 	rc = sps_transfer_one(bam_tx_pipe, dma_address, skb->len,
 				pkt, SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
 	if (rc) {
-		DBG("%s sps_transfer_one failed rc=%d\n", __func__, rc);
-		spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
+		DMUX_LOG_KERR("%s sps_transfer_one failed rc=%d\n",
+			__func__, rc);
 		list_del(&pkt->list_node);
 		DBG_INC_TX_SPS_FAILURE_CNT();
 		spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
+		dma_unmap_single(NULL, pkt->dma_address,
+					pkt->skb->len,	DMA_TO_DEVICE);
 		kfree(pkt);
 		if (new_skb)
 			dev_kfree_skb_any(new_skb);
 	} else {
+		spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
 		spin_lock_irqsave(&bam_ch[id].lock, flags);
 		bam_ch[id].num_tx_pkts++;
 		spin_unlock_irqrestore(&bam_ch[id].lock, flags);
@@ -800,6 +862,8 @@
 	if (!bam_is_connected) {
 		read_unlock(&ul_wakeup_lock);
 		ul_wakeup();
+		if (unlikely(in_global_reset == 1))
+			return -EFAULT;
 		read_lock(&ul_wakeup_lock);
 		notify_all(BAM_DMUX_UL_CONNECTED, (unsigned long)(NULL));
 	}
@@ -835,6 +899,8 @@
 	if (!bam_is_connected && !bam_ch_is_in_reset(id)) {
 		read_unlock(&ul_wakeup_lock);
 		ul_wakeup();
+		if (unlikely(in_global_reset == 1))
+			return -EFAULT;
 		read_lock(&ul_wakeup_lock);
 		notify_all(BAM_DMUX_UL_CONNECTED, (unsigned long)(NULL));
 	}
@@ -965,7 +1031,12 @@
 		info = list_first_entry(&bam_rx_pool, struct rx_pkt_info,
 							list_node);
 		list_del(&info->list_node);
+		--bam_rx_pool_len;
 		mutex_unlock(&bam_rx_pool_mutexlock);
+		if (info->dma_address != iov.addr)
+			DMUX_LOG_KERR("%s: iovec %p != dma %p\n",
+				__func__,
+				(void *)info->dma_address, (void *)iov.addr);
 		handle_bam_mux_cmd(&info->work);
 	}
 	return;
@@ -1004,6 +1075,7 @@
 			}
 			info = list_first_entry(&bam_rx_pool,
 					struct rx_pkt_info,	list_node);
+			--bam_rx_pool_len;
 			list_del(&info->list_node);
 			mutex_unlock(&bam_rx_pool_mutexlock);
 			handle_bam_mux_cmd(&info->work);
@@ -1124,10 +1196,14 @@
 	i += scnprintf(buf + i, max - i,
 			"skb copy cnt:    %u\n"
 			"skb copy bytes:  %u\n"
-			"sps tx failures: %u\n",
+			"sps tx failures: %u\n"
+			"sps tx stalls:   %u\n"
+			"rx queue len:    %d\n",
 			bam_dmux_write_cpy_cnt,
 			bam_dmux_write_cpy_bytes,
-			bam_dmux_tx_sps_failure_cnt
+			bam_dmux_tx_sps_failure_cnt,
+			bam_dmux_tx_stall_cnt,
+			bam_rx_pool_len
 			);
 
 	return i;
@@ -1156,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;
 	}
@@ -1281,6 +1358,8 @@
 	if (!bam_is_connected) {
 		read_unlock(&ul_wakeup_lock);
 		ul_wakeup();
+		if (unlikely(in_global_reset == 1))
+			return;
 		read_lock(&ul_wakeup_lock);
 		ul_packet_written = 1;
 		notify_all(BAM_DMUX_UL_CONNECTED, (unsigned long)(NULL));
@@ -1288,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)
@@ -1338,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;
@@ -1352,8 +1477,24 @@
 		return;
 	}
 	if (bam_is_connected) {
-		if (ul_packet_written) {
-			bam_dmux_log("%s: packet written\n", __func__);
+		if (!ul_packet_written) {
+			spin_lock(&bam_tx_pool_spinlock);
+			if (!list_empty(&bam_tx_pool)) {
+				struct tx_pkt_info *info;
+
+				info = list_first_entry(&bam_tx_pool,
+						struct tx_pkt_info, list_node);
+				DMUX_LOG_KERR("%s: UL delayed ts=%u.%09lu\n",
+					__func__, info->ts_sec, info->ts_nsec);
+				DBG_INC_TX_STALL_CNT();
+				ul_packet_written = 1;
+			}
+			spin_unlock(&bam_tx_pool_spinlock);
+		}
+
+		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));
@@ -1364,10 +1505,29 @@
 	write_unlock_irqrestore(&ul_wakeup_lock, flags);
 	ul_powerdown_finish();
 }
+
+static int ssrestart_check(void)
+{
+	/*
+	 * if the restart level is RESET_SOC, SSR is not on
+	 * so the crashed modem will end up crashing the system
+	 * anyways, so use BUG() to report the error
+	 * else prepare for the restart event which should
+	 * happen soon
+	 */
+	DMUX_LOG_KERR("%s: modem timeout\n", __func__);
+	if (get_restart_level() <= RESET_SOC) {
+		BUG();
+		return 0;
+	} else {
+		in_global_reset = 1;
+		return 1;
+	}
+}
+
 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 */
@@ -1381,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);
@@ -1407,17 +1567,29 @@
 		bam_dmux_log("%s waiting for previous ack\n", __func__);
 		ret = wait_for_completion_timeout(
 					&ul_wakeup_ack_completion, HZ);
-		BUG_ON(ret == 0);
 		wait_for_ack = 0;
+		if (unlikely(ret == 0) && ssrestart_check()) {
+			mutex_unlock(&wakeup_lock);
+			bam_dmux_log("%s timeout previous ack\n", __func__);
+			return;
+		}
 	}
 	INIT_COMPLETION(ul_wakeup_ack_completion);
 	power_vote(1);
 	bam_dmux_log("%s waiting for wakeup ack\n", __func__);
 	ret = wait_for_completion_timeout(&ul_wakeup_ack_completion, HZ);
-	BUG_ON(ret == 0);
+	if (unlikely(ret == 0) && ssrestart_check()) {
+		mutex_unlock(&wakeup_lock);
+		bam_dmux_log("%s timeout wakeup ack\n", __func__);
+		return;
+	}
 	bam_dmux_log("%s waiting completion\n", __func__);
 	ret = wait_for_completion_timeout(&bam_connection_completion, HZ);
-	BUG_ON(ret == 0);
+	if (unlikely(ret == 0) && ssrestart_check()) {
+		mutex_unlock(&wakeup_lock);
+		bam_dmux_log("%s timeout power on\n", __func__);
+		return;
+	}
 
 	bam_is_connected = 1;
 	bam_dmux_log("%s complete\n", __func__);
@@ -1453,8 +1625,7 @@
 	if (polling_mode)
 		rx_switch_to_interrupt_mode();
 
-	for (i = 0; i < NUM_BUFFERS; ++i)
-		queue_rx();
+	queue_rx();
 
 	toggle_apps_ack();
 	complete_all(&bam_connection_completion);
@@ -1495,6 +1666,7 @@
 		dev_kfree_skb_any(info->skb);
 		kfree(info);
 	}
+	bam_rx_pool_len = 0;
 	mutex_unlock(&bam_rx_pool_mutexlock);
 
 	verify_tx_queue_is_empty(__func__);
@@ -1588,9 +1760,15 @@
 		ul_powerdown();
 		wait_for_ack = 0;
 	}
+	/*
+	 * if modem crash during ul_wakeup(), power_vote is 1, needs to be
+	 * reset to 0.  harmless if bam_is_connected check above passes
+	 */
+	power_vote(0);
 	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) {
@@ -1638,7 +1816,7 @@
 	dma_addr_t dma_addr;
 	int ret;
 	void *a2_virt_addr;
-	int i;
+	int skip_iounmap = 0;
 
 	vote_dfab();
 	/* init BAM */
@@ -1669,7 +1847,7 @@
 	if (bam_tx_pipe == NULL) {
 		pr_err("%s: tx alloc endpoint failed\n", __func__);
 		ret = -ENOMEM;
-		goto register_bam_failed;
+		goto tx_alloc_endpoint_failed;
 	}
 	ret = sps_get_config(bam_tx_pipe, &tx_connection);
 	if (ret) {
@@ -1689,7 +1867,7 @@
 	if (tx_desc_mem_buf.base == NULL) {
 		pr_err("%s: tx memory alloc failed\n", __func__);
 		ret = -ENOMEM;
-		goto tx_mem_failed;
+		goto tx_get_config_failed;
 	}
 	tx_desc_mem_buf.phys_base = dma_addr;
 	memset(tx_desc_mem_buf.base, 0x0, tx_desc_mem_buf.size);
@@ -1706,7 +1884,7 @@
 	if (bam_rx_pipe == NULL) {
 		pr_err("%s: rx alloc endpoint failed\n", __func__);
 		ret = -ENOMEM;
-		goto tx_connect_failed;
+		goto rx_alloc_endpoint_failed;
 	}
 	ret = sps_get_config(bam_rx_pipe, &rx_connection);
 	if (ret) {
@@ -1763,8 +1941,7 @@
 	}
 
 	bam_mux_initialized = 1;
-	for (i = 0; i < NUM_BUFFERS; ++i)
-		queue_rx();
+	queue_rx();
 	toggle_apps_ack();
 	bam_connection_is_active = 1;
 	complete_all(&bam_connection_completion);
@@ -1776,17 +1953,26 @@
 	dma_free_coherent(NULL, rx_desc_mem_buf.size, rx_desc_mem_buf.base,
 				rx_desc_mem_buf.phys_base);
 rx_mem_failed:
-	sps_disconnect(bam_tx_pipe);
 rx_get_config_failed:
 	sps_free_endpoint(bam_rx_pipe);
+rx_alloc_endpoint_failed:
+	sps_disconnect(bam_tx_pipe);
 tx_connect_failed:
 	dma_free_coherent(NULL, tx_desc_mem_buf.size, tx_desc_mem_buf.base,
 				tx_desc_mem_buf.phys_base);
 tx_get_config_failed:
 	sps_free_endpoint(bam_tx_pipe);
-tx_mem_failed:
+tx_alloc_endpoint_failed:
 	sps_deregister_bam_device(h);
+	/*
+	 * sps_deregister_bam_device() calls iounmap.  calling iounmap on the
+	 * same handle below will cause a crash, so skip it if we've freed
+	 * the handle here.
+	 */
+	skip_iounmap = 1;
 register_bam_failed:
+	if (!skip_iounmap)
+		iounmap(a2_virt_addr);
 ioremap_failed:
 	/*destroy_workqueue(bam_mux_workqueue);*/
 	return ret;
@@ -1825,6 +2011,7 @@
 	return 0;
 
 register_bam_failed:
+	iounmap(a2_virt_addr);
 ioremap_failed:
 	return ret;
 }
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
new file mode 100644
index 0000000..cd84722
--- /dev/null
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -0,0 +1,398 @@
+/* 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 <asm/mach-types.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <mach/board.h>
+#include <mach/msm_bus_board.h>
+#include <mach/gpiomux.h>
+
+#include "devices.h"
+#include "board-8064.h"
+
+static struct gpiomux_setting cam_settings[] = {
+	{
+		.func = GPIOMUX_FUNC_GPIO, /*suspend*/
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_DOWN,
+	},
+
+	{
+		.func = GPIOMUX_FUNC_1, /*active 1*/
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_NONE,
+	},
+
+	{
+		.func = GPIOMUX_FUNC_GPIO, /*active 2*/
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_NONE,
+	},
+
+	{
+		.func = GPIOMUX_FUNC_1, /*active 3*/
+		.drv = GPIOMUX_DRV_8MA,
+		.pull = GPIOMUX_PULL_NONE,
+	},
+
+	{
+		.func = GPIOMUX_FUNC_5, /*active 4*/
+		.drv = GPIOMUX_DRV_8MA,
+		.pull = GPIOMUX_PULL_UP,
+	},
+
+	{
+		.func = GPIOMUX_FUNC_6, /*active 5*/
+		.drv = GPIOMUX_DRV_8MA,
+		.pull = GPIOMUX_PULL_UP,
+	},
+
+	{
+		.func = GPIOMUX_FUNC_2, /*active 6*/
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_UP,
+	},
+
+	{
+		.func = GPIOMUX_FUNC_3, /*active 7*/
+		.drv = GPIOMUX_DRV_8MA,
+		.pull = GPIOMUX_PULL_UP,
+	},
+
+	{
+		.func = GPIOMUX_FUNC_GPIO, /*i2c suspend*/
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_KEEPER,
+	},
+
+};
+
+
+static struct msm_gpiomux_config apq8064_cam_common_configs[] = {
+	{
+		.gpio = 2,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[2],
+			[GPIOMUX_SUSPENDED] = &cam_settings[0],
+		},
+	},
+	{
+		.gpio = 3,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[1],
+			[GPIOMUX_SUSPENDED] = &cam_settings[0],
+		},
+	},
+	{
+		.gpio = 4,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[1],
+			[GPIOMUX_SUSPENDED] = &cam_settings[0],
+		},
+	},
+	{
+		.gpio = 5,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[1],
+			[GPIOMUX_SUSPENDED] = &cam_settings[0],
+		},
+	},
+	{
+		.gpio = 76,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[2],
+			[GPIOMUX_SUSPENDED] = &cam_settings[0],
+		},
+	},
+	{
+		.gpio = 107,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[2],
+			[GPIOMUX_SUSPENDED] = &cam_settings[0],
+		},
+	},
+};
+
+static struct msm_gpiomux_config apq8064_cam_2d_configs[] = {
+	{
+		.gpio = 10,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &cam_settings[8],
+		},
+	},
+	{
+		.gpio = 11,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &cam_settings[8],
+		},
+	},
+	{
+		.gpio = 12,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &cam_settings[8],
+		},
+	},
+	{
+		.gpio = 13,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &cam_settings[8],
+		},
+	},
+};
+
+#ifdef CONFIG_MSM_CAMERA
+
+static struct msm_bus_vectors cam_init_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 0,
+		.ib  = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_VPE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 0,
+		.ib  = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 0,
+		.ib  = 0,
+	},
+};
+
+static struct msm_bus_vectors cam_preview_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 27648000,
+		.ib  = 110592000,
+	},
+	{
+		.src = MSM_BUS_MASTER_VPE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 0,
+		.ib  = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 0,
+		.ib  = 0,
+	},
+};
+
+static struct msm_bus_vectors cam_video_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 140451840,
+		.ib  = 561807360,
+	},
+	{
+		.src = MSM_BUS_MASTER_VPE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 206807040,
+		.ib  = 488816640,
+	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 0,
+		.ib  = 0,
+	},
+};
+
+static struct msm_bus_vectors cam_snapshot_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 274423680,
+		.ib  = 1097694720,
+	},
+	{
+		.src = MSM_BUS_MASTER_VPE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 0,
+		.ib  = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 540000000,
+		.ib  = 1350000000,
+	},
+};
+
+static struct msm_bus_vectors cam_zsl_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 302071680,
+		.ib  = 1208286720,
+	},
+	{
+		.src = MSM_BUS_MASTER_VPE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 0,
+		.ib  = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 540000000,
+		.ib  = 1350000000,
+	},
+};
+
+static struct msm_bus_paths cam_bus_client_config[] = {
+	{
+		ARRAY_SIZE(cam_init_vectors),
+		cam_init_vectors,
+	},
+	{
+		ARRAY_SIZE(cam_preview_vectors),
+		cam_preview_vectors,
+	},
+	{
+		ARRAY_SIZE(cam_video_vectors),
+		cam_video_vectors,
+	},
+	{
+		ARRAY_SIZE(cam_snapshot_vectors),
+		cam_snapshot_vectors,
+	},
+	{
+		ARRAY_SIZE(cam_zsl_vectors),
+		cam_zsl_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata cam_bus_client_pdata = {
+		cam_bus_client_config,
+		ARRAY_SIZE(cam_bus_client_config),
+		.name = "msm_camera",
+};
+
+static struct msm_camera_device_platform_data msm_camera_csi_device_data[] = {
+	{
+		.csid_core = 0,
+		.is_csiphy = 1,
+		.is_csid   = 1,
+		.is_ispif  = 1,
+		.is_vpe    = 1,
+		.cam_bus_scale_table = &cam_bus_client_pdata,
+	},
+	{
+		.csid_core = 1,
+		.is_csiphy = 1,
+		.is_csid   = 1,
+		.is_ispif  = 1,
+		.is_vpe    = 1,
+		.cam_bus_scale_table = &cam_bus_client_pdata,
+	},
+};
+
+static struct camera_vreg_t msm_8064_back_cam_vreg[] = {
+	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+	{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
+};
+
+static struct gpio apq8064_common_cam_gpio[] = {
+	{5, GPIOF_DIR_IN, "CAMIF_MCLK"},
+	{20, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
+	{21, GPIOF_DIR_IN, "CAMIF_I2C_CLK"},
+};
+
+static struct gpio apq8064_back_cam_gpio[] = {
+	{107, GPIOF_DIR_OUT, "CAM_RESET"},
+};
+
+static struct msm_gpio_set_tbl apq8064_back_cam_gpio_set_tbl[] = {
+	{107, GPIOF_OUT_INIT_LOW, 1000},
+	{107, GPIOF_OUT_INIT_HIGH, 4000},
+};
+
+static struct msm_camera_gpio_conf apq8064_back_cam_gpio_conf = {
+	.cam_gpiomux_conf_tbl = apq8064_cam_2d_configs,
+	.cam_gpiomux_conf_tbl_size = ARRAY_SIZE(apq8064_cam_2d_configs),
+	.cam_gpio_common_tbl = apq8064_common_cam_gpio,
+	.cam_gpio_common_tbl_size = ARRAY_SIZE(apq8064_common_cam_gpio),
+	.cam_gpio_req_tbl = apq8064_back_cam_gpio,
+	.cam_gpio_req_tbl_size = ARRAY_SIZE(apq8064_back_cam_gpio),
+	.cam_gpio_set_tbl = apq8064_back_cam_gpio_set_tbl,
+	.cam_gpio_set_tbl_size = ARRAY_SIZE(apq8064_back_cam_gpio_set_tbl),
+};
+
+#ifdef CONFIG_IMX074
+static struct msm_camera_sensor_flash_data flash_imx074 = {
+	.flash_type	= MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
+	.mount_angle	= 90,
+	.cam_vreg = msm_8064_back_cam_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8064_back_cam_vreg),
+	.gpio_conf = &apq8064_back_cam_gpio_conf,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_imx074_data = {
+	.sensor_name	= "imx074",
+	.pdata	= &msm_camera_csi_device_data[0],
+	.flash_data	= &flash_imx074,
+	.sensor_platform_info = &sensor_board_info_imx074,
+	.csi_if	= 1,
+	.camera_type = BACK_CAMERA_2D,
+};
+#endif
+
+void __init apq8064_init_cam(void)
+{
+	msm_gpiomux_install(apq8064_cam_common_configs,
+			ARRAY_SIZE(apq8064_cam_common_configs));
+
+	platform_device_register(&msm8960_device_csiphy0);
+	platform_device_register(&msm8960_device_csiphy1);
+	platform_device_register(&msm8960_device_csid0);
+	platform_device_register(&msm8960_device_csid1);
+	platform_device_register(&msm8960_device_ispif);
+	platform_device_register(&msm8960_device_vfe);
+	platform_device_register(&msm8960_device_vpe);
+}
+
+#ifdef CONFIG_I2C
+static struct i2c_board_info apq8064_camera_i2c_boardinfo[] = {
+#ifdef CONFIG_IMX074
+	{
+	I2C_BOARD_INFO("imx074", 0x1A),
+	.platform_data = &msm_camera_sensor_imx074_data,
+	},
+#endif
+};
+
+struct msm_camera_board_info apq8064_camera_board_info = {
+	.board_info = apq8064_camera_i2c_boardinfo,
+	.num_i2c_board_info = ARRAY_SIZE(apq8064_camera_i2c_boardinfo),
+};
+#endif
+#endif
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
new file mode 100644
index 0000000..73758d0
--- /dev/null
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -0,0 +1,144 @@
+/* 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/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+#include <asm/mach-types.h>
+#include <mach/msm_memtypes.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+#include <linux/ion.h>
+#include <mach/ion.h>
+
+#include "devices.h"
+#include "board-8064.h"
+
+#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
+/* prim = 1366 x 768 x 3(bpp) x 3(pages) */
+#define MSM_FB_PRIM_BUF_SIZE roundup(1366 * 768 * 3 * 3, 0x10000)
+#else
+/* prim = 1366 x 768 x 3(bpp) x 2(pages) */
+#define MSM_FB_PRIM_BUF_SIZE roundup(1366 * 768 * 3 * 2, 0x10000)
+#endif
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+/* hdmi = 1920 x 1088 x 2(bpp) x 1(page) */
+#define MSM_FB_EXT_BUF_SIZE 0x3FC000
+#elif defined(CONFIG_FB_MSM_TVOUT)
+/* tvout = 720 x 576 x 2(bpp) x 2(pages) */
+#define MSM_FB_EXT_BUF_SIZE 0x195000
+#else /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
+#define MSM_FB_EXT_BUF_SIZE 0
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
+
+#define MSM_FB_SIZE roundup(MSM_FB_PRIM_BUF_SIZE + MSM_FB_EXT_BUF_SIZE, 4096)
+
+#ifdef CONFIG_FB_MSM_OVERLAY0_WRITEBACK
+#define MSM_FB_OVERLAY0_WRITEBACK_SIZE roundup((1376 * 768 * 3 * 2), 4096)
+#else
+#define MSM_FB_OVERLAY0_WRITEBACK_SIZE (0)
+#endif  /* CONFIG_FB_MSM_OVERLAY0_WRITEBACK */
+
+#ifdef CONFIG_FB_MSM_OVERLAY1_WRITEBACK
+#define MSM_FB_OVERLAY1_WRITEBACK_SIZE roundup((1920 * 1088 * 3 * 2), 4096)
+#else
+#define MSM_FB_OVERLAY1_WRITEBACK_SIZE (0)
+#endif  /* CONFIG_FB_MSM_OVERLAY1_WRITEBACK */
+
+static struct resource msm_fb_resources[] = {
+	{
+		.flags = IORESOURCE_DMA,
+	}
+};
+
+#define SIMULATOR_PANAL_NAME "mipi_video_simulator"
+#define SIMULATOR_PANAL_NAME_LEN 20
+#define LVDS_CHIMEI_PANEL_NAME "lvds_chimei_wxga"
+#define LVDS_CHIMEI_PANEL_NAME_LEN 16
+
+static int msm_fb_detect_panel(const char *name)
+{
+	if (!strncmp(name, LVDS_CHIMEI_PANEL_NAME,
+		LVDS_CHIMEI_PANEL_NAME_LEN))
+		return 0;
+	return -ENODEV;
+}
+
+static struct msm_fb_platform_data msm_fb_pdata = {
+	.detect_client = msm_fb_detect_panel,
+};
+
+static struct platform_device msm_fb_device = {
+	.name              = "msm_fb",
+	.id                = 0,
+	.num_resources     = ARRAY_SIZE(msm_fb_resources),
+	.resource          = msm_fb_resources,
+	.dev.platform_data = &msm_fb_pdata,
+};
+
+void __init apq8064_allocate_fb_region(void)
+{
+	void *addr;
+	unsigned long size;
+
+	size = MSM_FB_SIZE;
+	addr = alloc_bootmem_align(size, 0x1000);
+	msm_fb_resources[0].start = __pa(addr);
+	msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
+	pr_info("allocating %lu bytes at %p (%lx physical) for fb\n",
+			size, addr, __pa(addr));
+}
+
+#define MDP_VSYNC_GPIO 0
+
+static int mdp_core_clk_rate_table[] = {
+	266667000,
+	266667000,
+	266667000,
+	266667000,
+};
+
+static struct msm_panel_common_pdata mdp_pdata = {
+	.gpio = MDP_VSYNC_GPIO,
+	.mdp_core_clk_rate = 266667000,
+	.mdp_core_clk_table = mdp_core_clk_rate_table,
+	.num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
+	.mdp_rev = MDP_REV_44,
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	.mem_hid = ION_CP_MM_HEAP_ID,
+#else
+	.mem_hid = MEMTYPE_EBI1,
+#endif
+};
+
+void __init apq8064_mdp_writeback(struct memtype_reserve* reserve_table)
+{
+	mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
+	mdp_pdata.ov1_wb_size = MSM_FB_OVERLAY1_WRITEBACK_SIZE;
+#if defined(CONFIG_ANDROID_PMEM) && !defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+	reserve_table[mdp_pdata.mem_hid].size +=
+		mdp_pdata.ov0_wb_size;
+	reserve_table[mdp_pdata.mem_hid].size +=
+		mdp_pdata.ov1_wb_size;
+#endif
+}
+
+void __init apq8064_init_fb(void)
+{
+	platform_device_register(&msm_fb_device);
+	msm_fb_register_device("mdp", &mdp_pdata);
+	msm_fb_register_device("lvds", NULL);
+}
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index 3075e07..e769566 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
@@ -21,6 +21,7 @@
 #include <mach/board.h>
 #include <mach/gpio.h>
 #include <mach/gpiomux.h>
+#include <mach/socinfo.h>
 #include "devices.h"
 #include "board-8064.h"
 
@@ -34,17 +35,24 @@
 /* The SPI configurations apply to GSBI 5*/
 static struct gpiomux_setting gpio_spi_config = {
 	.func = GPIOMUX_FUNC_2,
-	.drv = GPIOMUX_DRV_8MA,
+	.drv = GPIOMUX_DRV_12MA,
 	.pull = GPIOMUX_PULL_NONE,
 };
 
 /* The SPI configurations apply to GSBI 5 chip select 2*/
 static struct gpiomux_setting gpio_spi_cs2_config = {
 	.func = GPIOMUX_FUNC_3,
-	.drv = GPIOMUX_DRV_8MA,
+	.drv = GPIOMUX_DRV_12MA,
 	.pull = GPIOMUX_PULL_NONE,
 };
 
+/* Chip selects for SPI clients */
+static struct gpiomux_setting gpio_spi_cs_config = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_12MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
 struct msm_gpiomux_config apq8064_ethernet_configs[] = {
 	{
 		.gpio = 43,
@@ -83,7 +91,76 @@
 	.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 gpiomux_setting ext_regulator_config = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+	.dir = GPIOMUX_OUT_LOW,
+};
+
+static struct gpiomux_setting gsbi7_func1_cfg = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gsbi7_func2_cfg = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+static struct gpiomux_setting hsic_act_cfg = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting hsic_sus_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+	.dir = GPIOMUX_OUT_LOW,
+};
+
+static struct msm_gpiomux_config apq8064_hsic_configs[] = {
+	{
+		.gpio = 88,               /*HSIC_STROBE */
+		.settings = {
+			[GPIOMUX_ACTIVE] = &hsic_act_cfg,
+			[GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
+		},
+	},
+	{
+		.gpio = 89,               /* HSIC_DATA */
+		.settings = {
+			[GPIOMUX_ACTIVE] = &hsic_act_cfg,
+			[GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
+		},
+	},
+};
+#endif
+
 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 */
@@ -98,6 +175,12 @@
 		},
 	},
 	{
+		.gpio      = 53,		/* Funny CS0 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+		},
+	},
+	{
 		.gpio      = 31,		/* GSBI5 QUP SPI_CS2_N */
 		.settings = {
 			[GPIOMUX_SUSPENDED] = &gpio_spi_cs2_config,
@@ -110,6 +193,36 @@
 		},
 	},
 #endif
+	{
+		.gpio      = 30,		/* FP CS */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_cs_config,
+		},
+	},
+	{
+		.gpio      = 32,		/* EPM CS */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_cs_config,
+		},
+	},
+	{
+		.gpio      = 53,		/* NOR CS */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_cs_config,
+		},
+	},
+	{
+		.gpio      = 82,	/* GSBI7 UART2 TX */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi7_func2_cfg,
+		},
+	},
+	{
+		.gpio      = 83,	/* GSBI7 UART2 RX */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi7_func1_cfg,
+		},
+	},
 };
 
 static struct msm_gpiomux_config apq8064_slimbus_config[] __initdata = {
@@ -167,6 +280,78 @@
 	},
 };
 
+/* External 3.3 V regulator enable */
+static struct msm_gpiomux_config apq8064_ext_regulator_configs[] __initdata = {
+	{
+		.gpio = APQ8064_EXT_3P3V_REG_EN_GPIO,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ext_regulator_config,
+		},
+	},
+};
+
+static struct gpiomux_setting ap2mdm_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting mdm2ap_status_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting mdm2ap_errfatal_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_16MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting ap2mdm_pon_reset_n_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct msm_gpiomux_config mdm_configs[] __initdata = {
+	/* AP2MDM_STATUS */
+	{
+		.gpio = 48,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
+		}
+	},
+	/* MDM2AP_STATUS */
+	{
+		.gpio = 49,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &mdm2ap_status_cfg,
+		}
+	},
+	/* MDM2AP_ERRFATAL */
+	{
+		.gpio = 19,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &mdm2ap_errfatal_cfg,
+		}
+	},
+	/* AP2MDM_ERRFATAL */
+	{
+		.gpio = 18,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
+		}
+	},
+	/* AP2MDM_PON_RESET_N */
+	{
+		.gpio = 27,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ap2mdm_pon_reset_n_cfg,
+		}
+	}
+};
+
 void __init apq8064_init_gpiomux(void)
 {
 	int rc;
@@ -193,4 +378,16 @@
 
 	msm_gpiomux_install(apq8064_audio_auxpcm_configs,
 			ARRAY_SIZE(apq8064_audio_auxpcm_configs));
+
+	msm_gpiomux_install(apq8064_ext_regulator_configs,
+			ARRAY_SIZE(apq8064_ext_regulator_configs));
+
+	if (machine_is_apq8064_mtp())
+		msm_gpiomux_install(mdm_configs,
+			ARRAY_SIZE(mdm_configs));
+
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+	msm_gpiomux_install(apq8064_hsic_configs,
+			ARRAY_SIZE(apq8064_hsic_configs));
+#endif
 }
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..5204e48 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,15 +15,236 @@
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <linux/bootmem.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/leds.h>
+#include <linux/leds-pm8xxx.h>
+#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
 #include <asm/mach-types.h>
 #include <asm/mach/mmc.h>
 #include <mach/msm_bus_board.h>
 #include <mach/board.h>
 #include <mach/gpio.h>
 #include <mach/gpiomux.h>
+#include <mach/restart.h>
 #include "devices.h"
 #include "board-8064.h"
 
+struct pm8xxx_gpio_init {
+	unsigned			gpio;
+	struct pm_gpio			config;
+};
+
+struct pm8xxx_mpp_init {
+	unsigned			mpp;
+	struct pm8xxx_mpp_config_data	config;
+};
+
+#define PM8921_GPIO_INIT(_gpio, _dir, _buf, _val, _pull, _vin, _out_strength, \
+			_func, _inv, _disable) \
+{ \
+	.gpio	= PM8921_GPIO_PM_TO_SYS(_gpio), \
+	.config	= { \
+		.direction	= _dir, \
+		.output_buffer	= _buf, \
+		.output_value	= _val, \
+		.pull		= _pull, \
+		.vin_sel	= _vin, \
+		.out_strength	= _out_strength, \
+		.function	= _func, \
+		.inv_int_pol	= _inv, \
+		.disable_pin	= _disable, \
+	} \
+}
+
+#define PM8921_MPP_INIT(_mpp, _type, _level, _control) \
+{ \
+	.mpp	= PM8921_MPP_PM_TO_SYS(_mpp), \
+	.config	= { \
+		.type		= PM8XXX_MPP_TYPE_##_type, \
+		.level		= _level, \
+		.control	= PM8XXX_MPP_##_control, \
+	} \
+}
+
+#define PM8821_MPP_INIT(_mpp, _type, _level, _control) \
+{ \
+	.mpp	= PM8821_MPP_PM_TO_SYS(_mpp), \
+	.config	= { \
+		.type		= PM8XXX_MPP_TYPE_##_type, \
+		.level		= _level, \
+		.control	= PM8XXX_MPP_##_control, \
+	} \
+}
+
+#define PM8921_GPIO_DISABLE(_gpio) \
+	PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, 0, 0, 0, PM_GPIO_VIN_S4, \
+			 0, 0, 0, 1)
+
+#define PM8921_GPIO_OUTPUT(_gpio, _val, _strength) \
+	PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+			PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+			PM_GPIO_STRENGTH_##_strength, \
+			PM_GPIO_FUNC_NORMAL, 0, 0)
+
+#define PM8921_GPIO_INPUT(_gpio, _pull) \
+	PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, PM_GPIO_OUT_BUF_CMOS, 0, \
+			_pull, PM_GPIO_VIN_S4, \
+			PM_GPIO_STRENGTH_NO, \
+			PM_GPIO_FUNC_NORMAL, 0, 0)
+
+#define PM8921_GPIO_OUTPUT_FUNC(_gpio, _val, _func) \
+	PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+			PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+			PM_GPIO_STRENGTH_HIGH, \
+			_func, 0, 0)
+
+#define PM8921_GPIO_OUTPUT_VIN(_gpio, _val, _vin) \
+	PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+			PM_GPIO_PULL_NO, _vin, \
+			PM_GPIO_STRENGTH_HIGH, \
+			PM_GPIO_FUNC_NORMAL, 0, 0)
+
+/* Initial PM8921 GPIO configurations */
+static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
+};
+
+/* Initial PM8XXX MPP configurations */
+static struct pm8xxx_mpp_init pm8xxx_mpps[] __initdata = {
+	/* External 5V regulator enable; shared by HDMI and USB_OTG switches. */
+	PM8921_MPP_INIT(7, D_INPUT, PM8921_MPP_DIG_LEVEL_VPH, DIN_TO_INT),
+};
+
+void __init apq8064_pm8xxx_gpio_mpp_init(void)
+{
+	int i, rc;
+
+	for (i = 0; i < ARRAY_SIZE(pm8921_gpios); i++) {
+		rc = pm8xxx_gpio_config(pm8921_gpios[i].gpio,
+					&pm8921_gpios[i].config);
+		if (rc) {
+			pr_err("%s: pm8xxx_gpio_config: rc=%d\n", __func__, rc);
+			break;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(pm8xxx_mpps); i++) {
+		rc = pm8xxx_mpp_config(pm8xxx_mpps[i].mpp,
+					&pm8xxx_mpps[i].config);
+		if (rc) {
+			pr_err("%s: pm8xxx_mpp_config: rc=%d\n", __func__, rc);
+			break;
+		}
+	}
+}
+
+static struct pm8xxx_pwrkey_platform_data apq8064_pm8921_pwrkey_pdata = {
+	.pull_up		= 1,
+	.kpd_trigger_delay_us	= 15625,
+	.wakeup			= 1,
+};
+
+static struct pm8xxx_misc_platform_data apq8064_pm8921_misc_pdata = {
+	.priority		= 0,
+};
+
+#define PM8921_LC_LED_MAX_CURRENT	4	/* I = 4mA */
+#define PM8921_LC_LED_LOW_CURRENT	1	/* I = 1mA */
+#define PM8XXX_LED_PWM_PERIOD		1000
+#define PM8XXX_LED_PWM_DUTY_MS		20
+/**
+ * PM8XXX_PWM_CHANNEL_NONE shall be used when LED shall not be
+ * driven using PWM feature.
+ */
+#define PM8XXX_PWM_CHANNEL_NONE		-1
+
+static struct led_info pm8921_led_info[] = {
+	[0] = {
+		.name			= "led:red",
+		.default_trigger	= "ac-online",
+	},
+};
+
+static struct led_platform_data pm8921_led_core_pdata = {
+	.num_leds = ARRAY_SIZE(pm8921_led_info),
+	.leds = pm8921_led_info,
+};
+
+static int pm8921_led0_pwm_duty_pcts[56] = {
+	1, 4, 8, 12, 16, 20, 24, 28, 32, 36,
+	40, 44, 46, 52, 56, 60, 64, 68, 72, 76,
+	80, 84, 88, 92, 96, 100, 100, 100, 98, 95,
+	92, 88, 84, 82, 78, 74, 70, 66, 62, 58,
+	58, 54, 50, 48, 42, 38, 34, 30, 26, 22,
+	14, 10, 6, 4, 1
+};
+
+static struct pm8xxx_pwm_duty_cycles pm8921_led0_pwm_duty_cycles = {
+	.duty_pcts = (int *)&pm8921_led0_pwm_duty_pcts,
+	.num_duty_pcts = ARRAY_SIZE(pm8921_led0_pwm_duty_pcts),
+	.duty_ms = PM8XXX_LED_PWM_DUTY_MS,
+	.start_idx = 0,
+};
+
+static struct pm8xxx_led_config pm8921_led_configs[] = {
+	[0] = {
+		.id = PM8XXX_ID_LED_0,
+		.mode = PM8XXX_LED_MODE_PWM2,
+		.max_current = PM8921_LC_LED_MAX_CURRENT,
+		.pwm_channel = 5,
+		.pwm_period_us = PM8XXX_LED_PWM_PERIOD,
+		.pwm_duty_cycles = &pm8921_led0_pwm_duty_cycles,
+	},
+};
+
+static struct pm8xxx_led_platform_data apq8064_pm8921_leds_pdata = {
+		.led_core = &pm8921_led_core_pdata,
+		.configs = pm8921_led_configs,
+		.num_configs = ARRAY_SIZE(pm8921_led_configs),
+};
+
+static struct pm8xxx_adc_amux apq8064_pm8921_adc_channels_data[] = {
+	{"vcoin", CHANNEL_VCOIN, CHAN_PATH_SCALING2, AMUX_RSV1,
+		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+	{"vbat", CHANNEL_VBAT, CHAN_PATH_SCALING2, AMUX_RSV1,
+		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+	{"dcin", CHANNEL_DCIN, CHAN_PATH_SCALING4, AMUX_RSV1,
+		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+	{"ichg", CHANNEL_ICHG, CHAN_PATH_SCALING1, AMUX_RSV1,
+		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+	{"vph_pwr", CHANNEL_VPH_PWR, CHAN_PATH_SCALING2, AMUX_RSV1,
+		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+	{"ibat", CHANNEL_IBAT, CHAN_PATH_SCALING1, AMUX_RSV1,
+		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+	{"batt_therm", CHANNEL_BATT_THERM, CHAN_PATH_SCALING1, AMUX_RSV2,
+		ADC_DECIMATION_TYPE2, ADC_SCALE_BATT_THERM},
+	{"batt_id", CHANNEL_BATT_ID, CHAN_PATH_SCALING1, AMUX_RSV1,
+		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+	{"usbin", CHANNEL_USBIN, CHAN_PATH_SCALING3, AMUX_RSV1,
+		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+	{"pmic_therm", CHANNEL_DIE_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
+		ADC_DECIMATION_TYPE2, ADC_SCALE_PMIC_THERM},
+	{"625mv", CHANNEL_625MV, CHAN_PATH_SCALING1, AMUX_RSV1,
+		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+	{"125v", CHANNEL_125V, CHAN_PATH_SCALING1, AMUX_RSV1,
+		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+	{"chg_temp", CHANNEL_CHG_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
+		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+	{"xo_therm", CHANNEL_MUXOFF, CHAN_PATH_SCALING1, AMUX_RSV0,
+		ADC_DECIMATION_TYPE2, ADC_SCALE_XOTHERM},
+};
+
+static struct pm8xxx_adc_properties apq8064_pm8921_adc_data = {
+	.adc_vdd_reference	= 1800, /* milli-voltage for this adc */
+	.bitresolution		= 15,
+	.bipolar                = 0,
+};
+
+static struct pm8xxx_adc_platform_data apq8064_pm8921_adc_pdata = {
+	.adc_channel		= apq8064_pm8921_adc_channels_data,
+	.adc_num_board_channel	= ARRAY_SIZE(apq8064_pm8921_adc_channels_data),
+	.adc_prop		= &apq8064_pm8921_adc_data,
+	.adc_mpp_base		= PM8921_MPP_PM_TO_SYS(1),
+};
 
 static struct pm8xxx_mpp_platform_data
 apq8064_pm8921_mpp_pdata __devinitdata = {
@@ -43,18 +264,74 @@
 	.dev_id			= 0,
 };
 
+static struct pm8xxx_rtc_platform_data
+apq8064_pm8921_rtc_pdata = {
+	.rtc_write_enable       = false,
+	.rtc_alarm_powerup      = false,
+};
+
+static int apq8064_pm8921_therm_mitigation[] = {
+	1100,
+	700,
+	600,
+	325,
+};
+
+#define MAX_VOLTAGE_MV          4200
+static struct pm8921_charger_platform_data
+apq8064_pm8921_chg_pdata __devinitdata = {
+	.safety_time		= 180,
+	.update_time		= 60000,
+	.max_voltage		= MAX_VOLTAGE_MV,
+	.min_voltage		= 3200,
+	.resume_voltage_delta	= 100,
+	.term_current		= 100,
+	.cool_temp		= 10,
+	.warm_temp		= 40,
+	.temp_check_period	= 1,
+	.max_bat_chg_current	= 1100,
+	.cool_bat_chg_current	= 350,
+	.warm_bat_chg_current	= 350,
+	.cool_bat_voltage	= 4100,
+	.warm_bat_voltage	= 4100,
+	.thermal_mitigation	= apq8064_pm8921_therm_mitigation,
+	.thermal_levels		= ARRAY_SIZE(apq8064_pm8921_therm_mitigation),
+};
+
+static struct pm8xxx_ccadc_platform_data
+apq8064_pm8xxx_ccadc_pdata = {
+	.r_sense		= 10,
+};
+
+static struct pm8921_bms_platform_data
+apq8064_pm8921_bms_pdata __devinitdata = {
+	.r_sense		= 10,
+	.i_test			= 2500,
+	.v_failure		= 3000,
+	.calib_delay_ms		= 600000,
+	.max_voltage_uv		= MAX_VOLTAGE_MV * 1000,
+};
+
 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,
+	.pwrkey_pdata		= &apq8064_pm8921_pwrkey_pdata,
+	.misc_pdata		= &apq8064_pm8921_misc_pdata,
+	.leds_pdata		= &apq8064_pm8921_leds_pdata,
+	.adc_pdata		= &apq8064_pm8921_adc_pdata,
+	.charger_pdata		= &apq8064_pm8921_chg_pdata,
+	.bms_pdata		= &apq8064_pm8921_bms_pdata,
+	.ccadc_pdata		= &apq8064_pm8xxx_ccadc_pdata,
 };
 
 static struct pm8xxx_irq_platform_data
 apq8064_pm8821_irq_pdata __devinitdata = {
 	.irq_base		= PM8821_IRQ_BASE,
-	.devirq			= PM8821_USR_IRQ_N,
+	.devirq			= PM8821_SEC_IRQ_N,
 	.irq_trigger_flag	= IRQF_TRIGGER_HIGH,
 	.dev_id			= 1,
 };
@@ -88,6 +365,8 @@
 
 void __init apq8064_init_pmic(void)
 {
+	pmic_reset_irq = PM8921_IRQ_BASE + PM8921_RESOUT_IRQ;
+
 	apq8064_device_ssbi_pmic1.dev.platform_data =
 						&apq8064_ssbi_pm8921_pdata;
 	apq8064_device_ssbi_pmic2.dev.platform_data =
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 47b20e4..f3eebce 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-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
@@ -27,6 +27,8 @@
 };
 VREG_CONSUMERS(L2) = {
 	REGULATOR_SUPPLY("8921_l2",		NULL),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-001a"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-006c"),
 };
 VREG_CONSUMERS(L3) = {
 	REGULATOR_SUPPLY("8921_l3",		NULL),
@@ -39,6 +41,7 @@
 	REGULATOR_SUPPLY("HSUSB_1p8",		"msm_otg"),
 	REGULATOR_SUPPLY("HSUSB_1p8",		"msm_ehci_host.0"),
 	REGULATOR_SUPPLY("HSUSB_1p8",		"msm_ehci_host.1"),
+	REGULATOR_SUPPLY("iris_vddxo",		"wcnss_wlan.0"),
 };
 VREG_CONSUMERS(L5) = {
 	REGULATOR_SUPPLY("8921_l5",		NULL),
@@ -54,17 +57,22 @@
 };
 VREG_CONSUMERS(L8) = {
 	REGULATOR_SUPPLY("8921_l8",		NULL),
+	REGULATOR_SUPPLY("cam_vana",		"4-001a"),
+	REGULATOR_SUPPLY("cam_vana",		"4-006c"),
 };
 VREG_CONSUMERS(L9) = {
 	REGULATOR_SUPPLY("8921_l9",		NULL),
 };
 VREG_CONSUMERS(L10) = {
 	REGULATOR_SUPPLY("8921_l10",		NULL),
+	REGULATOR_SUPPLY("iris_vddpa",		"wcnss_wlan.0"),
 };
 VREG_CONSUMERS(L11) = {
 	REGULATOR_SUPPLY("8921_l11",		NULL),
 };
 VREG_CONSUMERS(L12) = {
+	REGULATOR_SUPPLY("cam_vdig",		"4-001a"),
+	REGULATOR_SUPPLY("cam_vdig",		"4-006c"),
 	REGULATOR_SUPPLY("8921_l12",		NULL),
 };
 VREG_CONSUMERS(L14) = {
@@ -75,6 +83,8 @@
 };
 VREG_CONSUMERS(L16) = {
 	REGULATOR_SUPPLY("8921_l16",		NULL),
+	REGULATOR_SUPPLY("cam_vaf",		"4-001a"),
+	REGULATOR_SUPPLY("cam_vaf",		"4-006c"),
 };
 VREG_CONSUMERS(L17) = {
 	REGULATOR_SUPPLY("8921_l17",		NULL),
@@ -90,6 +100,7 @@
 };
 VREG_CONSUMERS(L24) = {
 	REGULATOR_SUPPLY("8921_l24",		NULL),
+	REGULATOR_SUPPLY("riva_vddmx",		"wcnss_wlan.0"),
 };
 VREG_CONSUMERS(L25) = {
 	REGULATOR_SUPPLY("8921_l25",		NULL),
@@ -98,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),
@@ -110,12 +122,15 @@
 };
 VREG_CONSUMERS(S2) = {
 	REGULATOR_SUPPLY("8921_s2",		NULL),
+	REGULATOR_SUPPLY("iris_vddrfa",		"wcnss_wlan.0"),
 };
 VREG_CONSUMERS(S3) = {
 	REGULATOR_SUPPLY("8921_s3",		NULL),
 	REGULATOR_SUPPLY("HSUSB_VDDCX",		"msm_otg"),
 	REGULATOR_SUPPLY("HSUSB_VDDCX",		"msm_ehci_host.0"),
 	REGULATOR_SUPPLY("HSUSB_VDDCX",		"msm_ehci_host.1"),
+	REGULATOR_SUPPLY("HSIC_VDDCX",		"msm_hsic_host"),
+	REGULATOR_SUPPLY("riva_vddcx",		"wcnss_wlan.0"),
 };
 VREG_CONSUMERS(S4) = {
 	REGULATOR_SUPPLY("8921_s4",		NULL),
@@ -124,21 +139,26 @@
 	REGULATOR_SUPPLY("CDC_VDD_CP",		"tabla-slim"),
 	REGULATOR_SUPPLY("CDC_VDDA_TX",		"tabla-slim"),
 	REGULATOR_SUPPLY("CDC_VDDA_RX",		"tabla-slim"),
+	REGULATOR_SUPPLY("riva_vddpx",		"wcnss_wlan.0"),
 };
 VREG_CONSUMERS(S5) = {
 	REGULATOR_SUPPLY("8921_s5",		NULL),
+	REGULATOR_SUPPLY("krait0",		NULL),
 };
 VREG_CONSUMERS(S6) = {
 	REGULATOR_SUPPLY("8921_s6",		NULL),
+	REGULATOR_SUPPLY("krait1",		NULL),
 };
 VREG_CONSUMERS(S7) = {
 	REGULATOR_SUPPLY("8921_s7",		NULL),
 };
 VREG_CONSUMERS(LVS1) = {
 	REGULATOR_SUPPLY("8921_lvs1",		NULL),
+	REGULATOR_SUPPLY("iris_vddio",		"wcnss_wlan.0"),
 };
 VREG_CONSUMERS(LVS2) = {
 	REGULATOR_SUPPLY("8921_lvs2",		NULL),
+	REGULATOR_SUPPLY("iris_vdddig",		"wcnss_wlan.0"),
 };
 VREG_CONSUMERS(LVS3) = {
 	REGULATOR_SUPPLY("8921_lvs3",		NULL),
@@ -148,15 +168,19 @@
 };
 VREG_CONSUMERS(LVS5) = {
 	REGULATOR_SUPPLY("8921_lvs5",		NULL),
+	REGULATOR_SUPPLY("cam_vio",		"4-001a"),
+	REGULATOR_SUPPLY("cam_vio",		"4-006c"),
 };
 VREG_CONSUMERS(LVS6) = {
 	REGULATOR_SUPPLY("8921_lvs6",		NULL),
 };
 VREG_CONSUMERS(LVS7) = {
 	REGULATOR_SUPPLY("8921_lvs7",		NULL),
+	REGULATOR_SUPPLY("pll_vdd",		"pil_riva"),
 };
 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),
@@ -166,9 +190,19 @@
 };
 VREG_CONSUMERS(8821_S0) = {
 	REGULATOR_SUPPLY("8821_s0",		NULL),
+	REGULATOR_SUPPLY("krait2",		NULL),
 };
 VREG_CONSUMERS(8821_S1) = {
 	REGULATOR_SUPPLY("8821_s1",		NULL),
+	REGULATOR_SUPPLY("krait3",		NULL),
+};
+VREG_CONSUMERS(EXT_5V) = {
+	REGULATOR_SUPPLY("ext_5v",		NULL),
+};
+VREG_CONSUMERS(EXT_3P3V) = {
+	REGULATOR_SUPPLY("ext_3p3v",		NULL),
+	REGULATOR_SUPPLY("vdd_io",		"spi0.2"),
+	REGULATOR_SUPPLY("mhl_ext_3p3v",	"msm_otg"),
 };
 
 #define PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
@@ -266,6 +300,22 @@
 		.pin_ctrl	= _pin_ctrl, \
 	}
 
+#define GPIO_VREG(_id, _reg_name, _gpio_label, _gpio, _supply_regulator) \
+	[GPIO_VREG_ID_##_id] = { \
+		.init_data = { \
+			.constraints = { \
+				.valid_ops_mask	= REGULATOR_CHANGE_STATUS, \
+			}, \
+			.num_consumer_supplies	= \
+					ARRAY_SIZE(vreg_consumers_##_id), \
+			.consumer_supplies	= vreg_consumers_##_id, \
+			.supply_regulator	= _supply_regulator, \
+		}, \
+		.regulator_name = _reg_name, \
+		.gpio_label	= _gpio_label, \
+		.gpio		= _gpio, \
+	}
+
 #define SAW_VREG_INIT(_id, _name, _min_uV, _max_uV) \
 	{ \
 		.constraints = { \
@@ -278,6 +328,15 @@
 		.consumer_supplies	= vreg_consumers_##_id, \
 	}
 
+/* GPIO regulator constraints */
+struct gpio_regulator_platform_data
+apq8064_gpio_regulator_pdata[] __devinitdata = {
+	/*        ID      vreg_name gpio_label   gpio                  supply */
+	GPIO_VREG(EXT_5V, "ext_5v", "ext_5v_en", PM8921_MPP_PM_TO_SYS(7), NULL),
+	GPIO_VREG(EXT_3P3V, "ext_3p3v", "ext_3p3v_en",
+		  APQ8064_EXT_3P3V_REG_EN_GPIO, NULL),
+};
+
 /* SAW regulator constraints */
 struct regulator_init_data msm8064_saw_regulator_pdata_8921_s5 =
 	/*	      ID  vreg_name	       min_uV   max_uV */
@@ -305,7 +364,7 @@
 		3),
 	PM8XXX_SMPS(S4, "8921_s4",  1, 1, 1800000, 1800000, 500, NULL, 100000,
 		4),
-	PM8XXX_SMPS(S7, "8921_s7",  0, 1, 1200000, 1200000, 500, NULL, 100000,
+	PM8XXX_SMPS(S7, "8921_s7",  0, 1, 1300000, 1300000, 500, NULL, 100000,
 		5),
 
 	PM8XXX_LDO(L1,  "8921_l1",  1, 1, 1100000, 1100000, 200, "8921_s4", 0,
@@ -313,10 +372,11 @@
 	PM8XXX_LDO(L2,  "8921_l2",  0, 1, 1200000, 1200000, 200, "8921_s4", 0,
 		7),
 	PM8XXX_LDO(L3,  "8921_l3",  0, 1, 3075000, 3075000, 200, NULL, 0, 8),
-	PM8XXX_LDO(L4,  "8921_l4",  1, 1, 1800000, 1800000, 200, NULL, 0, 9),
+	PM8XXX_LDO(L4,  "8921_l4",  1, 1, 1800000, 1800000, 200, NULL, 10000,
+		9),
 	PM8XXX_LDO(L5,  "8921_l5",  0, 1, 2950000, 2950000, 200, NULL, 0, 10),
 	PM8XXX_LDO(L6,  "8921_l6",  0, 1, 2950000, 2950000, 200, NULL, 0, 11),
-	PM8XXX_LDO(L7,  "8921_l7",  1, 1, 1850000, 2950000, 200, NULL, 0, 12),
+	PM8XXX_LDO(L7,  "8921_l7",  0, 1, 1850000, 2950000, 200, NULL, 0, 12),
 	PM8XXX_LDO(L8,  "8921_l8",  0, 1, 2800000, 2800000, 200, NULL, 0, 13),
 	PM8XXX_LDO(L9,  "8921_l9",  0, 1, 2850000, 2850000, 200, NULL, 0, 14),
 	PM8XXX_LDO(L10, "8921_l10", 0, 1, 2900000, 2900000, 200, NULL, 0, 15),
@@ -334,10 +394,10 @@
 	PM8XXX_NLDO1200(L24, "8921_l24", 1, 1, 1150000, 1150000, 200, "8921_s1",
 		10000, 25),
 	PM8XXX_NLDO1200(L25, "8921_l25", 1, 1, 1225000, 1225000, 200, "8921_s1",
-		0, 26),
+		10000, 26),
 	PM8XXX_NLDO1200(L26, "8921_l26", 0, 1, 1050000, 1050000, 200, "8921_s7",
 		0, 27),
-	PM8XXX_NLDO1200(L27, "8921_l27", 0, 1, 1000000, 1000000, 200, "8921_s7",
+	PM8XXX_NLDO1200(L27, "8921_l27", 0, 1, 1100000, 1100000, 200, "8921_s7",
 		0, 28),
 	PM8XXX_NLDO1200(L28, "8921_l28", 0, 1, 1050000, 1050000, 200, "8921_s7",
 		0, 29),
@@ -351,8 +411,8 @@
 	PM8XXX_VS(LVS6,    "8921_lvs6", 0, 1,                 0, "8921_s4", 35),
 	PM8XXX_VS(LVS7,    "8921_lvs7", 1, 1,                 0, "8921_s4", 36),
 
-	PM8XXX_VS300(USB_OTG,  "8921_usb_otg",  0, 1,         0, NULL, 37),
-	PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1,         0, NULL, 38),
+	PM8XXX_VS300(USB_OTG,  "8921_usb_otg",  0, 0,         0, "ext_5v", 37),
+	PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1,         0, "ext_5v", 38),
 
 	/*         ID   name  always_on   min_uV   max_uV  en_t supply reg_ID */
 	PM8XXX_NCP(NCP,	"8921_ncp", 0,    1800000, 1800000, 200, "8921_l6", 39),
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 0ba7434..92e8f1b 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -23,6 +23,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/platform_data/qcom_crypto_device.h>
 #include <linux/ion.h>
+#include <linux/memory.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
@@ -39,6 +40,7 @@
 #include "devices.h"
 #include <mach/gpio.h>
 #include <mach/gpiomux.h>
+#include <mach/rpm.h>
 #ifdef CONFIG_ANDROID_PMEM
 #include <linux/android_pmem.h>
 #endif
@@ -47,9 +49,18 @@
 #include <asm/setup.h>
 #include <mach/dma.h>
 #include <mach/msm_bus_board.h>
+#include <mach/cpuidle.h>
+#include <mach/mdm2.h>
 
 #include "msm_watchdog.h"
 #include "board-8064.h"
+#include "acpuclock.h"
+#include "spm.h"
+#include "mpm.h"
+#include "rpm_resources.h"
+#include "pm.h"
+#include "pm-boot.h"
+#include "devices-msm8x60.h"
 
 #define MSM_PMEM_ADSP_SIZE         0x7800000
 #define MSM_PMEM_AUDIO_SIZE        0x2B4000
@@ -60,11 +71,14 @@
 #endif
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-#define MSM_PMEM_KERNEL_EBI1_SIZE  0xB0C000
+#define MSM_PMEM_KERNEL_EBI1_SIZE  0x280000
 #define MSM_ION_SF_SIZE		MSM_PMEM_SIZE
+#define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
 #define MSM_ION_MM_SIZE		MSM_PMEM_ADSP_SIZE
+#define MSM_ION_QSECOM_SIZE	0x100000 /* (1MB) */
 #define MSM_ION_MFC_SIZE	SZ_8K
-#define MSM_ION_HEAP_NUM	5
+#define MSM_ION_AUDIO_SIZE	MSM_PMEM_AUDIO_SIZE
+#define MSM_ION_HEAP_NUM	8
 #else
 #define MSM_PMEM_KERNEL_EBI1_SIZE  0x110C000
 #define MSM_ION_HEAP_NUM	1
@@ -198,13 +212,22 @@
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 static struct ion_cp_heap_pdata cp_mm_ion_pdata = {
 	.permission_type = IPT_TYPE_MM_CARVEOUT,
+	.align = PAGE_SIZE,
 };
 
 static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
 	.permission_type = IPT_TYPE_MFC_SHAREDMEM,
+	.align = PAGE_SIZE,
 };
 
 static struct ion_co_heap_pdata co_ion_pdata = {
+	.adjacent_mem_id = INVALID_HEAP_ID,
+	.align = PAGE_SIZE,
+};
+
+static struct ion_co_heap_pdata fw_co_ion_pdata = {
+	.adjacent_mem_id = ION_CP_MM_HEAP_ID,
+	.align = SZ_128K,
 };
 #endif
 static struct ion_platform_data ion_pdata = {
@@ -233,6 +256,14 @@
 			.extra_data = (void *) &cp_mm_ion_pdata,
 		},
 		{
+			.id	= ION_MM_FIRMWARE_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_MM_FIRMWARE_HEAP_NAME,
+			.size	= MSM_ION_MM_FW_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &fw_co_ion_pdata,
+		},
+		{
 			.id	= ION_CP_MFC_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_MFC_HEAP_NAME,
@@ -245,6 +276,22 @@
 			.type	= ION_HEAP_TYPE_IOMMU,
 			.name	= ION_IOMMU_HEAP_NAME,
 		},
+		{
+			.id	= ION_QSECOM_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_QSECOM_HEAP_NAME,
+			.size	= MSM_ION_QSECOM_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_ion_pdata,
+		},
+		{
+			.id	= ION_AUDIO_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_AUDIO_HEAP_NAME,
+			.size	= MSM_ION_AUDIO_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_ion_pdata,
+		},
 #endif
 	}
 };
@@ -260,16 +307,25 @@
 {
 #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
 	apq8064_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_SIZE;
+	apq8064_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_FW_SIZE;
 	apq8064_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE;
 	apq8064_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MFC_SIZE;
+	apq8064_reserve_table[MEMTYPE_EBI1].size += MSM_ION_QSECOM_SIZE;
+	apq8064_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE;
 #endif
 }
 
+static void __init reserve_mdp_memory(void)
+{
+	apq8064_mdp_writeback(apq8064_reserve_table);
+}
+
 static void __init apq8064_calculate_reserve_sizes(void)
 {
 	size_pmem_devices();
 	reserve_pmem_memory();
 	reserve_ion_memory();
+	reserve_mdp_memory();
 }
 
 static struct reserve_info apq8064_reserve_info __initdata = {
@@ -292,12 +348,19 @@
 	bank_size = apq8064_memory_bank_size();
 	low = meminfo.bank[0].start;
 	high = mb->start + mb->size;
+
+	/* Check if 32 bit overflow occured */
+	if (high < mb->start)
+		high = ~0UL;
+
 	low &= ~(bank_size - 1);
 
 	if (high - low <= bank_size)
 		return;
-	apq8064_reserve_info.low_unstable_address = low + bank_size;
-	apq8064_reserve_info.max_unstable_size = high - low - bank_size;
+	apq8064_reserve_info.low_unstable_address = mb->start -
+					MIN_MEMORY_BLOCK_SIZE + mb->size;
+	apq8064_reserve_info.max_unstable_size = MIN_MEMORY_BLOCK_SIZE;
+
 	apq8064_reserve_info.bank_size = bank_size;
 	pr_info("low unstable address %lx max size %lx bank size %lx\n",
 		apq8064_reserve_info.low_unstable_address,
@@ -312,15 +375,85 @@
 	msm_reserve();
 }
 
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+static struct msm_hsic_host_platform_data msm_hsic_pdata = {
+	.strobe		= 88,
+	.data		= 89,
+};
+#else
+static struct msm_hsic_host_platform_data msm_hsic_pdata;
+#endif
+
+#define PID_MAGIC_ID		0x71432909
+#define SERIAL_NUM_MAGIC_ID	0x61945374
+#define SERIAL_NUMBER_LENGTH	127
+#define DLOAD_USB_BASE_ADD	0x2A03F0C8
+
+struct magic_num_struct {
+	uint32_t pid;
+	uint32_t serial_num;
+};
+
+struct dload_struct {
+	uint32_t	reserved1;
+	uint32_t	reserved2;
+	uint32_t	reserved3;
+	uint16_t	reserved4;
+	uint16_t	pid;
+	char		serial_number[SERIAL_NUMBER_LENGTH];
+	uint16_t	reserved5;
+	struct magic_num_struct magic_struct;
+};
+
+static int usb_diag_update_pid_and_serial_num(uint32_t pid, const char *snum)
+{
+	struct dload_struct __iomem *dload = 0;
+
+	dload = ioremap(DLOAD_USB_BASE_ADD, sizeof(*dload));
+	if (!dload) {
+		pr_err("%s: cannot remap I/O memory region: %08x\n",
+					__func__, DLOAD_USB_BASE_ADD);
+		return -ENXIO;
+	}
+
+	pr_debug("%s: dload:%p pid:%x serial_num:%s\n",
+				__func__, dload, pid, snum);
+	/* update pid */
+	dload->magic_struct.pid = PID_MAGIC_ID;
+	dload->pid = pid;
+
+	/* update serial number */
+	dload->magic_struct.serial_num = 0;
+	if (!snum) {
+		memset(dload->serial_number, 0, SERIAL_NUMBER_LENGTH);
+		goto out;
+	}
+
+	dload->magic_struct.serial_num = SERIAL_NUM_MAGIC_ID;
+	strlcpy(dload->serial_number, snum, SERIAL_NUMBER_LENGTH);
+out:
+	iounmap(dload);
+	return 0;
+}
+
+static struct android_usb_platform_data android_usb_pdata = {
+	.update_pid_and_serial_num = usb_diag_update_pid_and_serial_num,
+};
+
 static struct platform_device android_usb_device = {
-	.name = "android_usb",
-	.id = -1,
+	.name	= "android_usb",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &android_usb_pdata,
+	},
 };
 
 static struct msm_otg_platform_data msm_otg_pdata = {
-	.mode			= USB_PERIPHERAL,
-	.otg_control		= OTG_PHY_CONTROL,
+	.mode			= USB_OTG,
+	.otg_control		= OTG_PMIC_CONTROL,
 	.phy_type		= SNPS_28NM_INTEGRATED_PHY,
+	.pmic_id_irq		= PM8921_USB_ID_IN_IRQ(PM8921_IRQ_BASE),
+	.power_budget		= 750,
 };
 
 #define TABLA_INTERRUPT_BASE (NR_MSM_IRQS + NR_GPIO_IRQS + NR_PM8921_IRQS)
@@ -505,6 +638,11 @@
 };
 #endif
 
+static struct mdm_platform_data mdm_platform_data = {
+	.mdm_version = "3.0",
+	.ramdump_delay_ms = 2000,
+	.peripheral_platform_device = &apq8064_device_hsic_host,
+};
 
 #define MSM_SHARED_RAM_PHYS 0x80000000
 static void __init apq8064_map_io(void)
@@ -517,14 +655,15 @@
 
 static void __init apq8064_init_irq(void)
 {
+	struct msm_mpm_device_data *data = NULL;
+
+#ifdef CONFIG_MSM_MPM
+	data = &apq8064_mpm_dev_data;
+#endif
+
+	msm_mpm_irq_extn_init(data);
 	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
 						(void *)MSM_QGIC_CPU_BASE);
-
-	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-	writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
-	writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-	mb();
 }
 
 static struct platform_device msm8064_device_saw_regulator_core0 = {
@@ -556,6 +695,368 @@
 	.id	= 3,
 	.dev	= {
 		.platform_data = &msm8064_saw_regulator_pdata_8821_s1,
+
+	},
+};
+
+static struct msm_rpmrs_level msm_rpmrs_levels[] __initdata = {
+	{
+		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
+		MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
+		true,
+		100, 8000, 100000, 1,
+	},
+
+	{
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE,
+		MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
+		true,
+		2000, 6000, 60100000, 3000,
+	},
+
+	{
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+		MSM_RPMRS_LIMITS(ON, GDHS, MAX, ACTIVE),
+		false,
+		4200, 5000, 60350000, 3500,
+	},
+
+	{
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+		MSM_RPMRS_LIMITS(ON, HSFS_OPEN, MAX, ACTIVE),
+		false,
+		6300, 4500, 65350000, 4800,
+	},
+
+	{
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+		MSM_RPMRS_LIMITS(OFF, GDHS, MAX, ACTIVE),
+		false,
+		11700, 2500, 67850000, 5500,
+	},
+
+	{
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+		MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, MAX, ACTIVE),
+		false,
+		13800, 2000, 71850000, 6800,
+	},
+
+	{
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+		MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, ACTIVE, RET_HIGH),
+		false,
+		29700, 500, 75850000, 8800,
+	},
+
+	{
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+		MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, RET_HIGH, RET_LOW),
+		false,
+		29700, 0, 76350000, 9800,
+	},
+};
+
+static struct msm_pm_boot_platform_data msm_pm_boot_pdata __initdata = {
+	.mode = MSM_PM_BOOT_CONFIG_TZ,
+};
+
+static struct msm_rpmrs_platform_data msm_rpmrs_data __initdata = {
+	.levels = &msm_rpmrs_levels[0],
+	.num_levels = ARRAY_SIZE(msm_rpmrs_levels),
+	.vdd_mem_levels  = {
+		[MSM_RPMRS_VDD_MEM_RET_LOW]	= 750000,
+		[MSM_RPMRS_VDD_MEM_RET_HIGH]	= 750000,
+		[MSM_RPMRS_VDD_MEM_ACTIVE]	= 1050000,
+		[MSM_RPMRS_VDD_MEM_MAX]		= 1150000,
+	},
+	.vdd_dig_levels = {
+		[MSM_RPMRS_VDD_DIG_RET_LOW]	= 500000,
+		[MSM_RPMRS_VDD_DIG_RET_HIGH]	= 750000,
+		[MSM_RPMRS_VDD_DIG_ACTIVE]	= 950000,
+		[MSM_RPMRS_VDD_DIG_MAX]		= 1150000,
+	},
+	.vdd_mask = 0x7FFFFF,
+	.rpmrs_target_id = {
+		[MSM_RPMRS_ID_PXO_CLK]		= MSM_RPM_ID_PXO_CLK,
+		[MSM_RPMRS_ID_L2_CACHE_CTL]	= MSM_RPM_ID_LAST,
+		[MSM_RPMRS_ID_VDD_DIG_0]	= MSM_RPM_ID_PM8921_S3_0,
+		[MSM_RPMRS_ID_VDD_DIG_1]	= MSM_RPM_ID_PM8921_S3_1,
+		[MSM_RPMRS_ID_VDD_MEM_0]	= MSM_RPM_ID_PM8921_L24_0,
+		[MSM_RPMRS_ID_VDD_MEM_1]	= MSM_RPM_ID_PM8921_L24_1,
+		[MSM_RPMRS_ID_RPM_CTL]		= MSM_RPM_ID_RPM_CTL,
+	},
+};
+
+static struct msm_cpuidle_state msm_cstates[] __initdata = {
+	{0, 0, "C0", "WFI",
+		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
+
+	{0, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
+
+	{0, 2, "C2", "POWER_COLLAPSE",
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE},
+
+	{1, 0, "C0", "WFI",
+		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
+
+	{1, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
+
+	{2, 0, "C0", "WFI",
+		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
+
+	{2, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
+
+	{3, 0, "C0", "WFI",
+		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
+
+	{3, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
+};
+
+static struct msm_pm_platform_data msm_pm_data[] = {
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
+		.idle_supported = 1,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+		.idle_supported = 1,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+		.idle_supported = 1,
+		.suspend_supported = 1,
+		.idle_enabled = 1,
+		.suspend_enabled = 1,
+	},
+
+	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
+		.idle_supported = 0,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+		.idle_supported = 1,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+		.idle_supported = 1,
+		.suspend_supported = 0,
+		.idle_enabled = 1,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
+		.idle_supported = 0,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+		.idle_supported = 1,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+		.idle_supported = 1,
+		.suspend_supported = 0,
+		.idle_enabled = 1,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
+		.idle_supported = 0,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+		.idle_supported = 1,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+		.idle_supported = 1,
+		.suspend_supported = 0,
+		.idle_enabled = 1,
+		.suspend_enabled = 0,
+	},
+};
+
+static uint8_t spm_wfi_cmd_sequence[] __initdata = {
+	0x03, 0x0f,
+};
+
+static uint8_t spm_power_collapse_without_rpm[] __initdata = {
+	0x00, 0x24, 0x54, 0x10,
+	0x09, 0x03, 0x01,
+	0x10, 0x54, 0x30, 0x0C,
+	0x24, 0x30, 0x0f,
+};
+
+static uint8_t spm_power_collapse_with_rpm[] __initdata = {
+	0x00, 0x24, 0x54, 0x10,
+	0x09, 0x07, 0x01, 0x0B,
+	0x10, 0x54, 0x30, 0x0C,
+	0x24, 0x30, 0x0f,
+};
+
+static struct msm_spm_seq_entry msm_spm_seq_list[] __initdata = {
+	[0] = {
+		.mode = MSM_SPM_MODE_CLOCK_GATING,
+		.notify_rpm = false,
+		.cmd = spm_wfi_cmd_sequence,
+	},
+	[1] = {
+		.mode = MSM_SPM_MODE_POWER_COLLAPSE,
+		.notify_rpm = false,
+		.cmd = spm_power_collapse_without_rpm,
+	},
+	[2] = {
+		.mode = MSM_SPM_MODE_POWER_COLLAPSE,
+		.notify_rpm = true,
+		.cmd = spm_power_collapse_with_rpm,
+	},
+};
+
+static uint8_t l2_spm_wfi_cmd_sequence[] __initdata = {
+	0x00, 0x20, 0x03, 0x20,
+	0x00, 0x0f,
+};
+
+static uint8_t l2_spm_gdhs_cmd_sequence[] __initdata = {
+	0x00, 0x20, 0x34, 0x64,
+	0x48, 0x07, 0x48, 0x20,
+	0x50, 0x64, 0x04, 0x34,
+	0x50, 0x0f,
+};
+static uint8_t l2_spm_power_off_cmd_sequence[] __initdata = {
+	0x00, 0x10, 0x34, 0x64,
+	0x48, 0x07, 0x48, 0x10,
+	0x50, 0x64, 0x04, 0x34,
+	0x50, 0x0F,
+};
+
+static struct msm_spm_seq_entry msm_spm_l2_seq_list[] __initdata = {
+	[0] = {
+		.mode = MSM_SPM_L2_MODE_RETENTION,
+		.notify_rpm = false,
+		.cmd = l2_spm_wfi_cmd_sequence,
+	},
+	[1] = {
+		.mode = MSM_SPM_L2_MODE_GDHS,
+		.notify_rpm = true,
+		.cmd = l2_spm_gdhs_cmd_sequence,
+	},
+	[2] = {
+		.mode = MSM_SPM_L2_MODE_POWER_COLLAPSE,
+		.notify_rpm = true,
+		.cmd = l2_spm_power_off_cmd_sequence,
+	},
+};
+
+
+static struct msm_spm_platform_data msm_spm_l2_data[] __initdata = {
+	[0] = {
+		.reg_base_addr = MSM_SAW_L2_BASE,
+		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
+		.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x00,
+		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x00A000AE,
+		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x00A00020,
+		.modes = msm_spm_l2_seq_list,
+		.num_modes = ARRAY_SIZE(msm_spm_l2_seq_list),
+	},
+};
+
+static struct msm_spm_platform_data msm_spm_data[] __initdata = {
+	[0] = {
+		.reg_base_addr = MSM_SAW0_BASE,
+		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
+		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
+		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
+#if defined(CONFIG_MSM_AVS_HW)
+		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
+		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
+#endif
+		.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
+		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
+		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
+		.vctl_timeout_us = 50,
+		.num_modes = ARRAY_SIZE(msm_spm_seq_list),
+		.modes = msm_spm_seq_list,
+	},
+	[1] = {
+		.reg_base_addr = MSM_SAW1_BASE,
+		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
+		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
+		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
+#if defined(CONFIG_MSM_AVS_HW)
+		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
+		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
+#endif
+		.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
+		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
+		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
+		.vctl_timeout_us = 50,
+		.num_modes = ARRAY_SIZE(msm_spm_seq_list),
+		.modes = msm_spm_seq_list,
+	},
+	[2] = {
+		.reg_base_addr = MSM_SAW2_BASE,
+		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
+		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
+		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
+#if defined(CONFIG_MSM_AVS_HW)
+		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
+		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
+#endif
+		.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
+		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
+		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
+		.vctl_timeout_us = 50,
+		.num_modes = ARRAY_SIZE(msm_spm_seq_list),
+		.modes = msm_spm_seq_list,
+	},
+	[3] = {
+		.reg_base_addr = MSM_SAW3_BASE,
+		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
+		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
+		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
+#if defined(CONFIG_MSM_AVS_HW)
+		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
+		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
+#endif
+		.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
+		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
+		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
+		.vctl_timeout_us = 50,
+		.num_modes = ARRAY_SIZE(msm_spm_seq_list),
+		.modes = msm_spm_seq_list,
 	},
 };
 
@@ -575,16 +1076,38 @@
 	msm_bus_8064_cpss_fpb.dev.platform_data = &msm_bus_8064_cpss_fpb_pdata;
 }
 
+static struct platform_device apq8064_device_ext_5v_vreg __devinitdata = {
+	.name	= GPIO_REGULATOR_DEV_NAME,
+	.id	= PM8921_MPP_PM_TO_SYS(7),
+	.dev	= {
+		.platform_data
+			= &apq8064_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V],
+	},
+};
+
+static struct platform_device apq8064_device_ext_3p3v_vreg __devinitdata = {
+	.name	= GPIO_REGULATOR_DEV_NAME,
+	.id	= APQ8064_EXT_3P3V_REG_EN_GPIO,
+	.dev	= {
+		.platform_data =
+			&apq8064_gpio_regulator_pdata[GPIO_VREG_ID_EXT_3P3V],
+	},
+};
+
 static struct platform_device *common_devices[] __initdata = {
 	&apq8064_device_dmov,
 	&apq8064_device_qup_i2c_gsbi4,
 	&apq8064_device_qup_spi_gsbi5,
 	&apq8064_slim_ctrl,
+	&apq8064_device_ext_5v_vreg,
+	&apq8064_device_ext_3p3v_vreg,
 	&apq8064_device_ssbi_pmic1,
 	&apq8064_device_ssbi_pmic2,
 	&msm_device_smd_apq8064,
 	&apq8064_device_otg,
 	&apq8064_device_gadget_peripheral,
+	&apq8064_device_hsusb_host,
+	&apq8064_device_hsic_host,
 	&android_usb_device,
 #ifdef CONFIG_ANDROID_PMEM
 #ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -636,11 +1159,18 @@
 	&apq_pcm_afe,
 	&apq_cpudai_auxpcm_rx,
 	&apq_cpudai_auxpcm_tx,
+	&apq8064_rpm_device,
+	&apq8064_rpm_log_device,
+	&apq8064_rpm_stat_device,
 	&msm_bus_8064_apps_fabric,
 	&msm_bus_8064_sys_fabric,
 	&msm_bus_8064_mm_fabric,
 	&msm_bus_8064_sys_fpb,
 	&msm_bus_8064_cpss_fpb,
+	&msm_device_vidc,
+	&msm_8960_riva,
+	&msm_8960_q6_lpass,
+	&msm_gss,
 };
 
 static struct platform_device *sim_devices[] __initdata = {
@@ -651,10 +1181,19 @@
 static struct platform_device *rumi3_devices[] __initdata = {
 	&apq8064_device_uart_gsbi1,
 	&msm_device_sps_apq8064,
+#ifdef CONFIG_MSM_ROTATOR
+	&msm_rotator_device,
+#endif
+};
+
+static struct platform_device *cdp_devices[] __initdata = {
+	&apq8064_device_uart_gsbi1,
+	&apq8064_device_uart_gsbi7,
+	&msm_device_sps_apq8064,
 };
 
 static struct msm_spi_platform_data apq8064_qup_spi_gsbi5_pdata = {
-	.max_clock_speed = 24000000,
+	.max_clock_speed = 1100000,
 };
 
 #define KS8851_IRQ_GPIO		43
@@ -693,7 +1232,7 @@
 					&apq8064_i2c_qup_gsbi4_pdata;
 }
 
-#ifdef CONFIG_KS8851
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
 static int ethernet_init(void)
 {
 	int ret;
@@ -716,16 +1255,18 @@
 
 static void __init apq8064_clock_init(void)
 {
-	if (machine_is_apq8064_sim())
-		msm_clock_init(&apq8064_clock_init_data);
-	else
+	if (machine_is_apq8064_rumi3())
 		msm_clock_init(&apq8064_dummy_clock_init_data);
+	else
+		msm_clock_init(&apq8064_clock_init_data);
 }
 
 static void __init apq8064_common_init(void)
 {
 	if (socinfo_init() < 0)
 		pr_err("socinfo_init() failed!\n");
+	BUG_ON(msm_rpm_init(&apq8064_rpm_data));
+	BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
 	apq8064_clock_init();
 	apq8064_init_gpiomux();
 	apq8064_i2c_init();
@@ -733,12 +1274,34 @@
 	apq8064_device_qup_spi_gsbi5.dev.platform_data =
 						&apq8064_qup_spi_gsbi5_pdata;
 	apq8064_init_pmic();
+	if (machine_is_apq8064_liquid())
+		msm_otg_pdata.mhl_enable = true;
 	apq8064_device_otg.dev.platform_data = &msm_otg_pdata;
+	apq8064_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
 	apq8064_init_buses();
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
+	apq8064_pm8xxx_gpio_mpp_init();
 	apq8064_init_mmc();
 	slim_register_board_info(apq8064_slim_devices,
 		ARRAY_SIZE(apq8064_slim_devices));
+	msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
+	acpuclk_init(&acpuclk_8064_soc_data);
+	msm_spm_l2_init(msm_spm_l2_data);
+	msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
+	msm_pm_set_rpm_wakeup_irq(RPM_APCC_CPU0_WAKE_UP_IRQ);
+	msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
+				msm_pm_data);
+	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
+
+	if (machine_is_apq8064_mtp()) {
+		mdm_8064_device.dev.platform_data = &mdm_platform_data;
+		platform_device_register(&mdm_8064_device);
+	}
+}
+
+static void __init apq8064_allocate_memory_regions(void)
+{
+	apq8064_allocate_fb_region();
 }
 
 static void __init apq8064_sim_init(void)
@@ -757,6 +1320,17 @@
 	ethernet_init();
 	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)
+{
+	apq8064_common_init();
+	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")
@@ -775,5 +1349,33 @@
 	.handle_irq = gic_handle_irq,
 	.timer = &msm_timer,
 	.init_machine = apq8064_rumi3_init,
+	.init_early = apq8064_allocate_memory_regions,
+MACHINE_END
+
+MACHINE_START(APQ8064_CDP, "QCT APQ8064 CDP")
+	.map_io = apq8064_map_io,
+	.reserve = apq8064_reserve,
+	.init_irq = apq8064_init_irq,
+	.handle_irq = gic_handle_irq,
+	.timer = &msm_timer,
+	.init_machine = apq8064_cdp_init,
+MACHINE_END
+
+MACHINE_START(APQ8064_MTP, "QCT APQ8064 MTP")
+	.map_io = apq8064_map_io,
+	.reserve = apq8064_reserve,
+	.init_irq = apq8064_init_irq,
+	.handle_irq = gic_handle_irq,
+	.timer = &msm_timer,
+	.init_machine = apq8064_cdp_init,
+MACHINE_END
+
+MACHINE_START(APQ8064_LIQUID, "QCT APQ8064 LIQUID")
+	.map_io = apq8064_map_io,
+	.reserve = apq8064_reserve,
+	.init_irq = apq8064_init_irq,
+	.handle_irq = gic_handle_irq,
+	.timer = &msm_timer,
+	.init_machine = apq8064_cdp_init,
 MACHINE_END
 
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index 98f453b..e1451f5 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.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,8 +13,11 @@
 #ifndef __ARCH_ARM_MACH_MSM_BOARD_APQ8064_H
 #define __ARCH_ARM_MACH_MSM_BOARD_APQ8064_H
 
+#include <linux/regulator/gpio-regulator.h>
 #include <linux/mfd/pm8xxx/pm8921.h>
 #include <linux/mfd/pm8xxx/pm8821.h>
+#include <mach/msm_memtypes.h>
+#include <mach/irqs.h>
 
 /* Macros assume PMIC GPIOs and MPPs start at 1 */
 #define PM8921_GPIO_BASE		NR_GPIO_IRQS
@@ -32,6 +35,14 @@
 
 extern int msm8064_pm8921_regulator_pdata_len __devinitdata;
 
+#define GPIO_VREG_ID_EXT_5V		0
+#define GPIO_VREG_ID_EXT_3P3V		1
+
+#define APQ8064_EXT_3P3V_REG_EN_GPIO	77
+
+extern struct gpio_regulator_platform_data
+	apq8064_gpio_regulator_pdata[] __devinitdata;
+
 extern struct regulator_init_data msm8064_saw_regulator_pdata_8921_s5;
 extern struct regulator_init_data msm8064_saw_regulator_pdata_8921_s6;
 extern struct regulator_init_data msm8064_saw_regulator_pdata_8821_s0;
@@ -44,4 +55,16 @@
 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
+
+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);
+void apq8064_pm8xxx_gpio_mpp_init(void);
+
 #endif
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index 6b5f917..8212e15 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,9 +12,9 @@
  */
 
 #include <asm/mach-types.h>
+#include <linux/gpio.h>
 #include <mach/board.h>
 #include <mach/msm_bus_board.h>
-#include <mach/gpio.h>
 #include <mach/gpiomux.h>
 #include "devices.h"
 #include "board-8930.h"
@@ -95,7 +95,7 @@
 };
 
 
-static struct msm_gpiomux_config msm8960_cam_common_configs[] = {
+static struct msm_gpiomux_config msm8930_cam_common_configs[] = {
 	{
 		.gpio = 2,
 		.settings = {
@@ -140,7 +140,7 @@
 	},
 };
 
-static struct msm_gpiomux_config msm8960_cam_2d_configs[] = {
+static struct msm_gpiomux_config msm8930_cam_2d_configs[] = {
 	{
 		.gpio = 18,
 		.settings = {
@@ -172,20 +172,6 @@
 };
 
 #ifdef CONFIG_MSM_CAMERA
-
-static uint16_t msm_cam_gpio_2d_tbl[] = {
-	5, /*CAMIF_MCLK*/
-	20, /*CAMIF_I2C_DATA*/
-	21, /*CAMIF_I2C_CLK*/
-};
-
-static struct msm_camera_gpio_conf gpio_conf = {
-	.cam_gpiomux_conf_tbl = msm8960_cam_2d_configs,
-	.cam_gpiomux_conf_tbl_size = ARRAY_SIZE(msm8960_cam_2d_configs),
-	.cam_gpio_tbl = msm_cam_gpio_2d_tbl,
-	.cam_gpio_tbl_size = ARRAY_SIZE(msm_cam_gpio_2d_tbl),
-};
-
 #define VFE_CAMIF_TIMER1_GPIO 2
 #define VFE_CAMIF_TIMER2_GPIO 3
 #define VFE_CAMIF_TIMER3_GPIO_INT 4
@@ -345,19 +331,84 @@
 
 static struct msm_camera_device_platform_data msm_camera_csi_device_data[] = {
 	{
-		.ioclk.mclk_clk_rate = 24000000,
-		.ioclk.vfe_clk_rate  = 228570000,
 		.csid_core = 0,
+		.is_csiphy = 1,
+		.is_csid   = 1,
+		.is_ispif  = 1,
+		.is_vpe    = 1,
 		.cam_bus_scale_table = &cam_bus_client_pdata,
 	},
 	{
-		.ioclk.mclk_clk_rate = 24000000,
-		.ioclk.vfe_clk_rate  = 228570000,
 		.csid_core = 1,
+		.is_csiphy = 1,
+		.is_csid   = 1,
+		.is_ispif  = 1,
+		.is_vpe    = 1,
 		.cam_bus_scale_table = &cam_bus_client_pdata,
 	},
 };
 
+static struct camera_vreg_t msm_8930_back_cam_vreg[] = {
+	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+	{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
+};
+
+static struct camera_vreg_t msm_8930_front_cam_vreg[] = {
+	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+	{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+};
+
+static struct gpio msm8930_common_cam_gpio[] = {
+	{5, GPIOF_DIR_IN, "CAMIF_MCLK"},
+	{20, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
+	{21, GPIOF_DIR_IN, "CAMIF_I2C_CLK"},
+};
+
+static struct gpio msm8930_front_cam_gpio[] = {
+	{76, GPIOF_DIR_OUT, "CAM_RESET"},
+};
+
+static struct gpio msm8930_back_cam_gpio[] = {
+	{107, GPIOF_DIR_OUT, "CAM_RESET"},
+};
+
+static struct msm_gpio_set_tbl msm8930_front_cam_gpio_set_tbl[] = {
+	{76, GPIOF_OUT_INIT_LOW, 1000},
+	{76, GPIOF_OUT_INIT_HIGH, 4000},
+};
+
+static struct msm_gpio_set_tbl msm8930_back_cam_gpio_set_tbl[] = {
+	{107, GPIOF_OUT_INIT_LOW, 1000},
+	{107, GPIOF_OUT_INIT_HIGH, 4000},
+};
+
+static struct msm_camera_gpio_conf msm_8930_front_cam_gpio_conf = {
+	.cam_gpiomux_conf_tbl = msm8930_cam_2d_configs,
+	.cam_gpiomux_conf_tbl_size = ARRAY_SIZE(msm8930_cam_2d_configs),
+	.cam_gpio_common_tbl = msm8930_common_cam_gpio,
+	.cam_gpio_common_tbl_size = ARRAY_SIZE(msm8930_common_cam_gpio),
+	.cam_gpio_req_tbl = msm8930_front_cam_gpio,
+	.cam_gpio_req_tbl_size = ARRAY_SIZE(msm8930_front_cam_gpio),
+	.cam_gpio_set_tbl = msm8930_front_cam_gpio_set_tbl,
+	.cam_gpio_set_tbl_size = ARRAY_SIZE(msm8930_front_cam_gpio_set_tbl),
+};
+
+static struct msm_camera_gpio_conf msm_8930_back_cam_gpio_conf = {
+	.cam_gpiomux_conf_tbl = msm8930_cam_2d_configs,
+	.cam_gpiomux_conf_tbl_size = ARRAY_SIZE(msm8930_cam_2d_configs),
+	.cam_gpio_common_tbl = msm8930_common_cam_gpio,
+	.cam_gpio_common_tbl_size = ARRAY_SIZE(msm8930_common_cam_gpio),
+	.cam_gpio_req_tbl = msm8930_back_cam_gpio,
+	.cam_gpio_req_tbl_size = ARRAY_SIZE(msm8930_back_cam_gpio),
+	.cam_gpio_set_tbl = msm8930_back_cam_gpio_set_tbl,
+	.cam_gpio_set_tbl_size = ARRAY_SIZE(msm8930_back_cam_gpio_set_tbl),
+};
+
 #ifdef CONFIG_IMX074_ACT
 static struct i2c_board_info imx074_actuator_i2c_info = {
 	I2C_BOARD_INFO("imx074_act", 0x11),
@@ -381,10 +432,9 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
 	.mount_angle	= 90,
-	.sensor_reset	= 107,
-	.sensor_pwd	= 85,
-	.vcm_pwd	= 0,
-	.vcm_enable	= 1,
+	.cam_vreg = msm_8930_back_cam_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8930_back_cam_vreg),
+	.gpio_conf = &msm_8930_back_cam_gpio_conf,
 };
 
 static struct msm_camera_sensor_info msm_camera_sensor_imx074_data = {
@@ -393,7 +443,6 @@
 	.flash_data	= &flash_imx074,
 	.strobe_flash_data = &strobe_flash_xenon,
 	.sensor_platform_info = &sensor_board_info_imx074,
-	.gpio_conf = &gpio_conf,
 	.csi_if	= 1,
 	.camera_type = BACK_CAMERA_2D,
 #ifdef CONFIG_IMX074_ACT
@@ -409,7 +458,9 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_mt9m114 = {
 	.mount_angle = 90,
-	.sensor_reset = 107,
+	.cam_vreg = msm_8930_back_cam_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8930_back_cam_vreg),
+	.gpio_conf = &msm_8930_back_cam_gpio_conf,
 };
 
 static struct msm_camera_sensor_info msm_camera_sensor_mt9m114_data = {
@@ -417,7 +468,6 @@
 	.pdata = &msm_camera_csi_device_data[0],
 	.flash_data = &flash_mt9m114,
 	.sensor_platform_info = &sensor_board_info_mt9m114,
-	.gpio_conf = &gpio_conf,
 	.csi_if = 1,
 	.camera_type = BACK_CAMERA_2D,
 };
@@ -430,10 +480,9 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_ov2720 = {
 	.mount_angle	= 0,
-	.sensor_reset	= 76,
-	.sensor_pwd	= 85,
-	.vcm_pwd	= 0,
-	.vcm_enable	= 1,
+	.cam_vreg = msm_8930_front_cam_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8930_front_cam_vreg),
+	.gpio_conf = &msm_8930_front_cam_gpio_conf,
 };
 
 static struct msm_camera_sensor_info msm_camera_sensor_ov2720_data = {
@@ -441,16 +490,43 @@
 	.pdata	= &msm_camera_csi_device_data[1],
 	.flash_data	= &flash_ov2720,
 	.sensor_platform_info = &sensor_board_info_ov2720,
-	.gpio_conf = &gpio_conf,
 	.csi_if	= 1,
 	.camera_type = FRONT_CAMERA_2D,
 };
 #endif
 
+static struct camera_vreg_t msm_8930_s5k3l1yx_vreg[] = {
+	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+	{"cam_vio", REG_VS, 0, 0, 0},
+	{"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
+};
+
+static struct msm_camera_sensor_flash_data flash_s5k3l1yx = {
+	.flash_type = MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_s5k3l1yx = {
+	.mount_angle  = 0,
+	.cam_vreg = msm_8930_s5k3l1yx_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8930_s5k3l1yx_vreg),
+	.gpio_conf = &msm_8930_back_cam_gpio_conf,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_s5k3l1yx_data = {
+	.sensor_name          = "s5k3l1yx",
+	.pdata                = &msm_camera_csi_device_data[0],
+	.flash_data           = &flash_s5k3l1yx,
+	.sensor_platform_info = &sensor_board_info_s5k3l1yx,
+	.csi_if               = 1,
+	.camera_type          = BACK_CAMERA_2D,
+};
+
 void __init msm8930_init_cam(void)
 {
-	msm_gpiomux_install(msm8960_cam_common_configs,
-			ARRAY_SIZE(msm8960_cam_common_configs));
+	msm_gpiomux_install(msm8930_cam_common_configs,
+			ARRAY_SIZE(msm8930_cam_common_configs));
 
 	platform_device_register(&msm8960_device_csiphy0);
 	platform_device_register(&msm8960_device_csiphy1);
@@ -479,6 +555,10 @@
 	I2C_BOARD_INFO("mt9m114", 0x48),
 	.platform_data = &msm_camera_sensor_mt9m114_data,
 	},
+	{
+	I2C_BOARD_INFO("s5k3l1yx", 0x20),
+	.platform_data = &msm_camera_sensor_s5k3l1yx_data,
+	},
 #ifdef CONFIG_MSM_CAMERA_FLASH_SC628A
 	{
 	I2C_BOARD_INFO("sc628a", 0x6E),
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index 23c94c4..d871e04 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -26,15 +26,7 @@
 #include <mach/ion.h>
 
 #include "devices.h"
-
-/* TODO: Remove this once PM8038 physically becomes
- * available.
- */
-#ifndef MSM8930_PHASE_2
-#include "board-8960.h"
-#else
 #include "board-8930.h"
-#endif
 
 #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
 #define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 3) /* 4 bpp x 3 pages */
@@ -156,7 +148,7 @@
 	static struct regulator *reg_l8, *reg_l23, *reg_l2;
 	int rc;
 
-	pr_info("%s: state : %d\n", __func__, on);
+	pr_debug("%s: state : %d\n", __func__, on);
 
 	if (!dsi_power_on) {
 
@@ -236,6 +228,11 @@
 			pr_err("enable l2 failed, rc=%d\n", rc);
 			return -ENODEV;
 		}
+		usleep(10000);
+		gpio_set_value(DISP_RST_GPIO, 1);
+		usleep(10);
+		gpio_set_value(DISP_RST_GPIO, 0);
+		usleep(20);
 		gpio_set_value(DISP_RST_GPIO, 1);
 	} else {
 
@@ -277,7 +274,7 @@
 
 static int mipi_dsi_panel_power(int on)
 {
-	pr_info("%s: on=%d\n", __func__, on);
+	pr_debug("%s: on=%d\n", __func__, on);
 
 	return mipi_dsi_cdp_panel_power(on);
 }
@@ -494,6 +491,7 @@
 	.fpga_3d_config_addr  = FPGA_3D_GPIO_CONFIG_ADDR,
 	.fpga_ctrl_mode = FPGA_SPI_INTF,
 	.phy_ctrl_settings = &dsi_novatek_cmd_mode_phy_db,
+	.dlane_swap = 0x1,
 };
 
 static struct platform_device mipi_dsi_novatek_panel_device = {
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index fc9b58f..2f9fdcd 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -30,6 +30,10 @@
 	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"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",        "4-0020"),
 };
 VREG_CONSUMERS(L3) = {
 	REGULATOR_SUPPLY("8038_l3",		NULL),
@@ -59,6 +63,14 @@
 	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"),
+	REGULATOR_SUPPLY("cam_vana",            "4-0020"),
+	REGULATOR_SUPPLY("cam_vaf",             "4-0020"),
 };
 VREG_CONSUMERS(L10) = {
 	REGULATOR_SUPPLY("8038_l10",		NULL),
@@ -70,12 +82,20 @@
 	REGULATOR_SUPPLY("iris_vddio",		"wcnss_wlan.0"),
 	REGULATOR_SUPPLY("riva_vddpx",		"wcnss_wlan.0"),
 	REGULATOR_SUPPLY("sdc_vccq",		"msm_sdcc.1"),
+	REGULATOR_SUPPLY("VDDIO_CDC",		"sitar-slim"),
+	REGULATOR_SUPPLY("CDC_VDDA_TX",		"sitar-slim"),
+	REGULATOR_SUPPLY("CDC_VDDA_RX",		"sitar-slim"),
 };
 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"),
+	REGULATOR_SUPPLY("cam_vdig",            "4-0020"),
 };
 VREG_CONSUMERS(L14) = {
 	REGULATOR_SUPPLY("8038_l14",		NULL),
+	REGULATOR_SUPPLY("pa_therm",		"pm8xxx-adc"),
 };
 VREG_CONSUMERS(L15) = {
 	REGULATOR_SUPPLY("8038_l15",		NULL),
@@ -89,6 +109,10 @@
 };
 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"),
+	REGULATOR_SUPPLY("cam_vio",             "4-0020"),
 };
 VREG_CONSUMERS(L19) = {
 	REGULATOR_SUPPLY("8038_l19",		NULL),
@@ -96,6 +120,8 @@
 };
 VREG_CONSUMERS(L20) = {
 	REGULATOR_SUPPLY("8038_l20",		NULL),
+	REGULATOR_SUPPLY("VDDD_CDC_D",		"sitar-slim"),
+	REGULATOR_SUPPLY("CDC_VDDA_A_1P2V",	"sitar-slim"),
 };
 VREG_CONSUMERS(L21) = {
 	REGULATOR_SUPPLY("8038_l21",		NULL),
@@ -109,6 +135,9 @@
 	REGULATOR_SUPPLY("dsi_vddio",		"mipi_dsi.1"),
 	REGULATOR_SUPPLY("hdmi_avdd",		"hdmi_msm.0"),
 	REGULATOR_SUPPLY("hdmi_vcc",		"hdmi_msm.0"),
+	REGULATOR_SUPPLY("pll_vdd",		"pil_riva"),
+	REGULATOR_SUPPLY("pll_vdd",		"pil_qdsp6v4.1"),
+	REGULATOR_SUPPLY("pll_vdd",		"pil_qdsp6v4.2"),
 };
 VREG_CONSUMERS(L24) = {
 	REGULATOR_SUPPLY("8038_l24",		NULL),
@@ -134,6 +163,7 @@
 };
 VREG_CONSUMERS(S4) = {
 	REGULATOR_SUPPLY("8038_s4",		NULL),
+	REGULATOR_SUPPLY("CDC_VDD_CP",		"sitar-slim"),
 };
 VREG_CONSUMERS(S5) = {
 	REGULATOR_SUPPLY("8038_s5",		NULL),
@@ -256,6 +286,97 @@
 		.pin_ctrl	= _pin_ctrl, \
 	}
 
+#define RPM_INIT(_id, _min_uV, _max_uV, _modes, _ops, _apply_uV, _default_uV, \
+		 _peak_uA, _avg_uA, _pull_down, _pin_ctrl, _freq, _pin_fn, \
+		 _force_mode, _power_mode, _state, _sleep_selectable, \
+		 _always_on, _supply_regulator, _system_uA) \
+	{ \
+		.init_data = { \
+			.constraints = { \
+				.valid_modes_mask	= _modes, \
+				.valid_ops_mask		= _ops, \
+				.min_uV			= _min_uV, \
+				.max_uV			= _max_uV, \
+				.input_uV		= _min_uV, \
+				.apply_uV		= _apply_uV, \
+				.always_on		= _always_on, \
+			}, \
+			.num_consumer_supplies	= \
+					ARRAY_SIZE(vreg_consumers_##_id), \
+			.consumer_supplies	= vreg_consumers_##_id, \
+			.supply_regulator	= _supply_regulator, \
+		}, \
+		.id			= RPM_VREG_ID_PM8038_##_id, \
+		.default_uV		= _default_uV, \
+		.peak_uA		= _peak_uA, \
+		.avg_uA			= _avg_uA, \
+		.pull_down_enable	= _pull_down, \
+		.pin_ctrl		= _pin_ctrl, \
+		.freq			= RPM_VREG_FREQ_##_freq, \
+		.pin_fn			= _pin_fn, \
+		.force_mode		= _force_mode, \
+		.power_mode		= _power_mode, \
+		.state			= _state, \
+		.sleep_selectable	= _sleep_selectable, \
+		.system_uA		= _system_uA, \
+	}
+
+#define RPM_LDO(_id, _always_on, _pd, _sleep_selectable, _min_uV, _max_uV, \
+		_supply_regulator, _system_uA, _init_peak_uA) \
+	RPM_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_NORMAL \
+		 | REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE \
+		 | REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE \
+		 | REGULATOR_CHANGE_DRMS, 0, _max_uV, _init_peak_uA, 0, _pd, \
+		 RPM_VREG_PIN_CTRL_NONE, NONE, RPM_VREG_PIN_FN_8930_NONE, \
+		 RPM_VREG_FORCE_MODE_8930_NONE, RPM_VREG_POWER_MODE_8930_PWM, \
+		 RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
+		 _supply_regulator, _system_uA)
+
+#define RPM_SMPS(_id, _always_on, _pd, _sleep_selectable, _min_uV, _max_uV, \
+		 _supply_regulator, _system_uA, _freq) \
+	RPM_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_NORMAL \
+		 | REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE \
+		 | REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE \
+		 | REGULATOR_CHANGE_DRMS, 0, _max_uV, _system_uA, 0, _pd, \
+		 RPM_VREG_PIN_CTRL_NONE, _freq, RPM_VREG_PIN_FN_8930_NONE, \
+		 RPM_VREG_FORCE_MODE_8930_NONE, RPM_VREG_POWER_MODE_8930_PWM, \
+		 RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
+		 _supply_regulator, _system_uA)
+
+#define RPM_VS(_id, _always_on, _pd, _sleep_selectable, _supply_regulator) \
+	RPM_INIT(_id, 0, 0, 0, REGULATOR_CHANGE_STATUS, 0, 0, 1000, 1000, _pd, \
+		 RPM_VREG_PIN_CTRL_NONE, NONE, RPM_VREG_PIN_FN_8930_NONE, \
+		 RPM_VREG_FORCE_MODE_8930_NONE, RPM_VREG_POWER_MODE_8930_PWM, \
+		 RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
+		 _supply_regulator, 0)
+
+#define RPM_NCP(_id, _always_on, _sleep_selectable, _min_uV, _max_uV, \
+		_supply_regulator, _freq) \
+	RPM_INIT(_id, _min_uV, _max_uV, 0, REGULATOR_CHANGE_VOLTAGE \
+		 | REGULATOR_CHANGE_STATUS, 0, _max_uV, 1000, 1000, 0, \
+		 RPM_VREG_PIN_CTRL_NONE, _freq, RPM_VREG_PIN_FN_8930_NONE, \
+		 RPM_VREG_FORCE_MODE_8930_NONE, RPM_VREG_POWER_MODE_8930_PWM, \
+		 RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
+		 _supply_regulator, 0)
+
+/* Pin control initialization */
+#define RPM_PC_INIT(_id, _always_on, _pin_fn, _pin_ctrl, _supply_regulator) \
+	{ \
+		.init_data = { \
+			.constraints = { \
+				.valid_ops_mask	= REGULATOR_CHANGE_STATUS, \
+				.always_on	= _always_on, \
+			}, \
+			.num_consumer_supplies	= \
+					ARRAY_SIZE(vreg_consumers_##_id##_PC), \
+			.consumer_supplies	= vreg_consumers_##_id##_PC, \
+			.supply_regulator	= _supply_regulator, \
+		}, \
+		.id	  = RPM_VREG_ID_PM8038_##_id##_PC, \
+		.pin_fn	  = RPM_VREG_PIN_FN_8930_##_pin_fn, \
+		.pin_ctrl = _pin_ctrl, \
+	}
+
 #define GPIO_VREG(_id, _reg_name, _gpio_label, _gpio, _supply_regulator) \
 	[MSM8930_GPIO_VREG_ID_##_id] = { \
 		.init_data = { \
@@ -306,60 +427,58 @@
 	 *	    ID  name always_on pd min_uV   max_uV   en_t supply
 	 *	system_uA reg_ID
 	 */
-	PM8XXX_SMPS(S1, "8038_s1", 1, 1,  1150000, 1150000, 500, NULL, 100000,
-		26),
-	PM8XXX_SMPS(S2, "8038_s2", 1, 1,  1400000, 1400000, 500, NULL, 100000,
-		27),
-	PM8XXX_SMPS(S3, "8038_s3", 0, 1,  1150000, 1150000, 500, NULL, 0, 28),
-	PM8XXX_SMPS(S4, "8038_s4", 1, 1,  2200000, 2200000, 500, NULL, 100000,
-		29),
-
-	PM8XXX_NLDO1200(L1, "8038_l1",  0, 1, 1300000, 1300000, 200, "8038_s2",
-		0, 1),
-	PM8XXX_LDO(L2,  "8038_l2",  0, 1, 1200000, 1200000, 200, "8038_s2", 0,
-		2),
-	PM8XXX_LDO(L3,  "8038_l3",  0, 1, 3075000, 3075000, 200, NULL, 0, 3),
-	PM8XXX_LDO(L4,  "8038_l4",  1, 1, 1800000, 1800000, 200, NULL, 10000,
-		4),
-	PM8XXX_LDO(L5,  "8038_l5",  0, 1, 2950000, 2950000, 200, NULL, 0, 5),
-	PM8XXX_LDO(L6,  "8038_l6",  0, 1, 2950000, 2950000, 200, NULL, 0, 6),
-	PM8XXX_LDO(L7,  "8038_l7",  0, 1, 2050000, 2050000, 200, "8038_s4", 0,
-		7),
-	PM8XXX_LDO(L8,  "8038_l8",  0, 1, 2800000, 2800000, 200, NULL, 0, 8),
-	PM8XXX_LDO(L9,  "8038_l9",  0, 1, 2850000, 2850000, 200, NULL, 0, 9),
-	PM8XXX_LDO(L10, "8038_l10", 0, 1, 2900000, 2900000, 200, NULL, 0, 10),
-	PM8XXX_LDO(L11, "8038_l11", 1, 1, 1800000, 1800000, 200, "8038_s4",
-		10000, 11),
-	PM8XXX_LDO(L12, "8038_l12", 0, 1, 1200000, 1200000, 200, "8038_s2", 0,
-		12),
-	PM8XXX_LDO(L14, "8038_l14", 0, 1, 1800000, 1800000, 200, NULL, 0, 13),
-	PM8XXX_LDO(L15, "8038_l15", 0, 1, 1800000, 2950000, 200, NULL, 0, 14),
 	PM8XXX_NLDO1200(L16, "8038_l16", 0, 1, 1050000, 1050000, 200, "8038_s3",
-		0, 15),
-	PM8XXX_LDO(L17, "8038_l17", 0, 1, 1800000, 2950000, 200, NULL, 0, 16),
-	PM8XXX_LDO(L18, "8038_l18", 0, 1, 1800000, 1800000, 200, NULL, 0, 17),
+		0, 0),
 	PM8XXX_NLDO1200(L19, "8038_l19", 0, 1, 1050000, 1050000, 200, "8038_s3",
-		0, 18),
-	PM8XXX_NLDO1200(L20, "8038_l20", 1, 1, 1200000, 1200000, 200, "8038_s2",
-		10000, 19),
-	PM8XXX_LDO(L21, "8038_l21", 0, 1, 1900000, 1900000, 200, "8038_s4", 0,
-		20),
-	PM8XXX_LDO(L22, "8038_l22", 1, 1, 2950000, 2950000, 200, NULL, 10000,
-		21),
-	PM8XXX_LDO(L23, "8038_l23", 0, 1, 1800000, 1800000, 200, "8038_s4", 0,
-		22),
-	PM8XXX_NLDO1200(L24, "8038_l24", 1, 1, 1150000, 1150000, 200, "8038_s2",
-		10000, 23),
-	PM8XXX_LDO(L26, "8038_l26", 1, 1, 1050000, 1050000, 200, "8038_s2",
-		10000, 24),
+		0, 1),
 	PM8XXX_NLDO1200(L27, "8038_l27", 0, 1, 1050000, 1050000, 200, "8038_s3",
-		0, 25),
+		0, 2),
+};
 
-	/*	  ID	name  always_on pd		   en_t supply reg_ID */
-	PM8XXX_VS(LVS1, "8038_lvs1", 0, 1,		     0, "8038_l11", 32),
-	PM8XXX_VS(LVS2, "8038_lvs2", 0, 1,		     0, "8038_l11", 33),
+static struct rpm_regulator_init_data
+msm8930_rpm_regulator_init_data[] __devinitdata = {
+	/*	 ID    a_on pd ss min_uV   max_uV  supply sys_uA freq */
+	RPM_SMPS(S1,	 1, 1, 1,  500000, 1150000, NULL, 100000, 4p80),
+	RPM_SMPS(S2,	 1, 1, 0, 1400000, 1400000, NULL, 100000, 1p60),
+	RPM_SMPS(S3,	 0, 1, 0, 1150000, 1150000, NULL, 100000, 3p20),
+	RPM_SMPS(S4,	 1, 1, 0, 2200000, 2200000, NULL, 100000, 1p60),
 
+	/*	ID     a_on pd ss min_uV   max_uV  supply  sys_uA init_ip */
+	RPM_LDO(L1,	 0, 1, 0, 1300000, 1300000, "8038_s2", 0, 0),
+	RPM_LDO(L2,	 0, 1, 0, 1200000, 1200000, "8038_s2", 0, 0),
+	RPM_LDO(L3,	 0, 1, 0, 3075000, 3075000, NULL,      0, 0),
+	RPM_LDO(L4,	 1, 1, 0, 1800000, 1800000, NULL,      10000, 10000),
+	RPM_LDO(L5,	 0, 1, 0, 2950000, 2950000, NULL,      0, 0),
+	RPM_LDO(L6,	 0, 1, 0, 2950000, 2950000, NULL,      0, 0),
+	RPM_LDO(L7,	 0, 1, 0, 2050000, 2050000, "8038_s4", 0, 0),
+	RPM_LDO(L8,	 0, 1, 0, 2800000, 2800000, NULL,      0, 0),
+	RPM_LDO(L9,	 0, 1, 0, 2850000, 2850000, NULL,      0, 0),
+	RPM_LDO(L10,	 0, 1, 0, 2900000, 2900000, NULL,      0, 0),
+	RPM_LDO(L11,	 1, 1, 0, 1800000, 1800000, "8038_s4", 10000, 10000),
+	RPM_LDO(L12,	 0, 1, 0, 1200000, 1200000, "8038_s2", 0, 0),
+	RPM_LDO(L14,	 0, 1, 0, 1800000, 1800000, NULL,      0, 0),
+	RPM_LDO(L15,	 0, 1, 0, 1800000, 2950000, NULL,      0, 0),
+	RPM_LDO(L17,	 0, 1, 0, 1800000, 2950000, NULL,      0, 0),
+	RPM_LDO(L18,	 0, 1, 0, 1800000, 1800000, NULL,      0, 0),
+	RPM_LDO(L20,	 1, 1, 0, 1200000, 1200000, "8038_s2", 10000, 10000),
+	RPM_LDO(L21,	 0, 1, 0, 1900000, 1900000, "8038_s4", 0, 0),
+	RPM_LDO(L22,	 1, 1, 0, 1850000, 2950000, NULL,      10000, 10000),
+	RPM_LDO(L23,	 1, 1, 1, 1800000, 1800000, "8038_s4", 0, 0),
+	RPM_LDO(L24,	 1, 1, 1,  500000, 1150000, "8038_s2", 10000, 10000),
+	RPM_LDO(L26,     1, 1, 0, 1050000, 1050000, "8038_s2", 10000, 10000),
+
+	/*	ID     a_on pd ss		    supply */
+	RPM_VS(LVS1,	 0, 1, 0,		    "8038_l11"),
+	RPM_VS(LVS2,	 0, 1, 0,		    "8038_l11"),
 };
 
 int msm8930_pm8038_regulator_pdata_len __devinitdata =
 	ARRAY_SIZE(msm8930_pm8038_regulator_pdata);
+
+struct rpm_regulator_platform_data msm8930_rpm_regulator_pdata __devinitdata = {
+	.init_data		= msm8930_rpm_regulator_init_data,
+	.num_regulators		= ARRAY_SIZE(msm8930_rpm_regulator_init_data),
+	.version		= RPM_VREG_VERSION_8930,
+	.vreg_id_vdd_mem	= RPM_VREG_ID_PM8038_L24,
+	.vreg_id_vdd_dig	= RPM_VREG_ID_PM8038_S1,
+};
diff --git a/arch/arm/mach-msm/board-8930-storage.c b/arch/arm/mach-msm/board-8930-storage.c
index eee6d09..dee1e98 100644
--- a/arch/arm/mach-msm/board-8930-storage.c
+++ b/arch/arm/mach-msm/board-8930-storage.c
@@ -23,14 +23,7 @@
 #include <mach/gpiomux.h>
 #include "devices.h"
 
-/* TODO: Remove this once PM8038 physically becomes
- * available.
- */
-#ifndef MSM8930_PHASE_2
-#include "board-8960.h"
-#else
 #include "board-8930.h"
-#endif
 
 /* MSM8960 has 5 SDCC controllers */
 enum sdcc_controllers {
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index fe125e3..618d757 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>
@@ -82,12 +81,11 @@
 #include "devices.h"
 #include "devices-msm8x60.h"
 #include "spm.h"
-#include <mach/pm.h>
+#include "pm.h"
 #include <mach/cpuidle.h>
 #include "rpm_resources.h"
 #include "mpm.h"
 #include "acpuclock.h"
-#include "rpm_log.h"
 #include "smd_private.h"
 #include "pm-boot.h"
 #include "msm_watchdog.h"
@@ -127,7 +125,7 @@
 
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-#define MSM_PMEM_KERNEL_EBI1_SIZE  0xB0C000
+#define MSM_PMEM_KERNEL_EBI1_SIZE  0x280000
 #define MSM_ION_SF_SIZE		MSM_PMEM_SIZE
 #define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
 #define MSM_ION_MM_SIZE		MSM_PMEM_ADSP_SIZE
@@ -787,6 +785,102 @@
 	&mdm_device,
 };
 
+#ifdef CONFIG_MSM_MPM
+static uint16_t msm_mpm_irqs_m2a[MSM_MPM_NR_MPM_IRQS] __initdata = {
+	[1] = MSM_GPIO_TO_INT(46),
+	[2] = MSM_GPIO_TO_INT(150),
+	[4] = MSM_GPIO_TO_INT(103),
+	[5] = MSM_GPIO_TO_INT(104),
+	[6] = MSM_GPIO_TO_INT(105),
+	[7] = MSM_GPIO_TO_INT(106),
+	[8] = MSM_GPIO_TO_INT(107),
+	[9] = MSM_GPIO_TO_INT(7),
+	[10] = MSM_GPIO_TO_INT(11),
+	[11] = MSM_GPIO_TO_INT(15),
+	[12] = MSM_GPIO_TO_INT(19),
+	[13] = MSM_GPIO_TO_INT(23),
+	[14] = MSM_GPIO_TO_INT(27),
+	[15] = MSM_GPIO_TO_INT(31),
+	[16] = MSM_GPIO_TO_INT(35),
+	[19] = MSM_GPIO_TO_INT(90),
+	[20] = MSM_GPIO_TO_INT(92),
+	[23] = MSM_GPIO_TO_INT(85),
+	[24] = MSM_GPIO_TO_INT(83),
+	[25] = USB1_HS_IRQ,
+	[27] = HDMI_IRQ,
+	[29] = MSM_GPIO_TO_INT(10),
+	[30] = MSM_GPIO_TO_INT(102),
+	[31] = MSM_GPIO_TO_INT(81),
+	[32] = MSM_GPIO_TO_INT(78),
+	[33] = MSM_GPIO_TO_INT(94),
+	[34] = MSM_GPIO_TO_INT(72),
+	[35] = MSM_GPIO_TO_INT(39),
+	[36] = MSM_GPIO_TO_INT(43),
+	[37] = MSM_GPIO_TO_INT(61),
+	[38] = MSM_GPIO_TO_INT(50),
+	[39] = MSM_GPIO_TO_INT(42),
+	[41] = MSM_GPIO_TO_INT(62),
+	[42] = MSM_GPIO_TO_INT(76),
+	[43] = MSM_GPIO_TO_INT(75),
+	[44] = MSM_GPIO_TO_INT(70),
+	[45] = MSM_GPIO_TO_INT(69),
+	[46] = MSM_GPIO_TO_INT(67),
+	[47] = MSM_GPIO_TO_INT(65),
+	[48] = MSM_GPIO_TO_INT(58),
+	[49] = MSM_GPIO_TO_INT(54),
+	[50] = MSM_GPIO_TO_INT(52),
+	[51] = MSM_GPIO_TO_INT(49),
+	[52] = MSM_GPIO_TO_INT(40),
+	[53] = MSM_GPIO_TO_INT(37),
+	[54] = MSM_GPIO_TO_INT(24),
+	[55] = MSM_GPIO_TO_INT(14),
+};
+
+static uint16_t msm_mpm_bypassed_apps_irqs[] __initdata = {
+	TLMM_MSM_SUMMARY_IRQ,
+	RPM_APCC_CPU0_GP_HIGH_IRQ,
+	RPM_APCC_CPU0_GP_MEDIUM_IRQ,
+	RPM_APCC_CPU0_GP_LOW_IRQ,
+	RPM_APCC_CPU0_WAKE_UP_IRQ,
+	RPM_APCC_CPU1_GP_HIGH_IRQ,
+	RPM_APCC_CPU1_GP_MEDIUM_IRQ,
+	RPM_APCC_CPU1_GP_LOW_IRQ,
+	RPM_APCC_CPU1_WAKE_UP_IRQ,
+	MSS_TO_APPS_IRQ_0,
+	MSS_TO_APPS_IRQ_1,
+	MSS_TO_APPS_IRQ_2,
+	MSS_TO_APPS_IRQ_3,
+	MSS_TO_APPS_IRQ_4,
+	MSS_TO_APPS_IRQ_5,
+	MSS_TO_APPS_IRQ_6,
+	MSS_TO_APPS_IRQ_7,
+	MSS_TO_APPS_IRQ_8,
+	MSS_TO_APPS_IRQ_9,
+	LPASS_SCSS_GP_LOW_IRQ,
+	LPASS_SCSS_GP_MEDIUM_IRQ,
+	LPASS_SCSS_GP_HIGH_IRQ,
+	SPS_MTI_30,
+	SPS_MTI_31,
+	RIVA_APSS_SPARE_IRQ,
+	RIVA_APPS_WLAN_SMSM_IRQ,
+	RIVA_APPS_WLAN_RX_DATA_AVAIL_IRQ,
+	RIVA_APPS_WLAN_DATA_XFER_DONE_IRQ,
+};
+
+struct msm_mpm_device_data msm8930_mpm_dev_data __initdata = {
+	.irqs_m2a = msm_mpm_irqs_m2a,
+	.irqs_m2a_size = ARRAY_SIZE(msm_mpm_irqs_m2a),
+	.bypassed_apps_irqs = msm_mpm_bypassed_apps_irqs,
+	.bypassed_apps_irqs_size = ARRAY_SIZE(msm_mpm_bypassed_apps_irqs),
+	.mpm_request_reg_base = MSM_RPM_BASE + 0x9d8,
+	.mpm_status_reg_base = MSM_RPM_BASE + 0xdf8,
+	.mpm_apps_ipc_reg = MSM_APCS_GCC_BASE + 0x008,
+	.mpm_apps_ipc_val =  BIT(1),
+	.mpm_ipc_irq = RPM_APCC_CPU0_GP_MEDIUM_IRQ,
+
+};
+#endif
+
 #define MSM_SHARED_RAM_PHYS 0x80000000
 
 static void __init msm8930_map_io(void)
@@ -800,15 +894,14 @@
 
 static void __init msm8930_init_irq(void)
 {
-	msm_mpm_irq_extn_init();
+	struct msm_mpm_device_data *data = NULL;
+#ifdef CONFIG_MSM_MPM
+	data = &msm8930_mpm_dev_data;
+#endif
+
+	msm_mpm_irq_extn_init(data);
 	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
 						(void *)MSM_QGIC_CPU_BASE);
-
-	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-	writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
-	writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-	mb();
 }
 
 static void __init msm8930_init_buses(void)
@@ -918,21 +1011,21 @@
 };
 
 static uint8_t spm_wfi_cmd_sequence[] __initdata = {
-			0x03, 0x0f,
+	0x03, 0x0f,
 };
 
 static uint8_t spm_power_collapse_without_rpm[] __initdata = {
-			0x00, 0x24, 0x54, 0x10,
-			0x09, 0x03, 0x01,
-			0x10, 0x54, 0x30, 0x0C,
-			0x24, 0x30, 0x0f,
+	0x00, 0x24, 0x54, 0x10,
+	0x09, 0x03, 0x01,
+	0x10, 0x54, 0x30, 0x0C,
+	0x24, 0x30, 0x0f,
 };
 
 static uint8_t spm_power_collapse_with_rpm[] __initdata = {
-			0x00, 0x24, 0x54, 0x10,
-			0x09, 0x07, 0x01, 0x0B,
-			0x10, 0x54, 0x30, 0x0C,
-			0x24, 0x30, 0x0f,
+	0x00, 0x24, 0x54, 0x10,
+	0x09, 0x07, 0x01, 0x0B,
+	0x10, 0x54, 0x30, 0x0C,
+	0x24, 0x30, 0x0f,
 };
 
 static struct msm_spm_seq_entry msm_spm_seq_list[] __initdata = {
@@ -991,21 +1084,21 @@
 };
 
 static uint8_t l2_spm_wfi_cmd_sequence[] __initdata = {
-			0x00, 0x20, 0x03, 0x20,
-			0x00, 0x0f,
+	0x00, 0x20, 0x03, 0x20,
+	0x00, 0x0f,
 };
 
 static uint8_t l2_spm_gdhs_cmd_sequence[] __initdata = {
-			0x00, 0x20, 0x34, 0x64,
-			0x48, 0x07, 0x48, 0x20,
-			0x50, 0x64, 0x04, 0x34,
-			0x50, 0x0f,
+	0x00, 0x20, 0x34, 0x64,
+	0x48, 0x07, 0x48, 0x20,
+	0x50, 0x64, 0x04, 0x34,
+	0x50, 0x0f,
 };
 static uint8_t l2_spm_power_off_cmd_sequence[] __initdata = {
-			0x00, 0x10, 0x34, 0x64,
-			0x48, 0x07, 0x48, 0x10,
-			0x50, 0x64, 0x04, 0x34,
-			0x50, 0x0F,
+	0x00, 0x10, 0x34, 0x64,
+	0x48, 0x07, 0x48, 0x10,
+	0x50, 0x64, 0x04, 0x34,
+	0x50, 0x0F,
 };
 
 static struct msm_spm_seq_entry msm_spm_l2_seq_list[] __initdata = {
@@ -1239,128 +1332,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
 
@@ -1375,8 +1346,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,
@@ -1413,10 +1384,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");
 }
 
@@ -1454,11 +1425,24 @@
 	return;
 }
 
+static struct mxt_config_info mxt_config_array[] = {
+	{
+		.config			= mxt_config_data_8930,
+		.config_length		= ARRAY_SIZE(mxt_config_data_8930),
+		.family_id		= 0x81,
+		.variant_id		= 0x01,
+		.version		= 0x10,
+		.build			= 0xAA,
+	},
+};
+
 static struct mxt_platform_data mxt_platform_data_8930 = {
-	.config			= mxt_config_data_8930,
-	.config_length		= ARRAY_SIZE(mxt_config_data_8930),
-	.x_size			= 1067,
-	.y_size			= 566,
+	.config_array		= mxt_config_array,
+	.config_array_size	= ARRAY_SIZE(mxt_config_array),
+	.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,
@@ -1553,20 +1537,6 @@
 	.src_clk_rate = 24000000,
 };
 
-static struct msm_rpm_platform_data msm_rpm_data = {
-	.reg_base_addrs = {
-		[MSM_RPM_PAGE_STATUS] = MSM_RPM_BASE,
-		[MSM_RPM_PAGE_CTRL] = MSM_RPM_BASE + 0x400,
-		[MSM_RPM_PAGE_REQ] = MSM_RPM_BASE + 0x600,
-		[MSM_RPM_PAGE_ACK] = MSM_RPM_BASE + 0xa00,
-	},
-
-	.irq_ack = RPM_APCC_CPU0_GP_HIGH_IRQ,
-	.irq_err = RPM_APCC_CPU0_GP_LOW_IRQ,
-	.irq_vmpm = RPM_APCC_CPU0_GP_MEDIUM_IRQ,
-	.msm_apps_ipc_rpm_reg = MSM_APCS_GCC_BASE + 0x008,
-	.msm_apps_ipc_rpm_val = 4,
-};
 
 static struct ks8851_pdata spi_eth_pdata = {
 	.irq_gpio = KS8851_IRQ_GPIO,
@@ -1615,14 +1585,6 @@
 	.tsens_num_sensor	= 5,
 };
 
-static struct platform_device msm_tsens_device = {
-	.name	= "tsens8960-tm",
-	.id	= -1,
-	.dev	= {
-		.platform_data = &msm_tsens_pdata,
-	},
-};
-
 #ifdef CONFIG_MSM_FAKE_BATTERY
 static struct platform_device fish_battery_device = {
 	.name = "fish_battery",
@@ -1675,37 +1637,14 @@
 	.name	= "rpm-regulator",
 	.id	= -1,
 	.dev	= {
-	/*
-	 * TODO: When physical 8930/PM8038 hardware becomes
-	 * available, replace msm_rpm_regulator_pdata
-	 * with 8930 rpm regulator object.
-	 */
-#if     !defined(MSM8930_PHASE_2)
-
+#ifndef MSM8930_PHASE_2
 		.platform_data = &msm_rpm_regulator_pdata,
+#else
+		.platform_data = &msm8930_rpm_regulator_pdata,
 #endif
 	},
 };
 
-static struct msm_rpm_log_platform_data msm_rpm_log_pdata = {
-	.phys_addr_base = 0x0010C000,
-	.reg_offsets = {
-		[MSM_RPM_LOG_PAGE_INDICES] = 0x00000080,
-		[MSM_RPM_LOG_PAGE_BUFFER]  = 0x000000A0,
-	},
-	.phys_size = SZ_8K,
-	.log_len = 4096,		  /* log's buffer length in bytes */
-	.log_len_mask = (4096 >> 2) - 1,  /* length mask in units of u32 */
-};
-
-static struct platform_device msm_rpm_log_device = {
-	.name	= "msm_rpm_log",
-	.id	= -1,
-	.dev	= {
-		.platform_data = &msm_rpm_log_pdata,
-	},
-};
-
 static struct platform_device *common_devices[] __initdata = {
 	&msm8960_device_dmov,
 	&msm_device_smd,
@@ -1763,12 +1702,12 @@
 #ifdef CONFIG_HW_RANDOM_MSM
 	&msm_device_rng,
 #endif
-	&msm_rpm_device,
+	&msm8930_rpm_device,
+	&msm8930_rpm_log_device,
+	&msm8930_rpm_stat_device,
 #ifdef CONFIG_ION_MSM
 	&ion_dev,
 #endif
-	&msm_rpm_log_device,
-	&msm_rpm_stat_device,
 	&msm_device_tz_log,
 
 #ifdef CONFIG_MSM_QDSS
@@ -1828,7 +1767,6 @@
 	&msm_bus_mm_fabric,
 	&msm_bus_sys_fpb,
 	&msm_bus_cpss_fpb,
-	&msm_tsens_device,
 };
 
 static void __init msm8930_i2c_init(void)
@@ -1982,6 +1920,33 @@
 	},
 };
 
+static struct msm_rpmrs_platform_data msm_rpmrs_data __initdata = {
+	.levels = &msm_rpmrs_levels[0],
+	.num_levels = ARRAY_SIZE(msm_rpmrs_levels),
+	.vdd_mem_levels  = {
+		[MSM_RPMRS_VDD_MEM_RET_LOW]	= 750000,
+		[MSM_RPMRS_VDD_MEM_RET_HIGH]	= 750000,
+		[MSM_RPMRS_VDD_MEM_ACTIVE]	= 1050000,
+		[MSM_RPMRS_VDD_MEM_MAX]		= 1150000,
+	},
+	.vdd_dig_levels = {
+		[MSM_RPMRS_VDD_DIG_RET_LOW]	= 500000,
+		[MSM_RPMRS_VDD_DIG_RET_HIGH]	= 750000,
+		[MSM_RPMRS_VDD_DIG_ACTIVE]	= 950000,
+		[MSM_RPMRS_VDD_DIG_MAX]		= 1150000,
+	},
+	.vdd_mask = 0x7FFFFF,
+	.rpmrs_target_id = {
+		[MSM_RPMRS_ID_PXO_CLK]		= MSM_RPM_ID_PXO_CLK,
+		[MSM_RPMRS_ID_L2_CACHE_CTL]	= MSM_RPM_ID_LAST,
+		[MSM_RPMRS_ID_VDD_DIG_0]	= MSM_RPM_ID_PM8038_S1_0,
+		[MSM_RPMRS_ID_VDD_DIG_1]	= MSM_RPM_ID_PM8038_S1_1,
+		[MSM_RPMRS_ID_VDD_MEM_0]	= MSM_RPM_ID_PM8038_L24_0,
+		[MSM_RPMRS_ID_VDD_MEM_1]	= MSM_RPM_ID_PM8038_L24_1,
+		[MSM_RPMRS_ID_RPM_CTL]		= MSM_RPM_ID_RPM_CTL,
+	},
+};
+
 static struct msm_pm_boot_platform_data msm_pm_boot_pdata __initdata = {
 	.mode = MSM_PM_BOOT_CONFIG_TZ,
 };
@@ -2048,12 +2013,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,
@@ -2123,9 +2082,9 @@
 	if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
 		pr_err("meminfo_init() failed!\n");
 
-	BUG_ON(msm_rpm_init(&msm_rpm_data));
-	BUG_ON(msm_rpmrs_levels_init(msm_rpmrs_levels,
-				ARRAY_SIZE(msm_rpmrs_levels)));
+	msm_tsens_early_init(&msm_tsens_pdata);
+	BUG_ON(msm_rpm_init(&msm8930_rpm_data));
+	BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
 
 	regulator_suppress_info_printing();
 	if (msm_xo_init())
diff --git a/arch/arm/mach-msm/board-8930.h b/arch/arm/mach-msm/board-8930.h
index 8e20903..cefaff5 100644
--- a/arch/arm/mach-msm/board-8930.h
+++ b/arch/arm/mach-msm/board-8930.h
@@ -13,6 +13,8 @@
 #ifndef __ARCH_ARM_MACH_MSM_BOARD_MSM8930_H
 #define __ARCH_ARM_MACH_MSM_BOARD_MSM8930_H
 
+#define MSM8930_PHASE_2
+
 #include <linux/regulator/gpio-regulator.h>
 #include <linux/mfd/pm8xxx/pm8038.h>
 #include <linux/i2c.h>
@@ -75,6 +77,9 @@
 extern struct gpio_regulator_platform_data
 	msm8930_gpio_regulator_pdata[] __devinitdata;
 
+extern struct rpm_regulator_platform_data
+	msm8930_rpm_regulator_pdata __devinitdata;
+
 #if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
 enum {
 	GPIO_EXPANDER_IRQ_BASE = (PM8038_IRQ_BASE + PM8038_NR_IRQS),
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index 4466872..6c292a4 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,9 +12,9 @@
  */
 
 #include <asm/mach-types.h>
+#include <linux/gpio.h>
 #include <mach/board.h>
 #include <mach/msm_bus_board.h>
-#include <mach/gpio.h>
 #include <mach/gpiomux.h>
 #include "devices.h"
 #include "board-8960.h"
@@ -181,20 +181,6 @@
 };
 
 #ifdef CONFIG_MSM_CAMERA
-
-static uint16_t msm_cam_gpio_2d_tbl[] = {
-	5, /*CAMIF_MCLK*/
-	20, /*CAMIF_I2C_DATA*/
-	21, /*CAMIF_I2C_CLK*/
-};
-
-static struct msm_camera_gpio_conf gpio_conf = {
-	.cam_gpiomux_conf_tbl = msm8960_cam_2d_configs,
-	.cam_gpiomux_conf_tbl_size = ARRAY_SIZE(msm8960_cam_2d_configs),
-	.cam_gpio_tbl = msm_cam_gpio_2d_tbl,
-	.cam_gpio_tbl_size = ARRAY_SIZE(msm_cam_gpio_2d_tbl),
-};
-
 #define VFE_CAMIF_TIMER1_GPIO 2
 #define VFE_CAMIF_TIMER2_GPIO 3
 #define VFE_CAMIF_TIMER3_GPIO_INT 4
@@ -350,19 +336,84 @@
 
 static struct msm_camera_device_platform_data msm_camera_csi_device_data[] = {
 	{
-		.ioclk.mclk_clk_rate = 24000000,
-		.ioclk.vfe_clk_rate  = 228570000,
 		.csid_core = 0,
+		.is_csiphy = 1,
+		.is_csid   = 1,
+		.is_ispif  = 1,
+		.is_vpe    = 1,
 		.cam_bus_scale_table = &cam_bus_client_pdata,
 	},
 	{
-		.ioclk.mclk_clk_rate = 24000000,
-		.ioclk.vfe_clk_rate  = 228570000,
 		.csid_core = 1,
+		.is_csiphy = 1,
+		.is_csid   = 1,
+		.is_ispif  = 1,
+		.is_vpe    = 1,
 		.cam_bus_scale_table = &cam_bus_client_pdata,
 	},
 };
 
+static struct camera_vreg_t msm_8960_back_cam_vreg[] = {
+	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+	{"cam_vio", REG_VS, 0, 0, 0},
+	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
+};
+
+static struct camera_vreg_t msm_8960_front_cam_vreg[] = {
+	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+	{"cam_vio", REG_VS, 0, 0, 0},
+	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+};
+
+static struct gpio msm8960_common_cam_gpio[] = {
+	{5, GPIOF_DIR_IN, "CAMIF_MCLK"},
+	{20, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
+	{21, GPIOF_DIR_IN, "CAMIF_I2C_CLK"},
+};
+
+static struct gpio msm8960_front_cam_gpio[] = {
+	{76, GPIOF_DIR_OUT, "CAM_RESET"},
+};
+
+static struct gpio msm8960_back_cam_gpio[] = {
+	{107, GPIOF_DIR_OUT, "CAM_RESET"},
+};
+
+static struct msm_gpio_set_tbl msm8960_front_cam_gpio_set_tbl[] = {
+	{76, GPIOF_OUT_INIT_LOW, 1000},
+	{76, GPIOF_OUT_INIT_HIGH, 4000},
+};
+
+static struct msm_gpio_set_tbl msm8960_back_cam_gpio_set_tbl[] = {
+	{107, GPIOF_OUT_INIT_LOW, 1000},
+	{107, GPIOF_OUT_INIT_HIGH, 4000},
+};
+
+static struct msm_camera_gpio_conf msm_8960_front_cam_gpio_conf = {
+	.cam_gpiomux_conf_tbl = msm8960_cam_2d_configs,
+	.cam_gpiomux_conf_tbl_size = ARRAY_SIZE(msm8960_cam_2d_configs),
+	.cam_gpio_common_tbl = msm8960_common_cam_gpio,
+	.cam_gpio_common_tbl_size = ARRAY_SIZE(msm8960_common_cam_gpio),
+	.cam_gpio_req_tbl = msm8960_front_cam_gpio,
+	.cam_gpio_req_tbl_size = ARRAY_SIZE(msm8960_front_cam_gpio),
+	.cam_gpio_set_tbl = msm8960_front_cam_gpio_set_tbl,
+	.cam_gpio_set_tbl_size = ARRAY_SIZE(msm8960_front_cam_gpio_set_tbl),
+};
+
+static struct msm_camera_gpio_conf msm_8960_back_cam_gpio_conf = {
+	.cam_gpiomux_conf_tbl = msm8960_cam_2d_configs,
+	.cam_gpiomux_conf_tbl_size = ARRAY_SIZE(msm8960_cam_2d_configs),
+	.cam_gpio_common_tbl = msm8960_common_cam_gpio,
+	.cam_gpio_common_tbl_size = ARRAY_SIZE(msm8960_common_cam_gpio),
+	.cam_gpio_req_tbl = msm8960_back_cam_gpio,
+	.cam_gpio_req_tbl_size = ARRAY_SIZE(msm8960_back_cam_gpio),
+	.cam_gpio_set_tbl = msm8960_back_cam_gpio_set_tbl,
+	.cam_gpio_set_tbl_size = ARRAY_SIZE(msm8960_back_cam_gpio_set_tbl),
+};
+
 #ifdef CONFIG_IMX074_ACT
 static struct i2c_board_info imx074_actuator_i2c_info = {
 	I2C_BOARD_INFO("imx074_act", 0x11),
@@ -386,10 +437,9 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
 	.mount_angle	= 90,
-	.sensor_reset	= 107,
-	.sensor_pwd	= 85,
-	.vcm_pwd	= 0,
-	.vcm_enable	= 1,
+	.cam_vreg = msm_8960_back_cam_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8960_back_cam_vreg),
+	.gpio_conf = &msm_8960_back_cam_gpio_conf,
 };
 
 static struct msm_camera_sensor_info msm_camera_sensor_imx074_data = {
@@ -398,7 +448,6 @@
 	.flash_data	= &flash_imx074,
 	.strobe_flash_data = &strobe_flash_xenon,
 	.sensor_platform_info = &sensor_board_info_imx074,
-	.gpio_conf = &gpio_conf,
 	.csi_if	= 1,
 	.camera_type = BACK_CAMERA_2D,
 #ifdef CONFIG_IMX074_ACT
@@ -414,7 +463,9 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_mt9m114 = {
 	.mount_angle = 90,
-	.sensor_reset = 107,
+	.cam_vreg = msm_8960_back_cam_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8960_back_cam_vreg),
+	.gpio_conf = &msm_8960_back_cam_gpio_conf,
 };
 
 static struct msm_camera_sensor_info msm_camera_sensor_mt9m114_data = {
@@ -422,7 +473,6 @@
 	.pdata = &msm_camera_csi_device_data[0],
 	.flash_data = &flash_mt9m114,
 	.sensor_platform_info = &sensor_board_info_mt9m114,
-	.gpio_conf = &gpio_conf,
 	.csi_if = 1,
 	.camera_type = BACK_CAMERA_2D,
 };
@@ -435,10 +485,9 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_ov2720 = {
 	.mount_angle	= 0,
-	.sensor_reset	= 76,
-	.sensor_pwd	= 85,
-	.vcm_pwd	= 0,
-	.vcm_enable	= 1,
+	.cam_vreg = msm_8960_front_cam_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8960_front_cam_vreg),
+	.gpio_conf = &msm_8960_front_cam_gpio_conf,
 };
 
 static struct msm_camera_sensor_info msm_camera_sensor_ov2720_data = {
@@ -446,16 +495,64 @@
 	.pdata	= &msm_camera_csi_device_data[1],
 	.flash_data	= &flash_ov2720,
 	.sensor_platform_info = &sensor_board_info_ov2720,
-	.gpio_conf = &gpio_conf,
 	.csi_if	= 1,
 	.camera_type = FRONT_CAMERA_2D,
 };
 #endif
 
-static struct msm8960_privacy_light_cfg privacy_light_info = {
-	.mpp = PM8921_MPP_PM_TO_SYS(12),
+static struct camera_vreg_t msm_8960_s5k3l1yx_vreg[] = {
+	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+	{"cam_vio", REG_VS, 0, 0, 0},
+	{"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
 };
 
+static struct msm_camera_sensor_flash_data flash_s5k3l1yx = {
+	.flash_type = MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_s5k3l1yx = {
+	.mount_angle  = 0,
+	.cam_vreg = msm_8960_s5k3l1yx_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8960_s5k3l1yx_vreg),
+	.gpio_conf = &msm_8960_back_cam_gpio_conf,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_s5k3l1yx_data = {
+	.sensor_name          = "s5k3l1yx",
+	.pdata                = &msm_camera_csi_device_data[0],
+	.flash_data           = &flash_s5k3l1yx,
+	.sensor_platform_info = &sensor_board_info_s5k3l1yx,
+	.csi_if               = 1,
+	.camera_type          = BACK_CAMERA_2D,
+};
+
+static struct pm8xxx_mpp_config_data privacy_light_on_config = {
+	.type		= PM8XXX_MPP_TYPE_SINK,
+	.level		= PM8XXX_MPP_CS_OUT_5MA,
+	.control	= PM8XXX_MPP_CS_CTRL_MPP_LOW_EN,
+};
+
+static struct pm8xxx_mpp_config_data privacy_light_off_config = {
+	.type		= PM8XXX_MPP_TYPE_SINK,
+	.level		= PM8XXX_MPP_CS_OUT_5MA,
+	.control	= PM8XXX_MPP_CS_CTRL_DISABLE,
+};
+
+static int32_t msm_camera_8960_ext_power_ctrl(int enable)
+{
+	int rc = 0;
+	if (enable) {
+		rc = pm8xxx_mpp_config(PM8921_MPP_PM_TO_SYS(12),
+			&privacy_light_on_config);
+	} else {
+		rc = pm8xxx_mpp_config(PM8921_MPP_PM_TO_SYS(12),
+			&privacy_light_off_config);
+	}
+	return rc;
+}
+
 void __init msm8960_init_cam(void)
 {
 	msm_gpiomux_install(msm8960_cam_common_configs,
@@ -480,9 +577,8 @@
 		s_info = &msm_camera_sensor_imx074_data;
 		s_info->sensor_platform_info->mount_angle = 180;
 		s_info = &msm_camera_sensor_ov2720_data;
-		s_info->sensor_platform_info->privacy_light = 1;
-		s_info->sensor_platform_info->privacy_light_info =
-			&privacy_light_info;
+		s_info->sensor_platform_info->ext_power_ctrl =
+			msm_camera_8960_ext_power_ctrl;
 	}
 
 	platform_device_register(&msm8960_device_csiphy0);
@@ -512,6 +608,10 @@
 	I2C_BOARD_INFO("mt9m114", 0x48),
 	.platform_data = &msm_camera_sensor_mt9m114_data,
 	},
+	{
+	I2C_BOARD_INFO("s5k3l1yx", 0x20),
+	.platform_data = &msm_camera_sensor_s5k3l1yx_data,
+	},
 #ifdef CONFIG_MSM_CAMERA_FLASH_SC628A
 	{
 	I2C_BOARD_INFO("sc628a", 0x6E),
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index 3c7878d..fb78ce7 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -15,14 +15,15 @@
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <linux/bootmem.h>
+#include <linux/ion.h>
 #include <asm/mach-types.h>
 #include <mach/msm_bus_board.h>
 #include <mach/msm_memtypes.h>
 #include <mach/board.h>
 #include <mach/gpio.h>
 #include <mach/gpiomux.h>
-#include <linux/ion.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,
@@ -156,7 +166,7 @@
 	static int gpio21, gpio24, gpio43;
 	int rc;
 
-	pr_info("%s: on=%d\n", __func__, on);
+	pr_debug("%s: on=%d\n", __func__, on);
 
 	gpio21 = PM8921_GPIO_PM_TO_SYS(21); /* disp power enable_n */
 	gpio43 = PM8921_GPIO_PM_TO_SYS(43); /* Displays Enable (rst_n)*/
@@ -266,7 +276,7 @@
 	static int gpio43;
 	int rc;
 
-	pr_info("%s: state : %d\n", __func__, on);
+	pr_debug("%s: state : %d\n", __func__, on);
 
 	if (!dsi_power_on) {
 
@@ -386,7 +396,7 @@
 {
 	int ret;
 
-	pr_info("%s: on=%d\n", __func__, on);
+	pr_debug("%s: on=%d\n", __func__, on);
 
 	if (machine_is_msm8960_liquid())
 		ret = mipi_dsi_liquid_panel_power(on);
@@ -671,9 +681,11 @@
 };
 
 #define FPGA_3D_GPIO_CONFIG_ADDR	0xB5
-static int dsi2lvds_gpio[2] = {
+static int dsi2lvds_gpio[4] = {
 	0,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
-	0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
+	0x1F08, /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
+	GPIO_LIQUID_EXPANDER_BASE+6,	/* TN Enable */
+	GPIO_LIQUID_EXPANDER_BASE+7,	/* TN Mode */
 	};
 
 static struct msm_panel_common_pdata mipi_dsi2lvds_pdata = {
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
index 0dfa1c6..5b632bd 100644
--- a/arch/arm/mach-msm/board-8960-gpiomux.c
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -210,7 +210,7 @@
 static struct gpiomux_setting ap2mdm_kpdpwr_n_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_8MA,
-	.pull = GPIOMUX_PULL_NONE,
+	.pull = GPIOMUX_PULL_DOWN,
 };
 
 static struct gpiomux_setting mdp_vsync_suspend_cfg = {
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index c7e32c0..0375b84 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -98,6 +98,7 @@
 	PM8XXX_GPIO_OUTPUT_VIN(21, 1, PM_GPIO_VIN_VPH),	 /* Backlight Enable */
 	PM8XXX_GPIO_DISABLE(22),			 /* Disable NFC */
 	PM8XXX_GPIO_OUTPUT_FUNC(24, 0, PM_GPIO_FUNC_2),	 /* Bl: Off, PWM mode */
+	PM8XXX_GPIO_OUTPUT_FUNC(25, 0, PM_GPIO_FUNC_2),	 /* TN_CLK */
 	PM8XXX_GPIO_INPUT(26,	    PM_GPIO_PULL_UP_30), /* SD_CARD_DET_N */
 	PM8XXX_GPIO_OUTPUT(43,	    PM_GPIO_PULL_UP_30), /* DISP_RESET_N */
 	PM8XXX_GPIO_OUTPUT(42, 0),                      /* USB 5V reg enable */
@@ -449,14 +450,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 f36c3a1..0f05af5 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -33,6 +33,7 @@
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-001a"),
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-006c"),
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-0048"),
+	REGULATOR_SUPPLY("mipi_csi_vdd",	"4-0020"),
 };
 VREG_CONSUMERS(L3) = {
 	REGULATOR_SUPPLY("8921_l3",		NULL),
@@ -74,12 +75,14 @@
 	REGULATOR_SUPPLY("cam_vana",		"4-001a"),
 	REGULATOR_SUPPLY("cam_vana",		"4-006c"),
 	REGULATOR_SUPPLY("cam_vana",		"4-0048"),
+	REGULATOR_SUPPLY("cam_vana",		"4-0020"),
 };
 VREG_CONSUMERS(L12) = {
 	REGULATOR_SUPPLY("8921_l12",		NULL),
 	REGULATOR_SUPPLY("cam_vdig",		"4-001a"),
 	REGULATOR_SUPPLY("cam_vdig",		"4-006c"),
 	REGULATOR_SUPPLY("cam_vdig",		"4-0048"),
+	REGULATOR_SUPPLY("cam_vdig",		"4-0020"),
 };
 VREG_CONSUMERS(L14) = {
 	REGULATOR_SUPPLY("8921_l14",		NULL),
@@ -93,6 +96,7 @@
 	REGULATOR_SUPPLY("cam_vaf",		"4-001a"),
 	REGULATOR_SUPPLY("cam_vaf",		"4-006c"),
 	REGULATOR_SUPPLY("cam_vaf",		"4-0048"),
+	REGULATOR_SUPPLY("cam_vaf",		"4-0020"),
 };
 VREG_CONSUMERS(L17) = {
 	REGULATOR_SUPPLY("8921_l17",		NULL),
@@ -110,6 +114,9 @@
 	REGULATOR_SUPPLY("8921_l23",		NULL),
 	REGULATOR_SUPPLY("dsi_vddio",		"mipi_dsi.1"),
 	REGULATOR_SUPPLY("hdmi_avdd",		"hdmi_msm.0"),
+	REGULATOR_SUPPLY("pll_vdd",		"pil_riva"),
+	REGULATOR_SUPPLY("pll_vdd",		"pil_qdsp6v4.1"),
+	REGULATOR_SUPPLY("pll_vdd",		"pil_qdsp6v4.2"),
 };
 VREG_CONSUMERS(L24) = {
 	REGULATOR_SUPPLY("8921_l24",		NULL),
@@ -204,6 +211,7 @@
 	REGULATOR_SUPPLY("cam_vio",		"4-001a"),
 	REGULATOR_SUPPLY("cam_vio",		"4-006c"),
 	REGULATOR_SUPPLY("cam_vio",		"4-0048"),
+	REGULATOR_SUPPLY("cam_vio",		"4-0020"),
 };
 VREG_CONSUMERS(LVS6) = {
 	REGULATOR_SUPPLY("8921_lvs6",		NULL),
@@ -214,6 +222,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),
@@ -237,12 +246,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 = { \
@@ -264,6 +273,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, \
@@ -272,7 +283,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) \
@@ -280,7 +291,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) \
@@ -288,32 +299,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, \
@@ -462,7 +473,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 */
@@ -488,9 +499,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-storage.c b/arch/arm/mach-msm/board-8960-storage.c
index 8b43d38..b03da38 100644
--- a/arch/arm/mach-msm/board-8960-storage.c
+++ b/arch/arm/mach-msm/board-8960-storage.c
@@ -121,8 +121,8 @@
 
 static struct msm_mmc_pad_pull sdc1_pad_pull_off_cfg[] = {
 	{TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
-	{TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_DOWN},
-	{TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_DOWN}
+	{TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
+	{TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
 };
 
 /* SDC3 pad data */
@@ -227,7 +227,7 @@
 	.pclk_src_dfab	= 1,
 	.nonremovable	= 1,
 	.vreg_data	= &mmc_slot_vreg_data[SDCC1],
-	.pin_data	= &mmc_slot_pin_data[SDCC1]
+	.pin_data	= &mmc_slot_pin_data[SDCC1],
 };
 #endif
 
@@ -259,10 +259,12 @@
 void __init msm8960_init_mmc(void)
 {
 #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
+	msm8960_sdc1_data.swfi_latency = msm_rpm_get_swfi_latency();
 	/* SDC1 : eMMC card connected */
 	msm_add_sdcc(1, &msm8960_sdc1_data);
 #endif
 #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
+	msm8960_sdc3_data.swfi_latency = msm_rpm_get_swfi_latency();
 	/* SDC3: External card slot */
 	msm_add_sdcc(3, &msm8960_sdc3_data);
 #endif
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 598e18d..786ec01 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -87,12 +87,11 @@
 #include "devices-msm8x60.h"
 #include "spm.h"
 #include "board-8960.h"
-#include <mach/pm.h>
+#include "pm.h"
 #include <mach/cpuidle.h>
 #include "rpm_resources.h"
 #include "mpm.h"
 #include "acpuclock.h"
-#include "rpm_log.h"
 #include "smd_private.h"
 #include "pm-boot.h"
 #include "msm_watchdog.h"
@@ -140,7 +139,7 @@
 #define MSM_LIQUID_PMEM_SIZE 0x4000000 /* 64 Mbytes */
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-#define MSM_PMEM_KERNEL_EBI1_SIZE  0xB0C000
+#define MSM_PMEM_KERNEL_EBI1_SIZE  0x280000
 #define MSM_ION_SF_SIZE		MSM_PMEM_SIZE
 #define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
 #define MSM_ION_MM_SIZE		MSM_PMEM_ADSP_SIZE
@@ -302,10 +301,6 @@
 #endif
 }
 
-static void __init reserve_fmem_memory(void)
-{
-}
-
 static int msm8960_paddr_to_memtype(unsigned int paddr)
 {
 	return MEMTYPE_EBI1;
@@ -316,11 +311,13 @@
 static struct ion_cp_heap_pdata cp_mm_ion_pdata = {
 	.permission_type = IPT_TYPE_MM_CARVEOUT,
 	.align = PAGE_SIZE,
+	.reusable = 1,
 };
 
 static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
 	.permission_type = IPT_TYPE_MFC_SHAREDMEM,
 	.align = PAGE_SIZE,
+	.reusable = 0,
 };
 
 static struct ion_co_heap_pdata co_ion_pdata = {
@@ -412,9 +409,8 @@
 	.dev = { .platform_data = &fmem_pdata },
 };
 
-static void reserve_ion_memory(void)
+static void __init adjust_mem_for_liquid(void)
 {
-#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
 	unsigned int i;
 
 	if (!pmem_param_set && machine_is_msm8960_liquid()) {
@@ -428,12 +424,99 @@
 			}
 		}
 	}
-	msm8960_reserve_table[MEMTYPE_EBI1].size += msm_ion_cp_mm_size;
-	msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_FW_SIZE;
-	msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE;
-	msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MFC_SIZE;
-	msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_QSECOM_SIZE;
-	msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE;
+}
+
+static void __init reserve_mem_for_ion(enum ion_memory_types mem_type,
+				      unsigned long size)
+{
+	msm8960_reserve_table[mem_type].size += size;
+}
+
+static __init const struct ion_platform_heap *find_ion_heap(int heap_id)
+{
+	unsigned int i;
+	for (i = 0; i < ion_pdata.nr; ++i) {
+		const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+		if (heap->id == heap_id)
+			return (const struct ion_platform_heap *) heap;
+	}
+	return 0;
+}
+
+/**
+ * Reserve memory for ION and calculate amount of reusable memory for fmem.
+ * We only reserve memory for heaps that are not reusable. However, we only
+ * support one reusable heap at the moment so we ignore the reusable flag for
+ * other than the first heap with reusable flag set. Also handle special case
+ * for adjacent heap when the adjacent heap is adjacent to a reusable heap.
+ */
+static void __init reserve_ion_memory(void)
+{
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+	unsigned int i;
+	unsigned int reusable_count = 0;
+
+	adjust_mem_for_liquid();
+	fmem_pdata.size = 0;
+	fmem_pdata.reserved_size = 0;
+
+	/* We only support 1 reusable heap. Check if more than one heap
+	 * is specified as reusable and set as non-reusable if found.
+	 */
+	for (i = 0; i < ion_pdata.nr; ++i) {
+		const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+
+		if (heap->type == ION_HEAP_TYPE_CP && heap->extra_data) {
+			struct ion_cp_heap_pdata *data = heap->extra_data;
+
+			reusable_count += (data->reusable) ? 1 : 0;
+
+			if (data->reusable && reusable_count > 1) {
+				pr_err("%s: Too many heaps specified as "
+					"reusable. Heap %s was not configured "
+					"as reusable.\n", __func__, heap->name);
+				data->reusable = 0;
+			}
+		}
+	}
+
+	for (i = 0; i < ion_pdata.nr; ++i) {
+		int reusable = 0;
+		int adjacent_heap_id = INVALID_HEAP_ID;
+		int adj_reusable = 0;
+		const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+
+		if (heap->extra_data) {
+			switch (heap->type) {
+			case ION_HEAP_TYPE_CP:
+				reusable = ((struct ion_cp_heap_pdata *)
+						heap->extra_data)->reusable;
+				break;
+			case ION_HEAP_TYPE_CARVEOUT:
+				adjacent_heap_id = ((struct ion_co_heap_pdata *)
+					heap->extra_data)->adjacent_mem_id;
+				break;
+			default:
+				break;
+			}
+		}
+
+		if (adjacent_heap_id != INVALID_HEAP_ID) {
+			const struct ion_platform_heap *adj_heap =
+						find_ion_heap(adjacent_heap_id);
+			if (adj_heap) {
+				adj_reusable = ((struct ion_cp_heap_pdata *)
+						adj_heap->extra_data)->reusable;
+				if (adj_reusable)
+					fmem_pdata.reserved_size += heap->size;
+			}
+		}
+
+		if (!reusable && !adj_reusable)
+			reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
+		else
+			fmem_pdata.size += heap->size;
+	}
 #endif
 }
 
@@ -447,7 +530,6 @@
 	size_pmem_devices();
 	reserve_pmem_memory();
 	reserve_ion_memory();
-	reserve_fmem_memory();
 	reserve_mdp_memory();
 }
 
@@ -480,8 +562,8 @@
 
 	if (high - low <= bank_size)
 		return;
-	msm8960_reserve_info.low_unstable_address = high -
-						MIN_MEMORY_BLOCK_SIZE;
+	msm8960_reserve_info.low_unstable_address = mb->start -
+					MIN_MEMORY_BLOCK_SIZE + mb->size;
 	msm8960_reserve_info.max_unstable_size = MIN_MEMORY_BLOCK_SIZE;
 
 	msm8960_reserve_info.bank_size = bank_size;
@@ -890,15 +972,15 @@
 
 static void __init msm8960_init_irq(void)
 {
-	msm_mpm_irq_extn_init();
+	struct msm_mpm_device_data *data = NULL;
+
+#ifdef CONFIG_MSM_MPM
+	data = &msm8960_mpm_dev_data;
+#endif
+
+	msm_mpm_irq_extn_init(data);
 	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
 						(void *)MSM_QGIC_CPU_BASE);
-
-	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-	writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
-	writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-	mb();
 }
 
 static void __init msm8960_init_buses(void)
@@ -1392,8 +1474,8 @@
 	},
 };
 
-/* configuration data */
-static const u8 mxt_config_data[] = {
+/* configuration data for mxt1386 */
+static const u8 mxt1386_config_data[] = {
 	/* T6 Object */
 	0, 0, 0, 0, 0, 0,
 	/* T38 Object */
@@ -1439,6 +1521,118 @@
 	0, 0, 0, 0, 0, 0,
 };
 
+/* configuration data for mxt1386e using V1.0 firmware */
+static const u8 mxt1386e_config_data_v1_0[] = {
+	/* T6 Object */
+	0, 0, 0, 0, 0, 0,
+	/* T38 Object */
+	12, 1, 0, 17, 1, 12, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0,
+	/* T7 Object */
+	100, 16, 50,
+	/* T8 Object */
+	25, 0, 20, 20, 0, 0, 20, 50, 0, 0,
+	/* T9 Object */
+	131, 0, 0, 26, 42, 0, 32, 80, 2, 5,
+	0, 5, 5, 0, 10, 30, 10, 10, 255, 2,
+	85, 5, 10, 10, 10, 10, 135, 55, 70, 40,
+	10, 5, 0, 0, 0,
+	/* T18 Object */
+	0, 0,
+	/* T24 Object */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0,
+	/* T25 Object */
+	3, 0, 60, 115, 156, 99,
+	/* T27 Object */
+	0, 0, 0, 0, 0, 0, 0,
+	/* T40 Object */
+	0, 0, 0, 0, 0,
+	/* T42 Object */
+	2, 0, 255, 0, 255, 0, 0, 0, 0, 0,
+	/* T43 Object */
+	0, 0, 0, 0, 0, 0, 0,
+	/* T46 Object */
+	64, 0, 20, 20, 0, 0, 0, 0, 0,
+	/* T47 Object */
+	0, 0, 0, 0, 0, 0, 3, 64, 66, 0,
+	/* T48 Object */
+	31, 64, 64, 0, 0, 0, 0, 0, 0, 0,
+	48, 40, 0, 10, 10, 0, 0, 100, 10, 80,
+	0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+	52, 0, 12, 0, 17, 0, 1, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0,
+	/* T56 Object */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	2, 99, 33,
+};
+
+/* configuration data for mxt1386e using V2.1 firmware */
+static const u8 mxt1386e_config_data_v2_1[] = {
+	/* T6 Object */
+	0, 0, 0, 0, 0, 0,
+	/* T38 Object */
+	12, 2, 0, 17, 1, 12, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0,
+	/* T7 Object */
+	100, 16, 50,
+	/* T8 Object */
+	25, 0, 20, 20, 0, 0, 20, 50, 0, 0,
+	/* T9 Object */
+	131, 0, 0, 26, 42, 0, 32, 80, 2, 5,
+	0, 5, 5, 0, 10, 30, 10, 10, 255, 2,
+	85, 5, 10, 10, 10, 10, 135, 55, 70, 40,
+	10, 5, 0, 0, 0,
+	/* T18 Object */
+	0, 0,
+	/* T24 Object */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0,
+	/* T25 Object */
+	3, 0, 60, 115, 156, 99,
+	/* T27 Object */
+	0, 0, 0, 0, 0, 0, 0,
+	/* T40 Object */
+	0, 0, 0, 0, 0,
+	/* T42 Object */
+	2, 0, 255, 0, 255, 0, 0, 0, 0, 0,
+	/* T43 Object */
+	0, 0, 0, 0, 0, 0, 0, 64, 0, 8,
+	16,
+	/* T46 Object */
+	64, 0, 20, 20, 0, 0, 0, 0, 0,
+	/* T47 Object */
+	0, 0, 0, 0, 0, 0, 3, 64, 66, 0,
+	/* T48 Object */
+	31, 64, 64, 0, 0, 0, 0, 0, 0, 0,
+	48, 40, 0, 10, 10, 0, 0, 100, 10, 80,
+	0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+	52, 0, 12, 0, 17, 0, 1, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0,
+	/* T56 Object */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	2, 99, 33, 0, 149, 24, 193, 255, 255, 255,
+	255,
+};
+
 #define MXT_TS_GPIO_IRQ			11
 #define MXT_TS_LDO_EN_GPIO		50
 #define MXT_TS_RESET_GPIO		52
@@ -1467,9 +1661,36 @@
 	gpio_free(MXT_TS_LDO_EN_GPIO);
 }
 
+static struct mxt_config_info mxt_config_array[] = {
+	{
+		.config		= mxt1386_config_data,
+		.config_length	= ARRAY_SIZE(mxt1386_config_data),
+		.family_id	= 0xA0,
+		.variant_id	= 0x0,
+		.version	= 0x10,
+		.build		= 0xAA,
+	},
+	{
+		.config		= mxt1386e_config_data_v1_0,
+		.config_length	= ARRAY_SIZE(mxt1386e_config_data_v1_0),
+		.family_id	= 0xA0,
+		.variant_id	= 0x2,
+		.version	= 0x10,
+		.build		= 0xAA,
+	},
+	{
+		.config		= mxt1386e_config_data_v2_1,
+		.config_length	= ARRAY_SIZE(mxt1386e_config_data_v2_1),
+		.family_id	= 0xA0,
+		.variant_id	= 0x7,
+		.version	= 0x21,
+		.build		= 0xAA,
+	},
+};
+
 static struct mxt_platform_data mxt_platform_data = {
-	.config			= mxt_config_data,
-	.config_length		= ARRAY_SIZE(mxt_config_data),
+	.config_array		= mxt_config_array,
+	.config_array_size	= ARRAY_SIZE(mxt_config_array),
 	.x_size			= 1365,
 	.y_size			= 767,
 	.irqflags		= IRQF_TRIGGER_FALLING,
@@ -1514,21 +1735,6 @@
 	.src_clk_rate = 24000000,
 };
 
-static struct msm_rpm_platform_data msm_rpm_data = {
-	.reg_base_addrs = {
-		[MSM_RPM_PAGE_STATUS] = MSM_RPM_BASE,
-		[MSM_RPM_PAGE_CTRL] = MSM_RPM_BASE + 0x400,
-		[MSM_RPM_PAGE_REQ] = MSM_RPM_BASE + 0x600,
-		[MSM_RPM_PAGE_ACK] = MSM_RPM_BASE + 0xa00,
-	},
-
-	.irq_ack = RPM_APCC_CPU0_GP_HIGH_IRQ,
-	.irq_err = RPM_APCC_CPU0_GP_LOW_IRQ,
-	.irq_vmpm = RPM_APCC_CPU0_GP_MEDIUM_IRQ,
-	.msm_apps_ipc_rpm_reg = MSM_APCS_GCC_BASE + 0x008,
-	.msm_apps_ipc_rpm_val = 4,
-};
-
 static struct msm_pm_sleep_status_data msm_pm_slp_sts_data = {
 	.base_addr = MSM_ACC0_BASE + 0x08,
 	.cpu_offset = MSM_ACC1_BASE - MSM_ACC0_BASE,
@@ -1582,14 +1788,6 @@
 		.tsens_num_sensor	= 5,
 };
 
-static struct platform_device msm_tsens_device = {
-	.name	= "tsens8960-tm",
-	.id	= -1,
-	.dev	= {
-		.platform_data = &msm_tsens_pdata,
-	},
-};
-
 #ifdef CONFIG_MSM_FAKE_BATTERY
 static struct platform_device fish_battery_device = {
 	.name = "fish_battery",
@@ -1638,25 +1836,6 @@
 	},
 };
 
-static struct msm_rpm_log_platform_data msm_rpm_log_pdata = {
-	.phys_addr_base = 0x0010C000,
-	.reg_offsets = {
-		[MSM_RPM_LOG_PAGE_INDICES] = 0x00000080,
-		[MSM_RPM_LOG_PAGE_BUFFER]  = 0x000000A0,
-	},
-	.phys_size = SZ_8K,
-	.log_len = 4096,		  /* log's buffer length in bytes */
-	.log_len_mask = (4096 >> 2) - 1,  /* length mask in units of u32 */
-};
-
-static struct platform_device msm_rpm_log_device = {
-	.name	= "msm_rpm_log",
-	.id	= -1,
-	.dev	= {
-		.platform_data = &msm_rpm_log_pdata,
-	},
-};
-
 static struct platform_device *common_devices[] __initdata = {
 	&msm8960_device_dmov,
 	&msm_device_smd,
@@ -1665,8 +1844,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,
@@ -1707,14 +1886,13 @@
 #ifdef CONFIG_HW_RANDOM_MSM
 	&msm_device_rng,
 #endif
-	&msm_rpm_device,
 #ifdef CONFIG_ION_MSM
 	&ion_dev,
 #endif
-	&msm_rpm_log_device,
-	&msm_rpm_stat_device,
+	&msm8960_rpm_device,
+	&msm8960_rpm_log_device,
+	&msm8960_rpm_stat_device,
 	&msm_device_tz_log,
-
 #ifdef CONFIG_MSM_QDSS
 	&msm_etb_device,
 	&msm_tpiu_device,
@@ -1827,7 +2005,6 @@
 	&msm_bus_mm_fabric,
 	&msm_bus_sys_fpb,
 	&msm_bus_cpss_fpb,
-	&msm_tsens_device,
 };
 
 static void __init msm8960_i2c_init(void)
@@ -1857,6 +2034,7 @@
 }
 
 static struct msm_cpuidle_state msm_cstates[] __initdata = {
+
 	{0, 0, "C0", "WFI",
 		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
 
@@ -1917,7 +2095,7 @@
 	},
 };
 
-static struct msm_rpmrs_level msm_rpmrs_levels[] __initdata = {
+static struct msm_rpmrs_level msm_rpmrs_levels[] = {
 	{
 		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
 		MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
@@ -1981,10 +2159,50 @@
 	},
 };
 
+static struct msm_rpmrs_platform_data msm_rpmrs_data __initdata = {
+	.levels = &msm_rpmrs_levels[0],
+	.num_levels = ARRAY_SIZE(msm_rpmrs_levels),
+	.vdd_mem_levels  = {
+		[MSM_RPMRS_VDD_MEM_RET_LOW]	= 750000,
+		[MSM_RPMRS_VDD_MEM_RET_HIGH]	= 750000,
+		[MSM_RPMRS_VDD_MEM_ACTIVE]	= 1050000,
+		[MSM_RPMRS_VDD_MEM_MAX]		= 1150000,
+	},
+	.vdd_dig_levels = {
+		[MSM_RPMRS_VDD_DIG_RET_LOW]	= 500000,
+		[MSM_RPMRS_VDD_DIG_RET_HIGH]	= 750000,
+		[MSM_RPMRS_VDD_DIG_ACTIVE]	= 950000,
+		[MSM_RPMRS_VDD_DIG_MAX]		= 1150000,
+	},
+	.vdd_mask = 0x7FFFFF,
+	.rpmrs_target_id = {
+		[MSM_RPMRS_ID_PXO_CLK]		= MSM_RPM_ID_PXO_CLK,
+		[MSM_RPMRS_ID_L2_CACHE_CTL]	= MSM_RPM_ID_LAST,
+		[MSM_RPMRS_ID_VDD_DIG_0]	= MSM_RPM_ID_PM8921_S3_0,
+		[MSM_RPMRS_ID_VDD_DIG_1]	= MSM_RPM_ID_PM8921_S3_1,
+		[MSM_RPMRS_ID_VDD_MEM_0]	= MSM_RPM_ID_PM8921_L24_0,
+		[MSM_RPMRS_ID_VDD_MEM_1]	= MSM_RPM_ID_PM8921_L24_1,
+		[MSM_RPMRS_ID_RPM_CTL]		= MSM_RPM_ID_RPM_CTL,
+	},
+};
+
 static struct msm_pm_boot_platform_data msm_pm_boot_pdata __initdata = {
 	.mode = MSM_PM_BOOT_CONFIG_TZ,
 };
 
+uint32_t msm_rpm_get_swfi_latency(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(msm_rpmrs_levels); i++) {
+		if (msm_rpmrs_levels[i].sleep_mode ==
+			MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)
+			return msm_rpmrs_levels[i].latency_us;
+	}
+
+	return 0;
+}
+
 #ifdef CONFIG_I2C
 #define I2C_SURF 1
 #define I2C_FFA  (1 << 1)
@@ -2064,8 +2282,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,
 };
 
@@ -2179,9 +2397,9 @@
 		&msm8960_device_watchdog.dev.platform_data;
 
 	wdog_pdata->bark_time = 15000;
-	BUG_ON(msm_rpm_init(&msm_rpm_data));
-	BUG_ON(msm_rpmrs_levels_init(msm_rpmrs_levels,
-				ARRAY_SIZE(msm_rpmrs_levels)));
+	msm_tsens_early_init(&msm_tsens_pdata);
+	BUG_ON(msm_rpm_init(&msm8960_rpm_data));
+	BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
 	regulator_suppress_info_printing();
 	platform_device_register(&msm8960_device_rpm_regulator);
 	msm_clock_init(&msm8960_clock_init_data);
@@ -2216,9 +2434,9 @@
 
 static void __init msm8960_rumi3_init(void)
 {
-	BUG_ON(msm_rpm_init(&msm_rpm_data));
-	BUG_ON(msm_rpmrs_levels_init(msm_rpmrs_levels,
-				ARRAY_SIZE(msm_rpmrs_levels)));
+	msm_tsens_early_init(&msm_tsens_pdata);
+	BUG_ON(msm_rpm_init(&msm8960_rpm_data));
+	BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
 	regulator_suppress_info_printing();
 	platform_device_register(&msm8960_device_rpm_regulator);
 	msm_clock_init(&msm8960_dummy_clock_init_data);
@@ -2251,9 +2469,9 @@
 	if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
 		pr_err("meminfo_init() failed!\n");
 
-	BUG_ON(msm_rpm_init(&msm_rpm_data));
-	BUG_ON(msm_rpmrs_levels_init(msm_rpmrs_levels,
-				ARRAY_SIZE(msm_rpmrs_levels)));
+	msm_tsens_early_init(&msm_tsens_pdata);
+	BUG_ON(msm_rpm_init(&msm8960_rpm_data));
+	BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
 
 	regulator_suppress_info_printing();
 	if (msm_xo_init())
diff --git a/arch/arm/mach-msm/board-8960.h b/arch/arm/mach-msm/board-8960.h
index 5f4f3a0..20af7b8 100644
--- a/arch/arm/mach-msm/board-8960.h
+++ b/arch/arm/mach-msm/board-8960.h
@@ -81,6 +81,7 @@
 void msm8960_allocate_fb_region(void);
 void msm8960_pm8921_gpio_mpp_init(void);
 void msm8960_mdp_writeback(struct memtype_reserve *reserve_table);
+uint32_t msm_rpm_get_swfi_latency(void);
 #define PLATFORM_IS_CHARM25() \
 	(machine_is_msm8960_cdp() && \
 		(socinfo_get_platform_subtype() == 1) \
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index f708b11..1f19bf6 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -12,6 +12,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/io.h>
 #include <linux/i2c.h>
 #include <linux/slimbus/slimbus.h>
 #include <linux/msm_ssbi.h>
@@ -30,11 +31,12 @@
 #include <mach/gpio.h>
 #include <mach/msm_spi.h>
 #include <mach/msm_bus_board.h>
+#include <mach/msm_xo.h>
 #include "timer.h"
 #include "devices.h"
 #include "board-9615.h"
 #include <mach/cpuidle.h>
-#include <mach/pm.h>
+#include "pm.h"
 #include "acpuclock.h"
 #include "pm-boot.h"
 
@@ -244,52 +246,26 @@
 #define USB_5V_EN		3
 #define PM_USB_5V_EN	PM8018_GPIO_PM_TO_SYS(USB_5V_EN)
 
-static void msm_hsusb_vbus_power(bool on)
+static int msm_hsusb_vbus_power(bool on)
 {
 	int rc;
-	static bool vbus_is_on;
 	struct pm_gpio usb_vbus = {
 			.direction      = PM_GPIO_DIR_OUT,
 			.pull           = PM_GPIO_PULL_NO,
 			.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
-			.output_value   = 0,
 			.vin_sel        = 2,
 			.out_strength   = PM_GPIO_STRENGTH_HIGH,
 			.function       = PM_GPIO_FUNC_NORMAL,
 			.inv_int_pol    = 0,
 	};
 
-	if (vbus_is_on == on)
-		return;
+	usb_vbus.output_value = on;
 
-	if (on) {
-		rc = pm8xxx_gpio_config(PM_USB_5V_EN, &usb_vbus);
-		if (rc) {
-			pr_err("failed to config usb_5v_en gpio\n");
-			return;
-		}
+	rc = pm8xxx_gpio_config(PM_USB_5V_EN, &usb_vbus);
+	if (rc)
+		pr_err("failed to config usb_5v_en gpio\n");
 
-		rc = gpio_request(PM_USB_5V_EN,
-						"usb_5v_en");
-		if (rc < 0) {
-			pr_err("failed to request usb_5v_en gpio\n");
-			return;
-		}
-
-		rc = gpio_direction_output(PM_USB_5V_EN, 1);
-		if (rc) {
-			pr_err("%s: unable to set_direction for gpio [%d]\n",
-				__func__, PM_USB_5V_EN);
-			goto free_usb_5v_en;
-		}
-
-		vbus_is_on = true;
-		return;
-	}
-	gpio_set_value(PM_USB_5V_EN, 0);
-free_usb_5v_en:
-	gpio_free(PM_USB_5V_EN);
-	vbus_is_on = false;
+	return rc;
 }
 
 static int shelby_phy_init_seq[] = {
@@ -301,9 +277,10 @@
 	-1};
 
 #define USB_BAM_PHY_BASE	0x12502000
-#define USB_BAM_PHY_SIZE	0x10000
+#define HSIC_BAM_PHY_BASE	0x12542000
 #define A2_BAM_PHY_BASE		0x124C2000
 static struct usb_bam_pipe_connect msm_usb_bam_connections[4][2] = {
+#ifndef CONFIG_USB_GADGET_CI13XXX_MSM_HSIC
 	[0][USB_TO_PEER_PERIPHERAL] = {
 		.src_phy_addr = USB_BAM_PHY_BASE,
 		.src_pipe_index = 11,
@@ -324,13 +301,119 @@
 		.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,
+		.src_pipe_index = 1,
+		.dst_phy_addr = A2_BAM_PHY_BASE,
+		.dst_pipe_index = 0,
+		.data_fifo_base_offset = 0x1100,
+		.data_fifo_size = 0x600,
+		.desc_fifo_base_offset = 0x1700,
+		.desc_fifo_size = 0x300,
+	},
+	[0][PEER_PERIPHERAL_TO_USB] = {
+		.src_phy_addr = A2_BAM_PHY_BASE,
+		.src_pipe_index = 1,
+		.dst_phy_addr = HSIC_BAM_PHY_BASE,
+		.dst_pipe_index = 0,
+		.data_fifo_base_offset = 0xa00,
+		.data_fifo_size = 0x600,
+		.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
 };
 
 static struct msm_usb_bam_platform_data msm_usb_bam_pdata = {
 	.connections = &msm_usb_bam_connections[0][0],
-	.usb_bam_phy_base = USB_BAM_PHY_BASE,
-	.usb_bam_phy_size = USB_BAM_PHY_SIZE,
-	.usb_bam_num_pipes = 32,
+#ifndef CONFIG_USB_GADGET_CI13XXX_MSM_HSIC
+	.usb_active_bam = HSUSB_BAM,
+	.usb_bam_num_pipes = 16,
+#else
+	.usb_active_bam = HSIC_BAM,
+	.usb_bam_num_pipes = 16,
+#endif
 };
 
 static struct msm_otg_platform_data msm_otg_pdata = {
@@ -341,8 +424,55 @@
 	.disable_reset_on_disconnect	= true,
 };
 
+#define PID_MAGIC_ID		0x71432909
+#define SERIAL_NUM_MAGIC_ID	0x61945374
+#define SERIAL_NUMBER_LENGTH	127
+#define DLOAD_USB_BASE_ADD	0x2B0000C8
+
+struct magic_num_struct {
+	uint32_t pid;
+	uint32_t serial_num;
+};
+
+struct dload_struct {
+	uint32_t	reserved1;
+	uint32_t	reserved2;
+	uint32_t	reserved3;
+	uint16_t	reserved4;
+	uint16_t	pid;
+	char		serial_number[SERIAL_NUMBER_LENGTH];
+	uint16_t	reserved5;
+	struct magic_num_struct magic_struct;
+};
+
 static int usb_diag_update_pid_and_serial_num(uint32_t pid, const char *snum)
 {
+	struct dload_struct __iomem *dload = 0;
+
+	dload = ioremap(DLOAD_USB_BASE_ADD, sizeof(*dload));
+	if (!dload) {
+		pr_err("%s: cannot remap I/O memory region: %08x\n",
+					__func__, DLOAD_USB_BASE_ADD);
+		return -ENXIO;
+	}
+
+	pr_debug("%s: dload:%p pid:%x serial_num:%s\n",
+				__func__, dload, pid, snum);
+	/* update pid */
+	dload->magic_struct.pid = PID_MAGIC_ID;
+	dload->pid = pid;
+
+	/* update serial number */
+	dload->magic_struct.serial_num = 0;
+	if (!snum) {
+		memset(dload->serial_number, 0, SERIAL_NUMBER_LENGTH);
+		goto out;
+	}
+
+	dload->magic_struct.serial_num = SERIAL_NUM_MAGIC_ID;
+	strlcpy(dload->serial_number, snum, SERIAL_NUMBER_LENGTH);
+out:
+	iounmap(dload);
 	return 0;
 }
 
@@ -400,7 +530,7 @@
 	&msm9615_device_tsens,
 	&msm_device_nand,
 	&msm_device_bam_dmux,
-	&msm_rpm_device,
+	&msm9615_rpm_device,
 #ifdef CONFIG_HW_RANDOM_MSM
 	&msm_device_rng,
 #endif
@@ -417,6 +547,8 @@
 	&msm9615_device_watchdog,
 	&msm_bus_9615_sys_fabric,
 	&msm_bus_def_fab,
+	&msm9615_rpm_log_device,
+	&msm9615_rpm_stat_device,
 };
 
 static void __init msm9615_i2c_init(void)
@@ -437,6 +569,7 @@
 	msm9615_i2c_init();
 	regulator_suppress_info_printing();
 	platform_device_register(&msm9615_device_rpm_regulator);
+	msm_xo_init();
 	msm_clock_init(&msm9615_clock_init_data);
 	msm9615_init_buses();
 	msm9615_device_qup_spi_gsbi3.dev.platform_data =
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index f26187e..b4b0b9a 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.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
@@ -18,14 +18,193 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#ifdef CONFIG_ION_MSM
+#include <linux/ion.h>
+#endif
+#include <linux/memory.h>
+#ifdef CONFIG_ANDROID_PMEM
+#include <linux/android_pmem.h>
+#endif
 #include <asm/mach/map.h>
 #include <asm/hardware/gic.h>
 #include <mach/board.h>
 #include <mach/gpio.h>
 #include <mach/gpiomux.h>
 #include <mach/msm_iomap.h>
+#ifdef CONFIG_ION_MSM
+#include <mach/ion.h>
+#endif
+#include <mach/msm_memtypes.h>
 #include "clock.h"
 
+#define MSM_KERNEL_EBI1_MEM_SIZE	0x280000
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+#define MSM_ION_SF_SIZE 0x4000000 /* 64 Mbytes */
+#else
+#define MSM_ION_SF_SIZE 0x2800000 /* 40 Mbytes */
+#endif
+#define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
+#define MSM_ION_MM_SIZE		0x7800000 /* (120MB) */
+#define MSM_ION_QSECOM_SIZE	0x100000 /* (1MB) */
+#define MSM_ION_MFC_SIZE	SZ_8K
+#define MSM_ION_AUDIO_SIZE	0x2B4000
+#define MSM_ION_HEAP_NUM	8
+
+#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
+static unsigned kernel_ebi1_mem_size = MSM_KERNEL_EBI1_MEM_SIZE;
+static int __init kernel_ebi1_mem_size_setup(char *p)
+{
+	kernel_ebi1_mem_size = memparse(p, NULL);
+	return 0;
+}
+early_param("kernel_ebi1_mem_size", kernel_ebi1_mem_size_setup);
+#endif
+
+static struct memtype_reserve msm_copper_reserve_table[] __initdata = {
+	[MEMTYPE_SMI] = {
+	},
+	[MEMTYPE_EBI0] = {
+		.flags	=	MEMTYPE_FLAGS_1M_ALIGN,
+	},
+	[MEMTYPE_EBI1] = {
+		.flags	=	MEMTYPE_FLAGS_1M_ALIGN,
+	},
+};
+
+static int msm_copper_paddr_to_memtype(unsigned int paddr)
+{
+	return MEMTYPE_EBI1;
+}
+
+#ifdef CONFIG_ION_MSM
+static struct ion_cp_heap_pdata cp_mm_ion_pdata = {
+	.permission_type = IPT_TYPE_MM_CARVEOUT,
+	.align = PAGE_SIZE,
+};
+
+static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
+	.permission_type = IPT_TYPE_MFC_SHAREDMEM,
+	.align = PAGE_SIZE,
+};
+
+static struct ion_co_heap_pdata co_ion_pdata = {
+	.adjacent_mem_id = INVALID_HEAP_ID,
+	.align = PAGE_SIZE,
+};
+
+static struct ion_co_heap_pdata fw_co_ion_pdata = {
+	.adjacent_mem_id = ION_CP_MM_HEAP_ID,
+	.align = SZ_128K,
+};
+
+static struct ion_platform_data ion_pdata = {
+	.nr = MSM_ION_HEAP_NUM,
+	.heaps = {
+		{
+			.id	= ION_SYSTEM_HEAP_ID,
+			.type	= ION_HEAP_TYPE_SYSTEM,
+			.name	= ION_VMALLOC_HEAP_NAME,
+		},
+		{
+			.id	= ION_SF_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_SF_HEAP_NAME,
+			.size	= MSM_ION_SF_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_ion_pdata,
+		},
+		{
+			.id	= ION_CP_MM_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CP,
+			.name	= ION_MM_HEAP_NAME,
+			.size	= MSM_ION_MM_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &cp_mm_ion_pdata,
+		},
+		{
+			.id	= ION_MM_FIRMWARE_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_MM_FIRMWARE_HEAP_NAME,
+			.size	= MSM_ION_MM_FW_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &fw_co_ion_pdata,
+		},
+		{
+			.id	= ION_CP_MFC_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CP,
+			.name	= ION_MFC_HEAP_NAME,
+			.size	= MSM_ION_MFC_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &cp_mfc_ion_pdata,
+		},
+		{
+			.id	= ION_IOMMU_HEAP_ID,
+			.type	= ION_HEAP_TYPE_IOMMU,
+			.name	= ION_IOMMU_HEAP_NAME,
+		},
+		{
+			.id	= ION_QSECOM_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_QSECOM_HEAP_NAME,
+			.size	= MSM_ION_QSECOM_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_ion_pdata,
+		},
+		{
+			.id	= ION_AUDIO_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_AUDIO_HEAP_NAME,
+			.size	= MSM_ION_AUDIO_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_ion_pdata,
+		},
+	}
+};
+
+static struct platform_device ion_dev = {
+	.name = "ion-msm",
+	.id = 1,
+	.dev = { .platform_data = &ion_pdata },
+};
+
+static void reserve_ion_memory(void)
+{
+	msm_copper_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_SIZE;
+	msm_copper_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_FW_SIZE;
+	msm_copper_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE;
+	msm_copper_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MFC_SIZE;
+	msm_copper_reserve_table[MEMTYPE_EBI1].size += MSM_ION_QSECOM_SIZE;
+	msm_copper_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE;
+#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
+	msm_copper_reserve_table[MEMTYPE_EBI1].size += kernel_ebi1_mem_size;
+#endif
+}
+#endif
+
+static void __init msm_copper_calculate_reserve_sizes(void)
+{
+#ifdef CONFIG_ION_MSM
+	reserve_ion_memory();
+#endif
+}
+
+static struct reserve_info msm_copper_reserve_info __initdata = {
+	.memtype_reserve_table = msm_copper_reserve_table,
+	.calculate_reserve_sizes = msm_copper_calculate_reserve_sizes,
+	.paddr_to_memtype = msm_copper_paddr_to_memtype,
+};
+
+static void __init msm_copper_early_memory(void)
+{
+	reserve_info = &msm_copper_reserve_info;
+}
+
+void __init msm_copper_reserve(void)
+{
+	msm_reserve();
+}
+
 static int __init gpiomux_init(void)
 {
 	int rc;
@@ -41,26 +220,20 @@
 
 void __init msm_copper_add_devices(void)
 {
+#ifdef CONFIG_ION_MSM
+	platform_device_register(&ion_dev);
+#endif
 }
 
-static struct of_device_id msm_copper_gic_match[] __initdata = {
-	{ .compatible = "qcom,msm-qgic2", },
+static struct of_device_id irq_match[] __initdata  = {
+	{ .compatible = "qcom,msm-qgic2", .data = gic_of_init, },
+	{ .compatible = "qcom,msm-gpio", .data = msm_gpio_of_init, },
 	{}
 };
 
 void __init msm_copper_init_irq(void)
 {
-	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
-			(void *)MSM_QGIC_CPU_BASE);
-
-	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-	writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
-	writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-	mb();
-
-	irq_domain_generate_simple(msm_copper_gic_match,
-		COPPER_QGIC_DIST_PHYS, GIC_SPI_START);
+	of_irq_init(irq_match);
 }
 
 static struct clk_lookup msm_clocks_dummy[] = {
@@ -104,3 +277,8 @@
 
 	*adata = msm_copper_auxdata_lookup;
 }
+
+void __init msm_copper_very_early(void)
+{
+	msm_copper_early_memory();
+}
diff --git a/arch/arm/mach-msm/board-dt.c b/arch/arm/mach-msm/board-dt.c
index 19f54cf..51ca29d 100644
--- a/arch/arm/mach-msm/board-dt.c
+++ b/arch/arm/mach-msm/board-dt.c
@@ -28,7 +28,7 @@
 {
 	struct device_node *node;
 	struct resource res;
-	struct of_irq oirq;
+	int rc;
 
 	node = of_find_compatible_node(NULL, NULL, "qcom,msm-qtimer");
 	if (!node) {
@@ -36,13 +36,12 @@
 		return;
 	}
 
-	if (of_irq_map_one(node, 0, &oirq)) {
+	rc = of_irq_to_resource(node, 0, &res);
+	if (rc < 0)
 		pr_err("interrupt not specified in timer node\n");
-	} else {
-		res.start = res.end = oirq.specifier[0];
-		res.flags = IORESOURCE_IRQ;
+	else
 		arch_timer_register(&res, 1);
-	}
+
 	of_node_put(node);
 }
 
@@ -91,6 +90,18 @@
 	NULL
 };
 
+static void __init msm_dt_reserve(void)
+{
+	if (early_machine_is_copper())
+		msm_copper_reserve();
+}
+
+static void __init msm_dt_init_very_early(void)
+{
+	if (early_machine_is_copper())
+		msm_copper_very_early();
+}
+
 DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
 	.map_io = msm_dt_map_io,
 	.init_irq = msm_dt_init_irq,
@@ -98,4 +109,7 @@
 	.handle_irq = gic_handle_irq,
 	.timer = &msm_dt_timer,
 	.dt_compat = msm_dt_match,
+	.nr_irqs = -1,
+	.reserve = msm_dt_reserve,
+	.init_very_early = msm_dt_init_very_early,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-fsm9xxx.c b/arch/arm/mach-msm/board-fsm9xxx.c
index 36ab719..87fea3f 100644
--- a/arch/arm/mach-msm/board-fsm9xxx.c
+++ b/arch/arm/mach-msm/board-fsm9xxx.c
@@ -38,7 +38,7 @@
 #include "devices.h"
 #include "timer.h"
 #include "acpuclock.h"
-#include <mach/pm.h>
+#include "pm.h"
 #include "spm.h"
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/machine.h>
diff --git a/arch/arm/mach-msm/board-msm7627a-bt.c b/arch/arm/mach-msm/board-msm7627a-bt.c
index 8b3b606..5acfcd5 100644
--- a/arch/arm/mach-msm/board-msm7627a-bt.c
+++ b/arch/arm/mach-msm/board-msm7627a-bt.c
@@ -100,6 +100,8 @@
 {
 	if (machine_is_msm7627a_qrd1())
 		gpio_bt_sys_rest_en = 114;
+	if (machine_is_msm7627a_evb())
+		gpio_bt_sys_rest_en = 16;
 }
 
 static int bt_set_gpio(int on)
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index a3c2da3..e3f668f 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -23,6 +23,289 @@
 #include "devices-msm7x2xa.h"
 #include "board-msm7627a.h"
 
+#ifdef CONFIG_MSM_CAMERA_V4L2
+static uint32_t camera_off_gpio_table[] = {
+	GPIO_CFG(15, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+};
+
+static uint32_t camera_on_gpio_table[] = {
+	GPIO_CFG(15, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+};
+
+#ifdef CONFIG_MSM_CAMERA_FLASH
+static struct msm_camera_sensor_flash_src msm_flash_src = {
+	.flash_sr_type = MSM_CAMERA_FLASH_SRC_EXT,
+	._fsrc.ext_driver_src.led_en = GPIO_CAM_GP_LED_EN1,
+	._fsrc.ext_driver_src.led_flash_en = GPIO_CAM_GP_LED_EN2,
+};
+#endif
+
+static struct regulator_bulk_data regs_camera[] = {
+	{ .supply = "msme1", .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "gp2",   .min_uV = 2850000, .max_uV = 2850000 },
+	{ .supply = "usb2",  .min_uV = 1800000, .max_uV = 1800000 },
+};
+
+static void msm_camera_vreg_config(int vreg_en)
+{
+	int rc = vreg_en ?
+		regulator_bulk_enable(ARRAY_SIZE(regs_camera), regs_camera) :
+		regulator_bulk_disable(ARRAY_SIZE(regs_camera), regs_camera);
+
+	if (rc)
+		pr_err("%s: could not %sable regulators: %d\n",
+				__func__, vreg_en ? "en" : "dis", rc);
+}
+
+static int config_gpio_table(uint32_t *table, int len)
+{
+	int rc = 0, i = 0;
+
+	for (i = 0; i < len; i++) {
+		rc = gpio_tlmm_config(table[i], GPIO_CFG_ENABLE);
+		if (rc) {
+			pr_err("%s not able to get gpio\n", __func__);
+			for (i--; i >= 0; i--)
+				gpio_tlmm_config(camera_off_gpio_table[i],
+							GPIO_CFG_ENABLE);
+			break;
+		}
+	}
+	return rc;
+}
+
+static struct msm_camera_sensor_info msm_camera_sensor_s5k4e1_data;
+/* TODO: static struct msm_camera_sensor_info msm_camera_sensor_ov9726_data; */
+static int config_camera_on_gpios_rear(void)
+{
+	int rc = 0;
+
+	if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa())
+		msm_camera_vreg_config(1);
+
+	rc = config_gpio_table(camera_on_gpio_table,
+			ARRAY_SIZE(camera_on_gpio_table));
+	if (rc < 0) {
+		pr_err("%s: CAMSENSOR gpio table request"
+		"failed\n", __func__);
+		return rc;
+	}
+
+	return rc;
+}
+
+static void config_camera_off_gpios_rear(void)
+{
+	if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa())
+		msm_camera_vreg_config(0);
+
+	config_gpio_table(camera_off_gpio_table,
+			ARRAY_SIZE(camera_off_gpio_table));
+}
+
+static int config_camera_on_gpios_front(void)
+{
+	int rc = 0;
+
+	if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa())
+		msm_camera_vreg_config(1);
+
+	rc = config_gpio_table(camera_on_gpio_table,
+			ARRAY_SIZE(camera_on_gpio_table));
+	if (rc < 0) {
+		pr_err("%s: CAMSENSOR gpio table request"
+			"failed\n", __func__);
+		return rc;
+	}
+
+	return rc;
+}
+
+static void config_camera_off_gpios_front(void)
+{
+	if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa())
+		msm_camera_vreg_config(0);
+
+	config_gpio_table(camera_off_gpio_table,
+			ARRAY_SIZE(camera_off_gpio_table));
+}
+
+struct msm_camera_device_platform_data msm_camera_device_data_csi1 = {
+	.camera_gpio_on  = config_camera_on_gpios_rear,
+	.camera_gpio_off = config_camera_off_gpios_rear,
+	.ioclk.mclk_clk_rate = 24000000,
+	.ioclk.vfe_clk_rate  = 192000000,
+	.csid_core = 1,
+	.is_csic = 1,
+};
+
+struct msm_camera_device_platform_data msm_camera_device_data_csi0 = {
+	.camera_gpio_on  = config_camera_on_gpios_front,
+	.camera_gpio_off = config_camera_off_gpios_front,
+	.ioclk.mclk_clk_rate = 24000000,
+	.ioclk.vfe_clk_rate  = 192000000,
+	.csid_core = 0,
+};
+
+#ifdef CONFIG_DW9712_ACT
+static struct i2c_board_info s5k4e1_actuator_i2c_info = {
+	I2C_BOARD_INFO("dw9712_act", 0x8C >> 1),
+};
+
+static struct msm_actuator_info s5k4e1_actuator_info = {
+	.board_info     = &s5k4e1_actuator_i2c_info,
+	.bus_id         = MSM_GSBI0_QUP_I2C_BUS_ID,
+	.vcm_pwd        = GPIO_CAM_GP_CAM_PWDN,
+	.vcm_enable     = 1,
+};
+#endif
+
+#ifdef CONFIG_S5K4E1
+static struct msm_camera_sensor_flash_data flash_s5k4e1 = {
+	.flash_type             = MSM_CAMERA_FLASH_LED,
+	.flash_src              = &msm_flash_src
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_s5k4e1 = {
+	.mount_angle	= 90,
+	.sensor_reset	= GPIO_CAM_GP_CAMIF_RESET_N,
+	.sensor_pwd	= 85,
+	.vcm_pwd	= GPIO_CAM_GP_CAM_PWDN,
+	.vcm_enable	= 1,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_s5k4e1_data = {
+	.sensor_name    = "s5k4e1",
+	.sensor_reset_enable = 1,
+	.pdata                  = &msm_camera_device_data_csi1,
+	.flash_data             = &flash_s5k4e1,
+	.sensor_platform_info   = &sensor_board_info_s5k4e1,
+	.csi_if                 = 1,
+	.camera_type = BACK_CAMERA_2D,
+#ifdef CONFIG_DW9712_ACT
+	.actuator_info = &s5k4e1_actuator_info
+#endif
+};
+#endif
+
+#ifdef CONFIG_MT9E013
+static struct msm_camera_sensor_flash_data flash_mt9e013 = {
+	.flash_type             = MSM_CAMERA_FLASH_LED,
+	.flash_src              = &msm_flash_src
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_mt9e013 = {
+	.mount_angle	= 90,
+	.sensor_reset	= 0,
+	.sensor_pwd	= 85,
+	.vcm_pwd	= 1,
+	.vcm_enable	= 0,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_mt9e013_data = {
+	.sensor_name    = "mt9e013",
+	.sensor_reset_enable = 1,
+	.pdata                  = &msm_camera_device_data_csi1,
+	.flash_data             = &flash_mt9e013,
+	.sensor_platform_info   = &sensor_board_info_mt9e013,
+	.csi_if                 = 1,
+	.camera_type = BACK_CAMERA_2D,
+};
+#endif
+
+#ifdef CONFIG_IMX072
+static struct msm_camera_sensor_platform_info imx072_sensor_7627a_info = {
+	.mount_angle = 90
+};
+
+static struct msm_camera_sensor_flash_data flash_imx072 = {
+	.flash_type             = MSM_CAMERA_FLASH_LED,
+	.flash_src              = &msm_flash_src
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_imx072_data = {
+	.sensor_name    = "imx072",
+	.sensor_reset_enable = 1,
+	.sensor_reset   = GPIO_CAM_GP_CAMIF_RESET_N, /* TODO 106,*/
+	.sensor_pwd             = 85,
+	.vcm_pwd                = GPIO_CAM_GP_CAM_PWDN,
+	.vcm_enable             = 1,
+	.pdata                  = &msm_camera_device_data_csi1,
+	.flash_data             = &flash_imx072,
+	.sensor_platform_info = &imx072_sensor_7627a_info,
+	.csi_if                 = 1
+};
+
+static struct platform_device msm_camera_sensor_imx072 = {
+	.name   = "msm_camera_imx072",
+	.dev    = {
+		.platform_data = &msm_camera_sensor_imx072_data,
+	},
+};
+#endif
+
+#ifdef CONFIG_WEBCAM_OV9726
+static struct msm_camera_sensor_flash_data flash_ov9726 = {
+	.flash_type             = MSM_CAMERA_FLASH_LED,
+	.flash_src              = &msm_flash_src
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_ov9726 = {
+	.mount_angle	= 90,
+	.sensor_reset	= GPIO_CAM_GP_CAM1MP_XCLR,
+	.sensor_pwd	= 85,
+	.vcm_pwd	= 1,
+	.vcm_enable	= 0,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_ov9726_data = {
+	.sensor_name    = "ov9726",
+	.sensor_reset_enable = 0,
+	.pdata                  = &msm_camera_device_data_csi0,
+	.flash_data             = &flash_ov9726,
+	.sensor_platform_info   = &sensor_board_info_ov9726,
+	.csi_if                 = 1,
+	.camera_type = FRONT_CAMERA_2D,
+};
+#endif
+
+static void __init msm7x27a_init_cam(void)
+{
+	platform_device_register(&msm7x27a_device_csic0);
+	platform_device_register(&msm7x27a_device_csic1);
+	platform_device_register(&msm7x27a_device_clkctl);
+	platform_device_register(&msm7x27a_device_vfe);
+}
+
+static struct i2c_board_info i2c_camera_devices[] = {
+	#ifdef CONFIG_S5K4E1
+	{
+		I2C_BOARD_INFO("s5k4e1", 0x36),
+		.platform_data = &msm_camera_sensor_s5k4e1_data,
+	},
+	#endif
+	#ifdef CONFIG_WEBCAM_OV9726
+	{
+		I2C_BOARD_INFO("ov9726", 0x10),
+		.platform_data = &msm_camera_sensor_ov9726_data,
+	},
+	#endif
+	#ifdef CONFIG_IMX072
+	{
+		I2C_BOARD_INFO("imx072", 0x34),
+	},
+	#endif
+	#ifdef CONFIG_MT9E013
+	{
+		I2C_BOARD_INFO("mt9e013", 0x6C >> 2),
+		.platform_data = &msm_camera_sensor_mt9e013_data,
+	},
+	#endif
+	{
+		I2C_BOARD_INFO("sc628a", 0x6E),
+	},
+};
+#else
 static uint32_t camera_off_gpio_table[] = {
 	GPIO_CFG(15, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
 };
@@ -196,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 = {
@@ -208,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
@@ -406,28 +689,6 @@
 };
 #endif
 
-enum {
-	SX150X_CAM,
-};
-
-static struct sx150x_platform_data sx150x_data[] __initdata = {
-	[SX150X_CAM]    = {
-		.gpio_base	      = GPIO_CAM_EXPANDER_BASE,
-		.oscio_is_gpo	   = false,
-		.io_pullup_ena	  = 0,
-		.io_pulldn_ena	  = 0,
-		.io_open_drain_ena      = 0x23,
-		.irq_summary	    = -1,
-	},
-};
-
-static struct i2c_board_info cam_exp_i2c_info[] __initdata = {
-	{
-		I2C_BOARD_INFO("sx1508q", 0x22),
-		.platform_data  = &sx150x_data[SX150X_CAM],
-	},
-};
-
 static struct i2c_board_info i2c_camera_devices[] = {
 	#ifdef CONFIG_S5K4E1
 	{
@@ -493,6 +754,29 @@
 	&msm_camera_sensor_ov7692,
 #endif
 };
+#endif
+
+enum {
+	SX150X_CAM,
+};
+
+static struct sx150x_platform_data sx150x_data[] __initdata = {
+	[SX150X_CAM]    = {
+		.gpio_base	      = GPIO_CAM_EXPANDER_BASE,
+		.oscio_is_gpo	   = false,
+		.io_pullup_ena	  = 0,
+		.io_pulldn_ena	  = 0,
+		.io_open_drain_ena      = 0x23,
+		.irq_summary	    = -1,
+	},
+};
+
+static struct i2c_board_info cam_exp_i2c_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("sx1508q", 0x22),
+		.platform_data  = &sx150x_data[SX150X_CAM],
+	},
+};
 
 static void __init register_i2c_devices(void)
 {
@@ -505,17 +789,19 @@
 {
 	int rc;
 
+#ifndef CONFIG_MSM_CAMERA_V4L2
 	if (machine_is_msm7627a_qrd1()) {
 		qrd1_camera_gpio_cfg();
 		platform_add_devices(camera_devices_qrd,
 				ARRAY_SIZE(camera_devices_qrd));
-	} else
+	} else if (machine_is_msm7627a_evb())
+		return;
+	else
 		platform_add_devices(camera_devices_msm,
 				ARRAY_SIZE(camera_devices_msm));
-
+#endif
 	if (!machine_is_msm7627a_qrd1())
 		register_i2c_devices();
-
 	rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_camera), regs_camera);
 
 	if (rc) {
@@ -530,11 +816,16 @@
 		return;
 	}
 
+#if defined(CONFIG_MSM_CAMERA_V4L2)
+	msm7x27a_init_cam();
+#endif
+#ifndef CONFIG_MSM_CAMERA_V4L2
 	if (machine_is_msm7627a_qrd1())
 		i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID,
 				i2c_camera_devices_qrd,
 				ARRAY_SIZE(i2c_camera_devices_qrd));
 	else
+#endif
 		i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID,
 				i2c_camera_devices,
 				ARRAY_SIZE(i2c_camera_devices));
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
new file mode 100644
index 0000000..15f681d
--- /dev/null
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -0,0 +1,856 @@
+/* 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/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+#include <linux/regulator/consumer.h>
+#include <asm/mach-types.h>
+#include <asm/io.h>
+#include <mach/msm_bus_board.h>
+#include <mach/msm_memtypes.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+#include <mach/socinfo.h>
+#include <mach/rpc_pmapp.h>
+#include "devices.h"
+#include "board-msm7627a.h"
+
+#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
+#define MSM_FB_SIZE	     0x260000
+#define MSM7x25A_MSM_FB_SIZE    0xE1000
+#else
+#define MSM_FB_SIZE	     0x195000
+#define MSM7x25A_MSM_FB_SIZE    0x96000
+#endif
+
+static unsigned fb_size = MSM_FB_SIZE;
+static int __init fb_size_setup(char *p)
+{
+	fb_size = memparse(p, NULL);
+	return 0;
+}
+
+early_param("fb_size", fb_size_setup);
+
+static struct regulator_bulk_data regs_lcdc[] = {
+	{ .supply = "gp2",   .min_uV = 2850000, .max_uV = 2850000 },
+	{ .supply = "msme1", .min_uV = 1800000, .max_uV = 1800000 },
+};
+static uint32_t lcdc_gpio_initialized;
+
+static void lcdc_toshiba_gpio_init(void)
+{
+	int rc = 0;
+	if (!lcdc_gpio_initialized) {
+		if (gpio_request(GPIO_SPI_CLK, "spi_clk")) {
+			pr_err("failed to request gpio spi_clk\n");
+			return;
+		}
+		if (gpio_request(GPIO_SPI_CS0_N, "spi_cs")) {
+			pr_err("failed to request gpio spi_cs0_N\n");
+			goto fail_gpio6;
+		}
+		if (gpio_request(GPIO_SPI_MOSI, "spi_mosi")) {
+			pr_err("failed to request gpio spi_mosi\n");
+			goto fail_gpio5;
+		}
+		if (gpio_request(GPIO_SPI_MISO, "spi_miso")) {
+			pr_err("failed to request gpio spi_miso\n");
+			goto fail_gpio4;
+		}
+		if (gpio_request(GPIO_DISPLAY_PWR_EN, "gpio_disp_pwr")) {
+			pr_err("failed to request gpio_disp_pwr\n");
+			goto fail_gpio3;
+		}
+		if (gpio_request(GPIO_BACKLIGHT_EN, "gpio_bkl_en")) {
+			pr_err("failed to request gpio_bkl_en\n");
+			goto fail_gpio2;
+		}
+		pmapp_disp_backlight_init();
+
+		rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_lcdc),
+					regs_lcdc);
+		if (rc) {
+			pr_err("%s: could not get regulators: %d\n",
+					__func__, rc);
+			goto fail_gpio1;
+		}
+
+		rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_lcdc),
+				regs_lcdc);
+		if (rc) {
+			pr_err("%s: could not set voltages: %d\n",
+					__func__, rc);
+			goto fail_vreg;
+		}
+		lcdc_gpio_initialized = 1;
+	}
+	return;
+fail_vreg:
+	regulator_bulk_free(ARRAY_SIZE(regs_lcdc), regs_lcdc);
+fail_gpio1:
+	gpio_free(GPIO_BACKLIGHT_EN);
+fail_gpio2:
+	gpio_free(GPIO_DISPLAY_PWR_EN);
+fail_gpio3:
+	gpio_free(GPIO_SPI_MISO);
+fail_gpio4:
+	gpio_free(GPIO_SPI_MOSI);
+fail_gpio5:
+	gpio_free(GPIO_SPI_CS0_N);
+fail_gpio6:
+	gpio_free(GPIO_SPI_CLK);
+	lcdc_gpio_initialized = 0;
+}
+
+static uint32_t lcdc_gpio_table[] = {
+	GPIO_SPI_CLK,
+	GPIO_SPI_CS0_N,
+	GPIO_SPI_MOSI,
+	GPIO_DISPLAY_PWR_EN,
+	GPIO_BACKLIGHT_EN,
+	GPIO_SPI_MISO,
+};
+
+static void config_lcdc_gpio_table(uint32_t *table, int len, unsigned enable)
+{
+	int n;
+
+	if (lcdc_gpio_initialized) {
+		/* All are IO Expander GPIOs */
+		for (n = 0; n < (len - 1); n++)
+			gpio_direction_output(table[n], 1);
+	}
+}
+
+static void lcdc_toshiba_config_gpios(int enable)
+{
+	config_lcdc_gpio_table(lcdc_gpio_table,
+		ARRAY_SIZE(lcdc_gpio_table), enable);
+}
+
+static int msm_fb_lcdc_power_save(int on)
+{
+	int rc = 0;
+	/* Doing the init of the LCDC GPIOs very late as they are from
+		an I2C-controlled IO Expander */
+	lcdc_toshiba_gpio_init();
+
+	if (lcdc_gpio_initialized) {
+		gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, on);
+		gpio_set_value_cansleep(GPIO_BACKLIGHT_EN, on);
+
+		rc = on ? regulator_bulk_enable(
+				ARRAY_SIZE(regs_lcdc), regs_lcdc) :
+			  regulator_bulk_disable(
+				ARRAY_SIZE(regs_lcdc), regs_lcdc);
+
+		if (rc)
+			pr_err("%s: could not %sable regulators: %d\n",
+					__func__, on ? "en" : "dis", rc);
+	}
+
+	return rc;
+}
+
+static int lcdc_toshiba_set_bl(int level)
+{
+	int ret;
+
+	ret = pmapp_disp_backlight_set_brightness(level);
+	if (ret)
+		pr_err("%s: can't set lcd backlight!\n", __func__);
+
+	return ret;
+}
+
+static struct lcdc_platform_data lcdc_pdata = {
+	.lcdc_gpio_config = NULL,
+	.lcdc_power_save   = msm_fb_lcdc_power_save,
+};
+
+static int lcd_panel_spi_gpio_num[] = {
+		GPIO_SPI_MOSI,  /* spi_sdi */
+		GPIO_SPI_MISO,  /* spi_sdoi */
+		GPIO_SPI_CLK,   /* spi_clk */
+		GPIO_SPI_CS0_N, /* spi_cs  */
+};
+
+static struct msm_panel_common_pdata lcdc_toshiba_panel_data = {
+	.panel_config_gpio = lcdc_toshiba_config_gpios,
+	.pmic_backlight = lcdc_toshiba_set_bl,
+	.gpio_num	 = lcd_panel_spi_gpio_num,
+};
+
+static struct platform_device lcdc_toshiba_panel_device = {
+	.name   = "lcdc_toshiba_fwvga_pt",
+	.id     = 0,
+	.dev    = {
+		.platform_data = &lcdc_toshiba_panel_data,
+	}
+};
+
+static struct resource msm_fb_resources[] = {
+	{
+		.flags  = IORESOURCE_DMA,
+	}
+};
+
+#define PANEL_NAME_MAX_LEN      30
+#define LCDC_TOSHIBA_FWVGA_PANEL_NAME   "lcdc_toshiba_fwvga_pt"
+#define MIPI_CMD_RENESAS_FWVGA_PANEL_NAME       "mipi_cmd_renesas_fwvga"
+
+static int msm_fb_detect_panel(const char *name)
+{
+	int ret = -ENODEV;
+
+	if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()) {
+		if (!strncmp(name, "lcdc_toshiba_fwvga_pt", 21) ||
+				!strncmp(name, "mipi_cmd_renesas_fwvga", 22))
+			ret = 0;
+	} else if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()) {
+		if (!strncmp(name, "mipi_cmd_renesas_fwvga", 22))
+			ret = 0;
+	} else if (machine_is_msm7627a_qrd1()) {
+		if (!strncmp(name, "mipi_video_truly_wvga", 21))
+			ret = 0;
+	} else if (machine_is_msm7627a_evb()) {
+		if (!strncmp(name, "mipi_cmd_nt35510_wvga", 21))
+			ret = 0;
+	}
+
+#if !defined(CONFIG_FB_MSM_LCDC_AUTO_DETECT) && \
+	!defined(CONFIG_FB_MSM_MIPI_PANEL_AUTO_DETECT) && \
+	!defined(CONFIG_FB_MSM_LCDC_MIPI_PANEL_AUTO_DETECT)
+		if (machine_is_msm7x27a_surf() ||
+			machine_is_msm7625a_surf()) {
+			if (!strncmp(name, LCDC_TOSHIBA_FWVGA_PANEL_NAME,
+				strnlen(LCDC_TOSHIBA_FWVGA_PANEL_NAME,
+					PANEL_NAME_MAX_LEN)))
+				return 0;
+		}
+#endif
+
+	return ret;
+}
+
+static int mipi_truly_set_bl(int on)
+{
+	gpio_set_value_cansleep(QRD_GPIO_BACKLIGHT_EN, !!on);
+
+	return 1;
+}
+
+static struct msm_fb_platform_data msm_fb_pdata = {
+	.detect_client = msm_fb_detect_panel,
+};
+
+static struct platform_device msm_fb_device = {
+	.name   = "msm_fb",
+	.id     = 0,
+	.num_resources  = ARRAY_SIZE(msm_fb_resources),
+	.resource       = msm_fb_resources,
+	.dev    = {
+		.platform_data = &msm_fb_pdata,
+	}
+};
+
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+static int mipi_renesas_set_bl(int level)
+{
+	int ret;
+
+	ret = pmapp_disp_backlight_set_brightness(level);
+
+	if (ret)
+		pr_err("%s: can't set lcd backlight!\n", __func__);
+
+	return ret;
+}
+
+static struct msm_panel_common_pdata mipi_renesas_pdata = {
+	.pmic_backlight = mipi_renesas_set_bl,
+};
+
+
+static struct platform_device mipi_dsi_renesas_panel_device = {
+	.name = "mipi_renesas",
+	.id = 0,
+	.dev    = {
+		.platform_data = &mipi_renesas_pdata,
+	}
+};
+#endif
+
+static struct msm_panel_common_pdata mipi_truly_pdata = {
+	.pmic_backlight = mipi_truly_set_bl,
+};
+
+static struct platform_device mipi_dsi_truly_panel_device = {
+	.name   = "mipi_truly",
+	.id     = 0,
+	.dev    = {
+		.platform_data = &mipi_truly_pdata,
+	}
+};
+
+static struct msm_panel_common_pdata mipi_NT35510_pdata = {
+	.pmic_backlight = NULL,/*mipi_NT35510_set_bl,*/
+};
+
+static struct platform_device mipi_dsi_NT35510_panel_device = {
+	.name = "mipi_NT35510",
+	.id   = 0,
+	.dev  = {
+		.platform_data = &mipi_NT35510_pdata,
+	}
+};
+
+static struct platform_device *msm_fb_devices[] __initdata = {
+	&msm_fb_device,
+	&lcdc_toshiba_panel_device,
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+	&mipi_dsi_renesas_panel_device,
+#endif
+};
+
+static struct platform_device *qrd_fb_devices[] __initdata = {
+	&msm_fb_device,
+	&mipi_dsi_truly_panel_device,
+};
+
+static struct platform_device *evb_fb_devices[] __initdata = {
+	&msm_fb_device,
+	&mipi_dsi_NT35510_panel_device,
+};
+
+void __init msm_msm7627a_allocate_memory_regions(void)
+{
+	void *addr;
+	unsigned long fb_size;
+
+	if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa())
+		fb_size = MSM7x25A_MSM_FB_SIZE;
+	else
+		fb_size = MSM_FB_SIZE;
+	addr = alloc_bootmem_align(fb_size, 0x1000);
+	msm_fb_resources[0].start = __pa(addr);
+	msm_fb_resources[0].end = msm_fb_resources[0].start + fb_size - 1;
+	pr_info("allocating %lu bytes at %p (%lx physical) for fb\n", fb_size,
+						addr, __pa(addr));
+}
+
+static struct msm_panel_common_pdata mdp_pdata = {
+	.gpio = 97,
+	.mdp_rev = MDP_REV_303,
+};
+
+#define GPIO_LCDC_BRDG_PD	128
+#define GPIO_LCDC_BRDG_RESET_N	129
+#define GPIO_LCD_DSI_SEL	125
+#define LCDC_RESET_PHYS		0x90008014
+
+static  void __iomem *lcdc_reset_ptr;
+
+static unsigned mipi_dsi_gpio[] = {
+		GPIO_CFG(GPIO_LCDC_BRDG_RESET_N, 0, GPIO_CFG_OUTPUT,
+		GPIO_CFG_NO_PULL, GPIO_CFG_2MA), /* LCDC_BRDG_RESET_N */
+		GPIO_CFG(GPIO_LCDC_BRDG_PD, 0, GPIO_CFG_OUTPUT,
+		GPIO_CFG_NO_PULL, GPIO_CFG_2MA), /* LCDC_BRDG_PD */
+};
+
+static unsigned lcd_dsi_sel_gpio[] = {
+	GPIO_CFG(GPIO_LCD_DSI_SEL, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
+			GPIO_CFG_2MA),
+};
+
+enum {
+	DSI_SINGLE_LANE = 1,
+	DSI_TWO_LANES,
+};
+
+static int msm_fb_get_lane_config(void)
+{
+	/* For MSM7627A SURF/FFA and QRD */
+	int rc = DSI_TWO_LANES;
+	if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
+		rc = DSI_SINGLE_LANE;
+		pr_info("DSI_SINGLE_LANES\n");
+	} else {
+		pr_info("DSI_TWO_LANES\n");
+	}
+	return rc;
+}
+
+static int msm_fb_dsi_client_msm_reset(void)
+{
+	int rc = 0;
+
+	rc = gpio_request(GPIO_LCDC_BRDG_RESET_N, "lcdc_brdg_reset_n");
+	if (rc < 0) {
+		pr_err("failed to request lcd brdg reset_n\n");
+		return rc;
+	}
+
+	rc = gpio_request(GPIO_LCDC_BRDG_PD, "lcdc_brdg_pd");
+	if (rc < 0) {
+		pr_err("failed to request lcd brdg pd\n");
+		return rc;
+	}
+
+	rc = gpio_tlmm_config(mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
+	if (rc) {
+		pr_err("Failed to enable LCDC Bridge reset enable\n");
+		goto gpio_error;
+	}
+
+	rc = gpio_tlmm_config(mipi_dsi_gpio[1], GPIO_CFG_ENABLE);
+	if (rc) {
+		pr_err("Failed to enable LCDC Bridge pd enable\n");
+		goto gpio_error2;
+	}
+
+	rc = gpio_direction_output(GPIO_LCDC_BRDG_RESET_N, 1);
+	rc |= gpio_direction_output(GPIO_LCDC_BRDG_PD, 1);
+	gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 0);
+
+	if (!rc) {
+		if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()) {
+			lcdc_reset_ptr = ioremap_nocache(LCDC_RESET_PHYS,
+				sizeof(uint32_t));
+
+			if (!lcdc_reset_ptr)
+				return 0;
+		}
+		return rc;
+	} else {
+		goto gpio_error;
+	}
+
+gpio_error2:
+	pr_err("Failed GPIO bridge pd\n");
+	gpio_free(GPIO_LCDC_BRDG_PD);
+
+gpio_error:
+	pr_err("Failed GPIO bridge reset\n");
+	gpio_free(GPIO_LCDC_BRDG_RESET_N);
+	return rc;
+}
+
+static int mipi_truly_sel_mode(int video_mode)
+{
+	int rc = 0;
+
+	rc = gpio_request(GPIO_LCD_DSI_SEL, "lcd_dsi_sel");
+	if (rc < 0)
+		goto gpio_error;
+
+	rc = gpio_tlmm_config(lcd_dsi_sel_gpio[0], GPIO_CFG_ENABLE);
+	if (rc)
+		goto gpio_error;
+
+	rc = gpio_direction_output(GPIO_LCD_DSI_SEL, 1);
+	if (!rc) {
+		gpio_set_value_cansleep(GPIO_LCD_DSI_SEL, video_mode);
+		return rc;
+	} else {
+		goto gpio_error;
+	}
+
+gpio_error:
+	pr_err("mipi_truly_sel_mode failed\n");
+	gpio_free(GPIO_LCD_DSI_SEL);
+	return rc;
+}
+
+static int msm_fb_dsi_client_qrd1_reset(void)
+{
+	int rc = 0;
+
+	rc = gpio_request(GPIO_LCDC_BRDG_RESET_N, "lcdc_brdg_reset_n");
+	if (rc < 0) {
+		pr_err("failed to request lcd brdg reset_n\n");
+		return rc;
+	}
+
+	rc = gpio_tlmm_config(mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
+	if (rc < 0) {
+		pr_err("Failed to enable LCDC Bridge reset enable\n");
+		return rc;
+	}
+
+	rc = gpio_direction_output(GPIO_LCDC_BRDG_RESET_N, 1);
+	if (rc < 0) {
+		pr_err("Failed GPIO bridge pd\n");
+		gpio_free(GPIO_LCDC_BRDG_RESET_N);
+		return rc;
+	}
+
+	mipi_truly_sel_mode(1);
+
+	return rc;
+}
+
+#define GPIO_QRD3_LCD_BRDG_RESET_N	85
+#define GPIO_QRD3_LCD_BACKLIGHT_EN	96
+#define GPIO_QRD3_LCD_EXT_2V85_EN	35
+#define GPIO_QRD3_LCD_EXT_1V8_EN	40
+
+static unsigned qrd3_mipi_dsi_gpio[] = {
+	GPIO_CFG(GPIO_QRD3_LCD_BRDG_RESET_N, 0, GPIO_CFG_OUTPUT,
+			GPIO_CFG_NO_PULL,
+			GPIO_CFG_2MA), /* GPIO_QRD3_LCD_BRDG_RESET_N */
+	GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0, GPIO_CFG_OUTPUT,
+			GPIO_CFG_NO_PULL,
+			GPIO_CFG_2MA), /* GPIO_QRD3_LCD_BACKLIGHT_EN */
+	GPIO_CFG(GPIO_QRD3_LCD_EXT_2V85_EN, 0, GPIO_CFG_OUTPUT,
+			GPIO_CFG_NO_PULL,
+			GPIO_CFG_2MA), /* GPIO_QRD3_LCD_EXT_2V85_EN */
+	GPIO_CFG(GPIO_QRD3_LCD_EXT_1V8_EN, 0, GPIO_CFG_OUTPUT,
+			GPIO_CFG_NO_PULL,
+			GPIO_CFG_2MA), /* GPIO_QRD3_LCD_EXT_1V8_EN */
+};
+
+static int msm_fb_dsi_client_qrd3_reset(void)
+{
+	int rc = 0;
+
+	rc = gpio_request(GPIO_QRD3_LCD_BRDG_RESET_N, "qrd3_lcd_brdg_reset_n");
+	if (rc < 0) {
+		pr_err("failed to request qrd3 lcd brdg reset_n\n");
+		return rc;
+	}
+
+	rc = gpio_tlmm_config(qrd3_mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
+	if (rc < 0) {
+		pr_err("Failed to enable LCD Bridge reset enable\n");
+		return rc;
+	}
+
+	rc = gpio_direction_output(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
+	if (rc < 0) {
+		pr_err("Failed GPIO bridge Reset\n");
+		gpio_free(GPIO_QRD3_LCD_BRDG_RESET_N);
+		return rc;
+	}
+
+	return rc;
+}
+
+static int msm_fb_dsi_client_reset(void)
+{
+	int rc = 0;
+
+	if (machine_is_msm7627a_qrd1())
+		rc = msm_fb_dsi_client_qrd1_reset();
+	else if (machine_is_msm7627a_evb())
+		rc = msm_fb_dsi_client_qrd3_reset();
+	else
+		rc = msm_fb_dsi_client_msm_reset();
+
+	return rc;
+
+}
+
+static struct regulator_bulk_data regs_dsi[] = {
+	{ .supply = "gp2",   .min_uV = 2850000, .max_uV = 2850000 },
+	{ .supply = "msme1", .min_uV = 1800000, .max_uV = 1800000 },
+};
+
+static int dsi_gpio_initialized;
+
+static int mipi_dsi_panel_msm_power(int on)
+{
+	int rc = 0;
+	uint32_t lcdc_reset_cfg;
+
+	/* I2C-controlled GPIO Expander -init of the GPIOs very late */
+	if (unlikely(!dsi_gpio_initialized)) {
+		pmapp_disp_backlight_init();
+
+		rc = gpio_request(GPIO_DISPLAY_PWR_EN, "gpio_disp_pwr");
+		if (rc < 0) {
+			pr_err("failed to request gpio_disp_pwr\n");
+			return rc;
+		}
+
+		if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()) {
+			rc = gpio_direction_output(GPIO_DISPLAY_PWR_EN, 1);
+			if (rc < 0) {
+				pr_err("failed to enable display pwr\n");
+				goto fail_gpio1;
+			}
+
+			rc = gpio_request(GPIO_BACKLIGHT_EN, "gpio_bkl_en");
+			if (rc < 0) {
+				pr_err("failed to request gpio_bkl_en\n");
+				goto fail_gpio1;
+			}
+
+			rc = gpio_direction_output(GPIO_BACKLIGHT_EN, 1);
+			if (rc < 0) {
+				pr_err("failed to enable backlight\n");
+				goto fail_gpio2;
+			}
+		}
+
+		rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_dsi), regs_dsi);
+		if (rc) {
+			pr_err("%s: could not get regulators: %d\n",
+					__func__, rc);
+			goto fail_gpio2;
+		}
+
+		rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_dsi),
+						regs_dsi);
+		if (rc) {
+			pr_err("%s: could not set voltages: %d\n",
+					__func__, rc);
+			goto fail_vreg;
+		}
+		if (pmapp_disp_backlight_set_brightness(100))
+			pr_err("backlight set brightness failed\n");
+
+		dsi_gpio_initialized = 1;
+	}
+	if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()) {
+		gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, on);
+		gpio_set_value_cansleep(GPIO_BACKLIGHT_EN, on);
+	} else if (machine_is_msm7x27a_ffa() ||
+			 machine_is_msm7625a_ffa()) {
+		if (on) {
+			/* This line drives an active low pin on FFA */
+			rc = gpio_direction_output(GPIO_DISPLAY_PWR_EN, !on);
+			if (rc < 0)
+				pr_err("failed to set direction for "
+					"display pwr\n");
+		} else {
+			gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, !on);
+			rc = gpio_direction_input(GPIO_DISPLAY_PWR_EN);
+			if (rc < 0)
+				pr_err("failed to set direction for "
+					"display pwr\n");
+		}
+	}
+
+	if (on) {
+		gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 0);
+
+		if (machine_is_msm7x27a_surf() ||
+				 machine_is_msm7625a_surf()) {
+			lcdc_reset_cfg = readl_relaxed(lcdc_reset_ptr);
+			rmb();
+			lcdc_reset_cfg &= ~1;
+
+			writel_relaxed(lcdc_reset_cfg, lcdc_reset_ptr);
+			msleep(20);
+			wmb();
+			lcdc_reset_cfg |= 1;
+			writel_relaxed(lcdc_reset_cfg, lcdc_reset_ptr);
+		} else {
+			gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 0);
+			msleep(20);
+			gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
+		}
+	} else {
+		gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 1);
+	}
+
+	rc = on ? regulator_bulk_enable(ARRAY_SIZE(regs_dsi), regs_dsi) :
+		  regulator_bulk_disable(ARRAY_SIZE(regs_dsi), regs_dsi);
+
+	if (rc)
+		pr_err("%s: could not %sable regulators: %d\n",
+				__func__, on ? "en" : "dis", rc);
+
+	return rc;
+fail_vreg:
+	regulator_bulk_free(ARRAY_SIZE(regs_dsi), regs_dsi);
+fail_gpio2:
+	gpio_free(GPIO_BACKLIGHT_EN);
+fail_gpio1:
+	gpio_free(GPIO_DISPLAY_PWR_EN);
+	dsi_gpio_initialized = 0;
+	return rc;
+}
+
+static int mipi_dsi_panel_qrd1_power(int on)
+{
+	int rc = 0;
+
+	if (!dsi_gpio_initialized) {
+		rc = gpio_request(QRD_GPIO_BACKLIGHT_EN, "gpio_bkl_en");
+		if (rc < 0)
+			return rc;
+
+		rc = gpio_tlmm_config(GPIO_CFG(QRD_GPIO_BACKLIGHT_EN, 0,
+			GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+			GPIO_CFG_ENABLE);
+		if (rc < 0) {
+			pr_err("failed GPIO_BACKLIGHT_EN tlmm config\n");
+			return rc;
+		}
+
+		rc = gpio_direction_output(QRD_GPIO_BACKLIGHT_EN, 1);
+		if (rc < 0) {
+			pr_err("failed to enable backlight\n");
+			gpio_free(QRD_GPIO_BACKLIGHT_EN);
+			return rc;
+		}
+		dsi_gpio_initialized = 1;
+	}
+
+	gpio_set_value_cansleep(QRD_GPIO_BACKLIGHT_EN, !!on);
+
+	if (on) {
+		gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
+		msleep(20);
+		gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 0);
+		msleep(20);
+		gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
+
+	}
+
+	return rc;
+}
+
+static int qrd3_dsi_gpio_initialized;
+
+static int mipi_dsi_panel_qrd3_power(int on)
+{
+	int rc = 0;
+
+	if (!qrd3_dsi_gpio_initialized) {
+		rc = gpio_request(GPIO_QRD3_LCD_BACKLIGHT_EN,
+			"qrd3_gpio_bkl_en");
+		if (rc < 0)
+			return rc;
+
+		rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0,
+			GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+			GPIO_CFG_ENABLE);
+		if (rc < 0) {
+			pr_err("failed QRD3 GPIO_BACKLIGHT_EN tlmm config\n");
+			return rc;
+		}
+		rc = gpio_direction_output(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
+		if (rc < 0) {
+			pr_err("failed to enable backlight\n");
+			gpio_free(GPIO_QRD3_LCD_BACKLIGHT_EN);
+			return rc;
+		}
+
+		rc = gpio_request(GPIO_QRD3_LCD_EXT_2V85_EN,
+			"qrd3_gpio_ext_2v85_en");
+		if (rc < 0)
+			return rc;
+
+		rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_EXT_2V85_EN, 0,
+			GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+			GPIO_CFG_ENABLE);
+		if (rc < 0) {
+			pr_err("failed QRD3 GPIO_QRD3_LCD_EXT_2V85_EN tlmm config\n");
+			return rc;
+		}
+
+		rc = gpio_direction_output(GPIO_QRD3_LCD_EXT_2V85_EN, 1);
+		if (rc < 0) {
+			pr_err("failed to enable external 2V85\n");
+			gpio_free(GPIO_QRD3_LCD_EXT_2V85_EN);
+			return rc;
+		}
+
+		rc = gpio_request(GPIO_QRD3_LCD_EXT_1V8_EN,
+			"qrd3_gpio_ext_1v8_en");
+		if (rc < 0)
+			return rc;
+
+		rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_EXT_1V8_EN, 0,
+			GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+			GPIO_CFG_ENABLE);
+		if (rc < 0) {
+			pr_err("failed QRD3 GPIO_QRD3_LCD_EXT_1V8_EN tlmm config\n");
+			return rc;
+		}
+
+		rc = gpio_direction_output(GPIO_QRD3_LCD_EXT_1V8_EN, 1);
+		if (rc < 0) {
+			pr_err("failed to enable external 1v8\n");
+			gpio_free(GPIO_QRD3_LCD_EXT_1V8_EN);
+			return rc;
+		}
+
+			qrd3_dsi_gpio_initialized = 1;
+	}
+
+	gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, !!on);
+	gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_2V85_EN, !!on);
+	gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_1V8_EN, !!on);
+
+	if (on) {
+		gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
+		msleep(20);
+		gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 0);
+		msleep(20);
+		gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
+		msleep(20);
+	}
+
+		return rc;
+}
+
+static int mipi_dsi_panel_power(int on)
+{
+	int rc = 0;
+
+	if (machine_is_msm7627a_qrd1())
+		rc = mipi_dsi_panel_qrd1_power(on);
+	else if (machine_is_msm7627a_evb())
+		rc = mipi_dsi_panel_qrd3_power(on);
+	else
+		rc = mipi_dsi_panel_msm_power(on);
+	return rc;
+}
+
+#define MDP_303_VSYNC_GPIO 97
+
+#ifdef CONFIG_FB_MSM_MDP303
+static struct mipi_dsi_platform_data mipi_dsi_pdata = {
+	.vsync_gpio		= MDP_303_VSYNC_GPIO,
+	.dsi_power_save		= mipi_dsi_panel_power,
+	.dsi_client_reset       = msm_fb_dsi_client_reset,
+	.get_lane_config	= msm_fb_get_lane_config,
+};
+#endif
+
+void __init msm_fb_add_devices(void)
+{
+	if (machine_is_msm7627a_qrd1())
+		platform_add_devices(qrd_fb_devices,
+				ARRAY_SIZE(qrd_fb_devices));
+	else if (machine_is_msm7627a_evb())
+		platform_add_devices(evb_fb_devices,
+				ARRAY_SIZE(evb_fb_devices));
+	else
+		platform_add_devices(msm_fb_devices,
+				ARRAY_SIZE(msm_fb_devices));
+
+	msm_fb_register_device("mdp", &mdp_pdata);
+	if (machine_is_msm7625a_surf() || machine_is_msm7x27a_surf())
+		msm_fb_register_device("lcdc", &lcdc_pdata);
+#ifdef CONFIG_FB_MSM_MDP303
+	msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
+#endif
+}
diff --git a/arch/arm/mach-msm/board-msm7627a-storage.c b/arch/arm/mach-msm/board-msm7627a-storage.c
index c3657b5..93a6178 100644
--- a/arch/arm/mach-msm/board-msm7627a-storage.c
+++ b/arch/arm/mach-msm/board-msm7627a-storage.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
@@ -148,7 +148,7 @@
 static int gpio_sdc1_hw_det = 85;
 static void gpio_sdc1_config(void)
 {
-	if (machine_is_msm7627a_qrd1())
+	if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb())
 		gpio_sdc1_hw_det = 42;
 }
 
@@ -248,7 +248,8 @@
 	} else {
 		status = gpio_direction_input(gpio_sdc1_hw_det);
 		if (!status) {
-			if (machine_is_msm7627a_qrd1())
+			if (machine_is_msm7627a_qrd1() ||
+					machine_is_msm7627a_evb())
 				status = !gpio_get_value(gpio_sdc1_hw_det);
 			else
 				status = gpio_get_value(gpio_sdc1_hw_det);
diff --git a/arch/arm/mach-msm/board-msm7627a-wlan.c b/arch/arm/mach-msm/board-msm7627a-wlan.c
new file mode 100644
index 0000000..6df7626
--- /dev/null
+++ b/arch/arm/mach-msm/board-msm7627a-wlan.c
@@ -0,0 +1,368 @@
+/* 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 <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <asm/mach-types.h>
+#include <mach/rpc_pmapp.h>
+#include "board-msm7627a.h"
+#include "devices-msm7x2xa.h"
+#include "timer.h"
+
+#define GPIO_WLAN_3V3_EN 119
+static const char *id = "WLAN";
+
+enum {
+	WLAN_VREG_S3 = 0,
+	WLAN_VREG_L17,
+	WLAN_VREG_L19
+};
+
+struct wlan_vreg_info {
+	const char *vreg_id;
+	unsigned int level_min;
+	unsigned int level_max;
+	unsigned int pmapp_id;
+	unsigned int is_vreg_pin_controlled;
+	struct regulator *reg;
+};
+
+static struct wlan_vreg_info vreg_info[] = {
+	{"msme1",     1800000, 1800000, 2,  0, NULL},
+	{"bt",        3300000, 3300000, 21, 1, NULL},
+	{"wlan4",     1800000, 1800000, 23, 1, NULL}
+};
+
+int gpio_wlan_sys_rest_en = 134;
+static void gpio_wlan_config(void)
+{
+	if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb())
+		gpio_wlan_sys_rest_en = 124;
+}
+
+static unsigned int qrf6285_init_regs(void)
+{
+	struct regulator_bulk_data regs[ARRAY_SIZE(vreg_info)];
+	int i = 0, rc = 0;
+
+	for (i = 0; i < ARRAY_SIZE(regs); i++) {
+		regs[i].supply = vreg_info[i].vreg_id;
+		regs[i].min_uV = vreg_info[i].level_min;
+		regs[i].max_uV = vreg_info[i].level_max;
+	}
+
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs), regs);
+	if (rc) {
+		pr_err("%s: could not get regulators: %d\n", __func__, rc);
+		goto out;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(regs); i++)
+		vreg_info[i].reg = regs[i].consumer;
+
+out:
+	return rc;
+}
+
+static unsigned int setup_wlan_gpio(bool on)
+{
+	int rc = 0;
+
+	if (on) {
+		rc = gpio_direction_output(gpio_wlan_sys_rest_en, 1);
+		msleep(100);
+	} else {
+		gpio_set_value_cansleep(gpio_wlan_sys_rest_en, 0);
+		rc = gpio_direction_input(gpio_wlan_sys_rest_en);
+		msleep(100);
+	}
+
+	if (rc)
+		pr_err("%s: WLAN sys_reset_en GPIO: Error", __func__);
+
+	return rc;
+}
+
+static unsigned int setup_wlan_clock(bool on)
+{
+	int rc = 0;
+
+	if (on) {
+		/* Vote for A0 clock */
+		rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_A0,
+					PMAPP_CLOCK_VOTE_ON);
+	} else {
+		/* Vote against A0 clock */
+		rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_A0,
+					 PMAPP_CLOCK_VOTE_OFF);
+	}
+
+	if (rc)
+		pr_err("%s: Configuring A0 clock for WLAN: Error", __func__);
+
+	return rc;
+}
+
+static unsigned int wlan_switch_regulators(int on)
+{
+	int rc = 0, index = 0;
+
+	if (machine_is_msm7627a_qrd1())
+		index = 2;
+
+	for ( ; index < ARRAY_SIZE(vreg_info); index++) {
+		if (on) {
+			rc = regulator_set_voltage(vreg_info[index].reg,
+						vreg_info[index].level_min,
+						vreg_info[index].level_max);
+			if (rc) {
+				pr_err("%s:%s set voltage failed %d\n",
+					__func__, vreg_info[index].vreg_id, rc);
+				goto reg_disable;
+			}
+
+			rc = regulator_enable(vreg_info[index].reg);
+			if (rc) {
+				pr_err("%s:%s vreg enable failed %d\n",
+					__func__, vreg_info[index].vreg_id, rc);
+				goto reg_disable;
+			}
+
+			if (vreg_info[index].is_vreg_pin_controlled) {
+				rc = pmapp_vreg_lpm_pincntrl_vote(id,
+						vreg_info[index].pmapp_id,
+						PMAPP_CLOCK_ID_A0, 1);
+				if (rc) {
+					pr_err("%s:%s pincntrl failed %d\n",
+						__func__,
+						vreg_info[index].vreg_id, rc);
+					goto pin_cnt_fail;
+				}
+			}
+		} else {
+			if (vreg_info[index].is_vreg_pin_controlled) {
+				rc = pmapp_vreg_lpm_pincntrl_vote(id,
+						vreg_info[index].pmapp_id,
+						PMAPP_CLOCK_ID_A0, 0);
+				if (rc) {
+					pr_err("%s:%s pincntrl failed %d\n",
+						__func__,
+						vreg_info[index].vreg_id, rc);
+					goto pin_cnt_fail;
+				}
+			}
+
+			rc = regulator_disable(vreg_info[index].reg);
+			if (rc) {
+				pr_err("%s:%s vreg disable failed %d\n",
+					__func__,
+					vreg_info[index].vreg_id, rc);
+				goto reg_disable;
+			}
+		}
+	}
+	return 0;
+pin_cnt_fail:
+	if (on)
+		regulator_disable(vreg_info[index].reg);
+reg_disable:
+	if (!machine_is_msm7627a_qrd1()) {
+		while (index) {
+			if (on) {
+				index--;
+				regulator_disable(vreg_info[index].reg);
+				regulator_put(vreg_info[index].reg);
+			}
+		}
+	}
+	return rc;
+}
+
+static unsigned int msm_AR600X_setup_power(bool on)
+{
+	int rc = 0;
+	static bool init_done;
+
+	if (unlikely(!init_done)) {
+		gpio_wlan_config();
+		rc = qrf6285_init_regs();
+		if (rc) {
+			pr_err("%s: qrf6285 init failed = %d\n", __func__, rc);
+			return rc;
+		} else {
+			init_done = true;
+		}
+	}
+
+	rc = wlan_switch_regulators(on);
+	if (rc) {
+		pr_err("%s: wlan_switch_regulators error = %d\n", __func__, rc);
+		goto out;
+	}
+
+	/* GPIO_WLAN_3V3_EN is only required for the QRD7627a */
+	if (machine_is_msm7627a_qrd1()) {
+		rc = gpio_tlmm_config(GPIO_CFG(GPIO_WLAN_3V3_EN, 0,
+					GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
+					GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+		if (rc) {
+			pr_err("%s gpio_tlmm_config 119 failed,error = %d\n",
+				__func__, rc);
+			goto reg_disable;
+		}
+		gpio_set_value(GPIO_WLAN_3V3_EN, 1);
+	}
+
+	/*
+	 * gpio_wlan_sys_rest_en is not from the GPIO expander for QRD7627a,
+	 * EVB1.0 and QRD8625,so the below step is required for those devices.
+	 */
+	if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()) {
+		rc = gpio_tlmm_config(GPIO_CFG(gpio_wlan_sys_rest_en, 0,
+					GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
+					GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+		if (rc) {
+			pr_err("%s gpio_tlmm_config 119 failed,error = %d\n",
+				__func__, rc);
+			goto qrd_gpio_fail;
+		}
+		gpio_set_value(gpio_wlan_sys_rest_en, 1);
+	} else {
+		rc = gpio_request(gpio_wlan_sys_rest_en, "WLAN_DEEP_SLEEP_N");
+		if (rc) {
+			pr_err("%s: WLAN sys_rest_en GPIO %d request failed %d\n",
+				__func__,
+				gpio_wlan_sys_rest_en, rc);
+			goto qrd_gpio_fail;
+		}
+		rc = setup_wlan_gpio(on);
+		if (rc) {
+			pr_err("%s: wlan_set_gpio = %d\n", __func__, rc);
+			goto gpio_fail;
+		}
+	}
+
+	/* Enable the A0 clock */
+	rc = setup_wlan_clock(on);
+	if (rc) {
+		pr_err("%s: setup_wlan_clock = %d\n", __func__, rc);
+		goto set_gpio_fail;
+	}
+
+	/* Configure A0 clock to be slave to WLAN_CLK_PWR_REQ */
+	rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_A0,
+				 PMAPP_CLOCK_VOTE_PIN_CTRL);
+	if (rc) {
+		pr_err("%s: Configuring A0 to Pin controllable failed %d\n",
+				__func__, rc);
+		goto set_clock_fail;
+	}
+
+	pr_info("WLAN power-up success\n");
+	return 0;
+set_clock_fail:
+	setup_wlan_clock(0);
+set_gpio_fail:
+	setup_wlan_gpio(0);
+gpio_fail:
+	gpio_free(gpio_wlan_sys_rest_en);
+qrd_gpio_fail:
+	gpio_free(GPIO_WLAN_3V3_EN);
+reg_disable:
+	wlan_switch_regulators(0);
+out:
+	pr_info("WLAN power-up failed\n");
+	return rc;
+}
+
+static unsigned int msm_AR600X_shutdown_power(bool on)
+{
+	int rc = 0;
+
+	/* Disable the A0 clock */
+	rc = setup_wlan_clock(on);
+	if (rc) {
+		pr_err("%s: setup_wlan_clock = %d\n", __func__, rc);
+		goto set_clock_fail;
+	}
+
+	/*
+	 * gpio_wlan_sys_rest_en is not from the GPIO expander for QRD7627a,
+	 * EVB1.0 and QRD8625,so the below step is required for those devices.
+	 */
+	if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()) {
+		rc = gpio_tlmm_config(GPIO_CFG(gpio_wlan_sys_rest_en, 0,
+					GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
+					GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+		if (rc) {
+			pr_err("%s gpio_tlmm_config 119 failed,error = %d\n",
+				__func__, rc);
+			goto gpio_fail;
+		}
+		gpio_set_value(gpio_wlan_sys_rest_en, 0);
+	} else {
+		rc = setup_wlan_gpio(on);
+		if (rc) {
+			pr_err("%s: wlan_set_gpio = %d\n", __func__, rc);
+			goto set_gpio_fail;
+		}
+		gpio_free(gpio_wlan_sys_rest_en);
+	}
+
+	/* GPIO_WLAN_3V3_EN is only required for the QRD7627a */
+	if (machine_is_msm7627a_qrd1()) {
+		rc = gpio_tlmm_config(GPIO_CFG(GPIO_WLAN_3V3_EN, 0,
+					GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
+					GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+		if (rc) {
+			pr_err("%s gpio_tlmm_config 119 failed,error = %d\n",
+				__func__, rc);
+			goto qrd_gpio_fail;
+		}
+		gpio_set_value(GPIO_WLAN_3V3_EN, 0);
+	}
+
+	rc = wlan_switch_regulators(on);
+	if (rc) {
+		pr_err("%s: wlan_switch_regulators error = %d\n",
+			__func__, rc);
+		goto reg_disable;
+	}
+
+	pr_info("WLAN power-down success\n");
+	return 0;
+set_clock_fail:
+	setup_wlan_clock(0);
+set_gpio_fail:
+	setup_wlan_gpio(0);
+gpio_fail:
+	gpio_free(gpio_wlan_sys_rest_en);
+qrd_gpio_fail:
+	gpio_free(GPIO_WLAN_3V3_EN);
+reg_disable:
+	wlan_switch_regulators(0);
+	pr_info("WLAN power-down failed\n");
+	return rc;
+}
+
+int  ar600x_wlan_power(bool on)
+{
+	if (on)
+		msm_AR600X_setup_power(on);
+	else
+		msm_AR600X_shutdown_power(on);
+
+	return 0;
+}
diff --git a/arch/arm/mach-msm/board-msm7627a.h b/arch/arm/mach-msm/board-msm7627a.h
index 7d7da4f..b0481a0 100644
--- a/arch/arm/mach-msm/board-msm7627a.h
+++ b/arch/arm/mach-msm/board-msm7627a.h
@@ -15,6 +15,9 @@
 
 void __init msm7627a_init_mmc(void);
 
+void __init msm_msm7627a_allocate_memory_regions(void);
+void __init msm_fb_add_devices(void);
+
 enum {
 	GPIO_EXPANDER_IRQ_BASE  = NR_MSM_IRQS + NR_GPIO_IRQS,
 	GPIO_EXPANDER_GPIO_BASE = NR_MSM_GPIOS,
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index 9385a58..8eb92a4 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -68,7 +68,7 @@
 #include "clock.h"
 #include "acpuclock.h"
 #include "msm-keypad-devices.h"
-#include <mach/pm.h>
+#include "pm.h"
 #include "pm-boot.h"
 
 #ifdef CONFIG_ARCH_MSM7X25
@@ -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-regulator.c b/arch/arm/mach-msm/board-msm7x27a-regulator.c
index 56ead81..5be382f 100644
--- a/arch/arm/mach-msm/board-msm7x27a-regulator.c
+++ b/arch/arm/mach-msm/board-msm7x27a-regulator.c
@@ -84,6 +84,7 @@
 PCOM_VREG_CONSUMERS(smps3) = {
 	REGULATOR_SUPPLY("smps3",	NULL),
 	REGULATOR_SUPPLY("msme1",	NULL),
+	REGULATOR_SUPPLY("vcc_i2c",	"1-004a"),
 };
 
 PCOM_VREG_CONSUMERS(smps4) = {
@@ -158,6 +159,7 @@
 PCOM_VREG_CONSUMERS(ldo12) = {
 	REGULATOR_SUPPLY("ldo12",	NULL),
 	REGULATOR_SUPPLY("gp2",		NULL),
+	REGULATOR_SUPPLY("vdd_ana",	"1-004a"),
 };
 
 PCOM_VREG_CONSUMERS(ldo13) = {
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 5bcd749..0680c44 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -12,8 +12,10 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/gpio_event.h>
+#include <linux/memblock.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include <asm/hardware/gic.h>
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 #include <mach/msm_hsusb.h>
@@ -49,7 +51,7 @@
 #include "timer.h"
 #include "board-msm7x27a-regulator.h"
 #include "devices-msm7x2xa.h"
-#include <mach/pm.h>
+#include "pm.h"
 #include <mach/rpc_server_handset.h>
 #include <mach/socinfo.h>
 #include "pm-boot.h"
@@ -150,6 +152,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
@@ -157,16 +163,6 @@
 #define MSM_PMEM_ADSP_SIZE      0x1100000
 #define MSM7x25A_MSM_PMEM_ADSP_SIZE      0xB91000
 
-
-#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_SIZE		0x260000
-#define MSM7x25A_MSM_FB_SIZE	0xE1000
-#else
-#define MSM_FB_SIZE		0x195000
-#define MSM7x25A_MSM_FB_SIZE	0x96000
-
-#endif
-
 #endif
 
 static struct android_usb_platform_data android_usb_pdata = {
@@ -400,253 +396,6 @@
 
 early_param("pmem_adsp_size", pmem_adsp_size_setup);
 
-static unsigned fb_size = MSM_FB_SIZE;
-static int __init fb_size_setup(char *p)
-{
-	fb_size = memparse(p, NULL);
-	return 0;
-}
-
-early_param("fb_size", fb_size_setup);
-
-static struct regulator_bulk_data regs_lcdc[] = {
-	{ .supply = "gp2",   .min_uV = 2850000, .max_uV = 2850000 },
-	{ .supply = "msme1", .min_uV = 1800000, .max_uV = 1800000 },
-};
-
-static uint32_t lcdc_gpio_initialized;
-
-static void lcdc_toshiba_gpio_init(void)
-{
-	int rc = 0;
-	if (!lcdc_gpio_initialized) {
-		if (gpio_request(GPIO_SPI_CLK, "spi_clk")) {
-			pr_err("failed to request gpio spi_clk\n");
-			return;
-		}
-		if (gpio_request(GPIO_SPI_CS0_N, "spi_cs")) {
-			pr_err("failed to request gpio spi_cs0_N\n");
-			goto fail_gpio6;
-		}
-		if (gpio_request(GPIO_SPI_MOSI, "spi_mosi")) {
-			pr_err("failed to request gpio spi_mosi\n");
-			goto fail_gpio5;
-		}
-		if (gpio_request(GPIO_SPI_MISO, "spi_miso")) {
-			pr_err("failed to request gpio spi_miso\n");
-			goto fail_gpio4;
-		}
-		if (gpio_request(GPIO_DISPLAY_PWR_EN, "gpio_disp_pwr")) {
-			pr_err("failed to request gpio_disp_pwr\n");
-			goto fail_gpio3;
-		}
-		if (gpio_request(GPIO_BACKLIGHT_EN, "gpio_bkl_en")) {
-			pr_err("failed to request gpio_bkl_en\n");
-			goto fail_gpio2;
-		}
-		pmapp_disp_backlight_init();
-
-		rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_lcdc), regs_lcdc);
-		if (rc) {
-			pr_err("%s: could not get regulators: %d\n",
-					__func__, rc);
-			goto fail_gpio1;
-		}
-
-		rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_lcdc),
-				regs_lcdc);
-		if (rc) {
-			pr_err("%s: could not set voltages: %d\n",
-					__func__, rc);
-			goto fail_vreg;
-		}
-		lcdc_gpio_initialized = 1;
-	}
-	return;
-fail_vreg:
-	regulator_bulk_free(ARRAY_SIZE(regs_lcdc), regs_lcdc);
-fail_gpio1:
-	gpio_free(GPIO_BACKLIGHT_EN);
-fail_gpio2:
-	gpio_free(GPIO_DISPLAY_PWR_EN);
-fail_gpio3:
-	gpio_free(GPIO_SPI_MISO);
-fail_gpio4:
-	gpio_free(GPIO_SPI_MOSI);
-fail_gpio5:
-	gpio_free(GPIO_SPI_CS0_N);
-fail_gpio6:
-	gpio_free(GPIO_SPI_CLK);
-	lcdc_gpio_initialized = 0;
-}
-
-static uint32_t lcdc_gpio_table[] = {
-	GPIO_SPI_CLK,
-	GPIO_SPI_CS0_N,
-	GPIO_SPI_MOSI,
-	GPIO_DISPLAY_PWR_EN,
-	GPIO_BACKLIGHT_EN,
-	GPIO_SPI_MISO,
-};
-
-static void config_lcdc_gpio_table(uint32_t *table, int len, unsigned enable)
-{
-	int n;
-
-	if (lcdc_gpio_initialized) {
-		/* All are IO Expander GPIOs */
-		for (n = 0; n < (len - 1); n++)
-			gpio_direction_output(table[n], 1);
-	}
-}
-
-static void lcdc_toshiba_config_gpios(int enable)
-{
-	config_lcdc_gpio_table(lcdc_gpio_table,
-		ARRAY_SIZE(lcdc_gpio_table), enable);
-}
-
-static int msm_fb_lcdc_power_save(int on)
-{
-	int rc = 0;
-	/* Doing the init of the LCDC GPIOs very late as they are from
-		an I2C-controlled IO Expander */
-	lcdc_toshiba_gpio_init();
-
-	if (lcdc_gpio_initialized) {
-		gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, on);
-		gpio_set_value_cansleep(GPIO_BACKLIGHT_EN, on);
-
-		rc = on ? regulator_bulk_enable(
-				ARRAY_SIZE(regs_lcdc), regs_lcdc) :
-			  regulator_bulk_disable(
-				ARRAY_SIZE(regs_lcdc), regs_lcdc);
-
-		if (rc)
-			pr_err("%s: could not %sable regulators: %d\n",
-					__func__, on ? "en" : "dis", rc);
-	}
-
-	return rc;
-}
-
-
-static int lcdc_toshiba_set_bl(int level)
-{
-	int ret;
-
-	ret = pmapp_disp_backlight_set_brightness(level);
-	if (ret)
-		pr_err("%s: can't set lcd backlight!\n", __func__);
-
-	return ret;
-}
-
-
-static struct lcdc_platform_data lcdc_pdata = {
-	.lcdc_gpio_config = NULL,
-	.lcdc_power_save   = msm_fb_lcdc_power_save,
-};
-
-static int lcd_panel_spi_gpio_num[] = {
-		GPIO_SPI_MOSI,  /* spi_sdi */
-		GPIO_SPI_MISO,  /* spi_sdoi */
-		GPIO_SPI_CLK,   /* spi_clk */
-		GPIO_SPI_CS0_N, /* spi_cs  */
-};
-
-static struct msm_panel_common_pdata lcdc_toshiba_panel_data = {
-	.panel_config_gpio = lcdc_toshiba_config_gpios,
-	.pmic_backlight = lcdc_toshiba_set_bl,
-	.gpio_num	  = lcd_panel_spi_gpio_num,
-};
-
-static struct platform_device lcdc_toshiba_panel_device = {
-	.name   = "lcdc_toshiba_fwvga_pt",
-	.id     = 0,
-	.dev    = {
-		.platform_data = &lcdc_toshiba_panel_data,
-	}
-};
-
-static struct resource msm_fb_resources[] = {
-	{
-		.flags  = IORESOURCE_DMA,
-	}
-};
-
-#define PANEL_NAME_MAX_LEN	30
-#define LCDC_TOSHIBA_FWVGA_PANEL_NAME	"lcdc_toshiba_fwvga_pt"
-#define MIPI_CMD_RENESAS_FWVGA_PANEL_NAME	"mipi_cmd_renesas_fwvga"
-
-static int msm_fb_detect_panel(const char *name)
-{
-	int ret = -ENODEV;
-
-	if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()) {
-		if (!strncmp(name, "lcdc_toshiba_fwvga_pt", 21) ||
-				!strncmp(name, "mipi_cmd_renesas_fwvga", 22))
-			ret = 0;
-	} else if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()) {
-		if (!strncmp(name, "mipi_cmd_renesas_fwvga", 22))
-			ret = 0;
-	}
-
-#if !defined(CONFIG_FB_MSM_LCDC_AUTO_DETECT) && \
-	!defined(CONFIG_FB_MSM_MIPI_PANEL_AUTO_DETECT) && \
-	!defined(CONFIG_FB_MSM_LCDC_MIPI_PANEL_AUTO_DETECT)
-		if (machine_is_msm7x27a_surf() ||
-			machine_is_msm7625a_surf()) {
-			if (!strncmp(name, LCDC_TOSHIBA_FWVGA_PANEL_NAME,
-				strnlen(LCDC_TOSHIBA_FWVGA_PANEL_NAME,
-					PANEL_NAME_MAX_LEN)))
-				return 0;
-		}
-#endif
-	return ret;
-}
-
-static struct msm_fb_platform_data msm_fb_pdata = {
-	.detect_client = msm_fb_detect_panel,
-};
-
-static struct platform_device msm_fb_device = {
-	.name   = "msm_fb",
-	.id     = 0,
-	.num_resources  = ARRAY_SIZE(msm_fb_resources),
-	.resource       = msm_fb_resources,
-	.dev    = {
-		.platform_data = &msm_fb_pdata,
-	}
-};
-
-#ifdef CONFIG_FB_MSM_MIPI_DSI
-static int mipi_renesas_set_bl(int level)
-{
-	int ret;
-
-	ret = pmapp_disp_backlight_set_brightness(level);
-
-	if (ret)
-		pr_err("%s: can't set lcd backlight!\n", __func__);
-
-	return ret;
-}
-
-static struct msm_panel_common_pdata mipi_renesas_pdata = {
-	.pmic_backlight = mipi_renesas_set_bl,
-};
-
-
-static struct platform_device mipi_dsi_renesas_panel_device = {
-	.name = "mipi_renesas",
-	.id = 0,
-	.dev    = {
-		.platform_data = &mipi_renesas_pdata,
-	}
-};
-#endif
-
 #define SND(desc, num) { .name = #desc, .id = num }
 static struct snd_endpoint snd_endpoints_list[] = {
 	SND(HANDSET, 0),
@@ -934,6 +683,12 @@
 	&msm_gsbi1_qup_i2c_device,
 };
 
+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 = {
 	&msm_device_dmov,
 	&msm_device_smd,
@@ -951,13 +706,8 @@
 	&android_pmem_audio_device,
 	&msm_device_snd,
 	&msm_device_adspdec,
-	&msm_fb_device,
-	&lcdc_toshiba_panel_device,
 	&msm_batt_device,
 	&smsc911x_device,
-#ifdef CONFIG_FB_MSM_MIPI_DSI
-	&mipi_dsi_renesas_panel_device,
-#endif
 	&msm_kgsl_3d0,
 #ifdef CONFIG_BT
 	&msm_bt_power_device,
@@ -983,24 +733,6 @@
 }
 early_param("pmem_audio_size", pmem_audio_size_setup);
 
-static void __init msm_msm7x2x_allocate_memory_regions(void)
-{
-	void *addr;
-	unsigned long size;
-
-	if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa())
-		fb_size = MSM7x25A_MSM_FB_SIZE;
-	else
-		fb_size = MSM_FB_SIZE;
-
-	size = fb_size;
-	addr = alloc_bootmem_align(size, 0x1000);
-	msm_fb_resources[0].start = __pa(addr);
-	msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
-	pr_info("allocating %lu bytes at %p (%lx physical) for fb\n",
-		size, addr, __pa(addr));
-}
-
 static struct memtype_reserve msm7x27a_reserve_table[] __initdata = {
 	[MEMTYPE_SMI] = {
 	},
@@ -1068,253 +800,23 @@
 	msm_reserve();
 }
 
+static void __init msm8625_reserve(void)
+{
+	memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
+}
+
 static void __init msm_device_i2c_init(void)
 {
+	if (machine_is_msm8625_rumi3()) {
+		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;
 }
 
-static struct msm_panel_common_pdata mdp_pdata = {
-	.gpio = 97,
-	.mdp_rev = MDP_REV_303,
-};
-
-
-#ifdef CONFIG_FB_MSM
-#define GPIO_LCDC_BRDG_PD	128
-#define GPIO_LCDC_BRDG_RESET_N	129
-
-#define LCDC_RESET_PHYS		0x90008014
-
-static	void __iomem *lcdc_reset_ptr;
-
-static unsigned mipi_dsi_gpio[] = {
-	GPIO_CFG(GPIO_LCDC_BRDG_RESET_N, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
-		GPIO_CFG_2MA),       /* LCDC_BRDG_RESET_N */
-	GPIO_CFG(GPIO_LCDC_BRDG_PD, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
-		GPIO_CFG_2MA),       /* LCDC_BRDG_RESET_N */
-};
-
-enum {
-	DSI_SINGLE_LANE = 1,
-	DSI_TWO_LANES,
-};
-
-static int msm_fb_get_lane_config(void)
-{
-	int rc = DSI_TWO_LANES;
-
-	if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
-		rc = DSI_SINGLE_LANE;
-		pr_info("DSI Single Lane\n");
-	} else {
-		pr_info("DSI Two Lanes\n");
-	}
-	return rc;
-}
-
-static int msm_fb_dsi_client_reset(void)
-{
-	int rc = 0;
-
-	rc = gpio_request(GPIO_LCDC_BRDG_RESET_N, "lcdc_brdg_reset_n");
-	if (rc < 0) {
-		pr_err("failed to request lcd brdg reset_n\n");
-		return rc;
-	}
-
-	rc = gpio_request(GPIO_LCDC_BRDG_PD, "lcdc_brdg_pd");
-	if (rc < 0) {
-		pr_err("failed to request lcd brdg pd\n");
-		return rc;
-	}
-
-	rc = gpio_tlmm_config(mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
-	if (rc) {
-		pr_err("Failed to enable LCDC Bridge reset enable\n");
-		goto gpio_error;
-	}
-
-	rc = gpio_tlmm_config(mipi_dsi_gpio[1], GPIO_CFG_ENABLE);
-	if (rc) {
-		pr_err("Failed to enable LCDC Bridge pd enable\n");
-		goto gpio_error2;
-	}
-
-	rc = gpio_direction_output(GPIO_LCDC_BRDG_RESET_N, 1);
-	rc |= gpio_direction_output(GPIO_LCDC_BRDG_PD, 1);
-	gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 0);
-
-	if (!rc) {
-		if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()) {
-			lcdc_reset_ptr = ioremap_nocache(LCDC_RESET_PHYS,
-				sizeof(uint32_t));
-
-			if (!lcdc_reset_ptr)
-				return 0;
-		}
-		return rc;
-	} else {
-		goto gpio_error;
-	}
-
-gpio_error2:
-	pr_err("Failed GPIO bridge pd\n");
-	gpio_free(GPIO_LCDC_BRDG_PD);
-
-gpio_error:
-	pr_err("Failed GPIO bridge reset\n");
-	gpio_free(GPIO_LCDC_BRDG_RESET_N);
-	return rc;
-}
-
-static struct regulator_bulk_data regs_dsi[] = {
-	{ .supply = "gp2",   .min_uV = 2850000, .max_uV = 2850000 },
-	{ .supply = "msme1", .min_uV = 1800000, .max_uV = 1800000 },
-};
-
-static int dsi_gpio_initialized;
-
-static int mipi_dsi_panel_power(int on)
-{
-	int rc = 0;
-	uint32_t lcdc_reset_cfg;
-
-	/* I2C-controlled GPIO Expander -init of the GPIOs very late */
-	if (unlikely(!dsi_gpio_initialized)) {
-		pmapp_disp_backlight_init();
-
-		rc = gpio_request(GPIO_DISPLAY_PWR_EN, "gpio_disp_pwr");
-		if (rc < 0) {
-			pr_err("failed to request gpio_disp_pwr\n");
-			return rc;
-		}
-
-		if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()) {
-			rc = gpio_direction_output(GPIO_DISPLAY_PWR_EN, 1);
-			if (rc < 0) {
-				pr_err("failed to enable display pwr\n");
-				goto fail_gpio1;
-			}
-
-			rc = gpio_request(GPIO_BACKLIGHT_EN, "gpio_bkl_en");
-			if (rc < 0) {
-				pr_err("failed to request gpio_bkl_en\n");
-				goto fail_gpio1;
-			}
-
-			rc = gpio_direction_output(GPIO_BACKLIGHT_EN, 1);
-			if (rc < 0) {
-				pr_err("failed to enable backlight\n");
-				goto fail_gpio2;
-			}
-		}
-
-		rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_dsi), regs_dsi);
-		if (rc) {
-			pr_err("%s: could not get regulators: %d\n",
-					__func__, rc);
-			goto fail_gpio2;
-		}
-
-		rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_dsi), regs_dsi);
-		if (rc) {
-			pr_err("%s: could not set voltages: %d\n",
-					__func__, rc);
-			goto fail_vreg;
-		}
-		if (pmapp_disp_backlight_set_brightness(100))
-			pr_err("backlight set brightness failed\n");
-
-		dsi_gpio_initialized = 1;
-	}
-
-	if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()) {
-		gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, on);
-		gpio_set_value_cansleep(GPIO_BACKLIGHT_EN, on);
-	} else if (machine_is_msm7x27a_ffa() ||
-			 machine_is_msm7625a_ffa()) {
-		if (on) {
-			/* This line drives an active low pin on FFA */
-			rc = gpio_direction_output(GPIO_DISPLAY_PWR_EN, !on);
-			if (rc < 0)
-				pr_err("failed to set direction for "
-					"display pwr\n");
-		} else {
-			gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, !on);
-			rc = gpio_direction_input(GPIO_DISPLAY_PWR_EN);
-			if (rc < 0)
-				pr_err("failed to set direction for "
-					"display pwr\n");
-		}
-	}
-
-	if (on) {
-		gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 0);
-
-		if (machine_is_msm7x27a_surf() ||
-				 machine_is_msm7625a_surf()) {
-			lcdc_reset_cfg = readl_relaxed(lcdc_reset_ptr);
-			rmb();
-			lcdc_reset_cfg &= ~1;
-
-			writel_relaxed(lcdc_reset_cfg, lcdc_reset_ptr);
-			msleep(20);
-			wmb();
-			lcdc_reset_cfg |= 1;
-			writel_relaxed(lcdc_reset_cfg, lcdc_reset_ptr);
-		} else {
-			gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 0);
-			msleep(20);
-			gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
-		}
-	} else {
-		gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 1);
-
-		if (pmapp_disp_backlight_set_brightness(0))
-			pr_err("backlight set brightness failed\n");
-	}
-
-	rc = on ? regulator_bulk_enable(ARRAY_SIZE(regs_dsi), regs_dsi) :
-		  regulator_bulk_disable(ARRAY_SIZE(regs_dsi), regs_dsi);
-
-	if (rc)
-		pr_err("%s: could not %sable regulators: %d\n",
-				__func__, on ? "en" : "dis", rc);
-
-	return rc;
-
-fail_vreg:
-	regulator_bulk_free(ARRAY_SIZE(regs_dsi), regs_dsi);
-fail_gpio2:
-	gpio_free(GPIO_BACKLIGHT_EN);
-fail_gpio1:
-	gpio_free(GPIO_DISPLAY_PWR_EN);
-	dsi_gpio_initialized = 0;
-	return rc;
-}
-#endif
-
-#define MDP_303_VSYNC_GPIO 97
-
-#ifdef CONFIG_FB_MSM_MDP303
-static struct mipi_dsi_platform_data mipi_dsi_pdata = {
-	.vsync_gpio = MDP_303_VSYNC_GPIO,
-	.dsi_power_save   = mipi_dsi_panel_power,
-	.dsi_client_reset = msm_fb_dsi_client_reset,
-	.get_lane_config = msm_fb_get_lane_config,
-};
-#endif
-
-static void __init msm_fb_add_devices(void)
-{
-	msm_fb_register_device("mdp", &mdp_pdata);
-	msm_fb_register_device("lcdc", &lcdc_pdata);
-#ifdef CONFIG_FB_MSM_MDP303
-	msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
-#endif
-}
-
 #define MSM_EBI2_PHYS			0xa0d00000
 #define MSM_EBI2_XMEM_CS2_CFG1		0xa0d10030
 
@@ -1573,12 +1075,21 @@
 			ARRAY_SIZE(rumi_sim_devices));
 }
 
+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));
+}
+
 #define LED_GPIO_PDM		96
 #define UART1DM_RX_GPIO		45
 
 #if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
 static int __init msm7x27a_init_ar6000pm(void)
 {
+	msm_wlan_ar6000_pm_device.dev.platform_data = &ar600x_wlan_power;
 	return platform_device_register(&msm_wlan_ar6000_pm_device);
 }
 #else
@@ -1678,7 +1189,7 @@
 
 static void __init msm7x2x_init_early(void)
 {
-	msm_msm7x2x_allocate_memory_regions();
+	msm_msm7627a_allocate_memory_regions();
 }
 
 MACHINE_START(MSM7X27A_RUMI3, "QCT MSM7x27a RUMI3")
@@ -1731,3 +1242,12 @@
 	.init_early     = msm7x2x_init_early,
 	.handle_irq	= vic_handle_irq,
 MACHINE_END
+MACHINE_START(MSM8625_RUMI3, "QCT MSM8625 RUMI3")
+	.boot_params    = PHYS_OFFSET + 0x100,
+	.map_io         = msm8625_map_io,
+	.reserve        = msm8625_reserve,
+	.init_irq       = msm8625_init_irq,
+	.init_machine   = msm8625_rumi3_init,
+	.timer          = &msm_timer,
+	.handle_irq	= gic_handle_irq,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index bd570cf..e0b3c49 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -78,7 +78,7 @@
 #include <linux/usb/android.h>
 #include <mach/usbdiag.h>
 #endif
-#include <mach/pm.h>
+#include "pm.h"
 #include "pm-boot.h"
 #include "spm.h"
 #include "acpuclock.h"
@@ -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;
@@ -797,6 +804,7 @@
 
 #ifdef CONFIG_MSM_SSBI
 static struct msm_ssbi_platform_data msm7x30_ssbi_pm8058_pdata = {
+	.rsl_id = "D:PMIC_SSBI",
 	.controller_type = MSM_SBI_CTRL_SSBI2,
 	.slave	= {
 		.name			= "pm8058-core",
@@ -2143,10 +2151,10 @@
 
 
 static struct msm_ts_platform_data msm_ts_data = {
-	.min_x          = 0,
-	.max_x          = 4096,
-	.min_y          = 0,
-	.max_y          = 4096,
+	.min_x          = 284,
+	.max_x          = 3801,
+	.min_y          = 155,
+	.max_y          = 3929,
 	.min_press      = 0,
 	.max_press      = 255,
 	.inv_x          = 4096,
@@ -6348,6 +6356,10 @@
 static struct tsc2007_platform_data tsc2007_ts_data = {
 	.model = 2007,
 	.x_plate_ohms = 300,
+	.min_x		= 210,
+	.max_x		= 3832,
+	.min_y		= 150,
+	.max_y		= 3936,
 	.irq_flags    = IRQF_TRIGGER_LOW,
 	.init_platform_hw = tsc2007_init,
 	.exit_platform_hw = tsc2007_exit,
@@ -6893,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;
 }
@@ -6939,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,
@@ -6948,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")
@@ -6959,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")
@@ -6970,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")
@@ -6981,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")
@@ -6992,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,
@@ -7002,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,
@@ -7012,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/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 7699aa8..29f5fac 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -89,7 +89,7 @@
 #include "devices.h"
 #include "devices-msm8x60.h"
 #include <mach/cpuidle.h>
-#include <mach/pm.h>
+#include "pm.h"
 #include "mpm.h"
 #include "spm.h"
 #include "rpm_log.h"
@@ -918,6 +918,33 @@
 	},
 };
 
+static struct msm_rpmrs_platform_data msm_rpmrs_data __initdata = {
+	.levels = &msm_rpmrs_levels[0],
+	.num_levels = ARRAY_SIZE(msm_rpmrs_levels),
+	.vdd_mem_levels  = {
+		[MSM_RPMRS_VDD_MEM_RET_LOW]     = 500,
+		[MSM_RPMRS_VDD_MEM_RET_HIGH]    = 750,
+		[MSM_RPMRS_VDD_MEM_ACTIVE]      = 1000,
+		[MSM_RPMRS_VDD_MEM_MAX]         = 1250,
+	},
+	.vdd_dig_levels = {
+		[MSM_RPMRS_VDD_DIG_RET_LOW]     = 500,
+		[MSM_RPMRS_VDD_DIG_RET_HIGH]    = 750,
+		[MSM_RPMRS_VDD_DIG_ACTIVE]      = 1000,
+		[MSM_RPMRS_VDD_DIG_MAX]         = 1250,
+	},
+	.vdd_mask = 0xFFF,
+	.rpmrs_target_id = {
+		[MSM_RPMRS_ID_PXO_CLK]          = MSM_RPM_ID_PXO_CLK,
+		[MSM_RPMRS_ID_L2_CACHE_CTL]     = MSM_RPM_ID_APPS_L2_CACHE_CTL,
+		[MSM_RPMRS_ID_VDD_DIG_0]        = MSM_RPM_ID_SMPS1_0,
+		[MSM_RPMRS_ID_VDD_DIG_1]        = MSM_RPM_ID_SMPS1_1,
+		[MSM_RPMRS_ID_VDD_MEM_0]        = MSM_RPM_ID_SMPS0_0,
+		[MSM_RPMRS_ID_VDD_MEM_1]        = MSM_RPM_ID_SMPS0_1,
+		[MSM_RPMRS_ID_RPM_CTL]          = MSM_RPM_ID_TRIGGER_SET_FROM,
+	},
+};
+
 static struct msm_pm_boot_platform_data msm_pm_boot_pdata __initdata = {
 	.mode = MSM_PM_BOOT_CONFIG_TZ,
 };
@@ -2676,9 +2703,10 @@
 #define MSM_ION_MM_SIZE		0x3600000 /* (54MB) */
 #define MSM_ION_MFC_SIZE	SZ_8K
 #define MSM_ION_WB_SIZE		0x600000 /* 6MB */
+#define MSM_ION_AUDIO_SIZE	MSM_PMEM_AUDIO_SIZE
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-#define MSM_ION_HEAP_NUM	7
+#define MSM_ION_HEAP_NUM	8
 #else
 #define MSM_ION_HEAP_NUM	1
 #endif
@@ -3727,28 +3755,6 @@
 
 #endif
 
-#if defined(CONFIG_MSM_RPM_LOG) || defined(CONFIG_MSM_RPM_LOG_MODULE)
-
-static struct msm_rpm_log_platform_data msm_rpm_log_pdata = {
-	.phys_addr_base = 0x00106000,
-	.reg_offsets = {
-		[MSM_RPM_LOG_PAGE_INDICES] = 0x00000C80,
-		[MSM_RPM_LOG_PAGE_BUFFER]  = 0x00000CA0,
-	},
-	.phys_size = SZ_8K,
-	.log_len = 4096,		  /* log's buffer length in bytes */
-	.log_len_mask = (4096 >> 2) - 1,  /* length mask in units of u32 */
-};
-
-static struct platform_device msm_rpm_log_device = {
-	.name	= "msm_rpm_log",
-	.id	= -1,
-	.dev	= {
-		.platform_data = &msm_rpm_log_pdata,
-	},
-};
-#endif
-
 #ifdef CONFIG_BATTERY_MSM8X60
 static struct msm_charger_platform_data msm_charger_data = {
 	.safety_time = 180,
@@ -5193,10 +5199,10 @@
 #endif
 
 #if defined(CONFIG_MSM_RPM_LOG) || defined(CONFIG_MSM_RPM_LOG_MODULE)
-	&msm_rpm_log_device,
+	&msm8660_rpm_log_device,
 #endif
 #if defined(CONFIG_MSM_RPM_STATS_LOG)
-	&msm_rpm_stat_device,
+	&msm8660_rpm_stat_device,
 #endif
 	&msm_device_vidc,
 #if (defined(CONFIG_MARIMBA_CORE)) && \
@@ -5232,7 +5238,7 @@
 #endif
 
 	&msm_tsens_device,
-	&msm_rpm_device,
+	&msm8660_rpm_device,
 #ifdef CONFIG_ION_MSM
 	&ion_dev,
 #endif
@@ -5329,6 +5335,14 @@
 			.memory_type = ION_EBI_TYPE,
 			.extra_data = (void *) &cp_wb_ion_pdata,
 		},
+		{
+			.id	= ION_AUDIO_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_AUDIO_HEAP_NAME,
+			.size	= MSM_ION_AUDIO_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *)&co_ion_pdata,
+		},
 #endif
 	}
 };
@@ -5377,6 +5391,7 @@
 	msm8x60_reserve_table[MEMTYPE_SMI].size += MSM_ION_MFC_SIZE;
 	msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_CAMERA_SIZE;
 	msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_WB_SIZE;
+	msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE;
 #endif
 }
 
@@ -10045,23 +10060,6 @@
 		PM8058_GPIO_IRQ(PM8058_IRQ_BASE, 6);
 }
 
-#ifdef CONFIG_MSM_RPM
-static struct msm_rpm_platform_data msm_rpm_data = {
-	.reg_base_addrs = {
-		[MSM_RPM_PAGE_STATUS] = MSM_RPM_BASE,
-		[MSM_RPM_PAGE_CTRL] = MSM_RPM_BASE + 0x400,
-		[MSM_RPM_PAGE_REQ] = MSM_RPM_BASE + 0x600,
-		[MSM_RPM_PAGE_ACK] = MSM_RPM_BASE + 0xa00,
-	},
-
-	.irq_ack = RPM_SCSS_CPU0_GP_HIGH_IRQ,
-	.irq_err = RPM_SCSS_CPU0_GP_LOW_IRQ,
-	.irq_vmpm = RPM_SCSS_CPU0_GP_MEDIUM_IRQ,
-	.msm_apps_ipc_rpm_reg = MSM_GCC_BASE + 0x008,
-	.msm_apps_ipc_rpm_val = 4,
-};
-#endif
-
 void msm_fusion_setup_pinctrl(void)
 {
 	struct msm_xo_voter *a1;
@@ -10129,11 +10127,8 @@
 	 * Initialize RPM first as other drivers and devices may need
 	 * it for their initialization.
 	 */
-#ifdef CONFIG_MSM_RPM
-	BUG_ON(msm_rpm_init(&msm_rpm_data));
-#endif
-	BUG_ON(msm_rpmrs_levels_init(msm_rpmrs_levels,
-				ARRAY_SIZE(msm_rpmrs_levels)));
+	BUG_ON(msm_rpm_init(&msm8660_rpm_data));
+	BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
 	if (msm_xo_init())
 		pr_err("Failed to initialize XO votes\n");
 
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 9d4818a..1222b67 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -26,6 +26,7 @@
 #include <linux/power_supply.h>
 #include <linux/input/rmi_platformdata.h>
 #include <linux/input/rmi_i2c.h>
+#include <linux/i2c/atmel_mxt_ts.h>
 #include <linux/regulator/consumer.h>
 #include <asm/mach/mmc.h>
 #include <asm/mach-types.h>
@@ -48,7 +49,7 @@
 #include "board-msm7x27a-regulator.h"
 #include "devices.h"
 #include "devices-msm7x2xa.h"
-#include <mach/pm.h>
+#include "pm.h"
 #include "timer.h"
 #include "pm-boot.h"
 #include "board-msm7x27a-regulator.h"
@@ -124,13 +125,6 @@
 #ifdef CONFIG_ARCH_MSM7X27A
 #define MSM_PMEM_MDP_SIZE       0x1DD1000
 #define MSM_PMEM_ADSP_SIZE      0x1000000
-
-#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_SIZE		0x260000
-#else
-#define MSM_FB_SIZE		0x195000
-#endif
-
 #endif
 
 #if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C) || \
@@ -474,66 +468,6 @@
 
 early_param("pmem_adsp_size", pmem_adsp_size_setup);
 
-static unsigned fb_size = MSM_FB_SIZE;
-static int __init fb_size_setup(char *p)
-{
-	fb_size = memparse(p, NULL);
-	return 0;
-}
-
-early_param("fb_size", fb_size_setup);
-
-static struct resource msm_fb_resources[] = {
-	{
-		.flags	= IORESOURCE_DMA,
-	}
-};
-
-static int msm_fb_detect_panel(const char *name)
-{
-	int ret;
-
-	if (!strncmp(name, "mipi_video_truly_wvga", 21))
-		ret = 0;
-	else
-		ret = -ENODEV;
-
-	return ret;
-}
-
-static int mipi_truly_set_bl(int on)
-{
-	gpio_set_value_cansleep(QRD_GPIO_BACKLIGHT_EN, !!on);
-
-	return 1;
-}
-
-static struct msm_fb_platform_data msm_fb_pdata = {
-	.detect_client = msm_fb_detect_panel,
-};
-
-static struct platform_device msm_fb_device = {
-	.name   = "msm_fb",
-	.id     = 0,
-	.num_resources  = ARRAY_SIZE(msm_fb_resources),
-	.resource       = msm_fb_resources,
-	.dev    = {
-		.platform_data = &msm_fb_pdata,
-	}
-};
-
-static struct msm_panel_common_pdata mipi_truly_pdata = {
-	.pmic_backlight = mipi_truly_set_bl,
-};
-
-static struct platform_device mipi_dsi_truly_panel_device = {
-	.name	= "mipi_truly",
-	.id	= 0,
-	.dev	= {
-		.platform_data = &mipi_truly_pdata,
-	}
-};
-
 #define SND(desc, num) { .name = #desc, .id = num }
 static struct snd_endpoint snd_endpoints_list[] = {
 	SND(HANDSET, 0),
@@ -725,7 +659,7 @@
 	.dev.platform_data  = &msm_psy_batt_data,
 };
 
-static struct platform_device *qrd1_devices[] __initdata = {
+static struct platform_device *qrd_common_devices[] __initdata = {
 	&msm_device_dmov,
 	&msm_device_smd,
 	&msm_device_uart1,
@@ -737,7 +671,6 @@
 	&android_usb_device,
 	&android_pmem_device,
 	&android_pmem_adsp_device,
-	&msm_fb_device,
 	&android_pmem_audio_device,
 	&msm_device_snd,
 	&msm_device_adspdec,
@@ -746,8 +679,6 @@
 #ifdef CONFIG_BT
 	&msm_bt_power_device,
 #endif
-	&mipi_dsi_truly_panel_device,
-	&msm_wlan_ar6000_pm_device,
 	&asoc_msm_pcm,
 	&asoc_msm_dai0,
 	&asoc_msm_dai1,
@@ -769,19 +700,6 @@
 }
 early_param("pmem_audio_size", pmem_audio_size_setup);
 
-static void __init msm_msm7627a_allocate_memory_regions(void)
-{
-	void *addr;
-	unsigned long size;
-
-	size = fb_size ? : MSM_FB_SIZE;
-	addr = alloc_bootmem_align(size, 0x1000);
-	msm_fb_resources[0].start = __pa(addr);
-	msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
-	pr_info("allocating %lu bytes at %p (%lx physical) for fb\n", size,
-						addr, __pa(addr));
-}
-
 static struct memtype_reserve msm7627a_reserve_table[] __initdata = {
 	[MEMTYPE_SMI] = {
 	},
@@ -793,167 +711,6 @@
 	},
 };
 
-static struct msm_panel_common_pdata mdp_pdata = {
-	.gpio = 97,
-	.mdp_rev = MDP_REV_303,
-};
-
-#define GPIO_LCDC_BRDG_PD      128
-#define GPIO_LCDC_BRDG_RESET_N 129
-#define GPIO_LCD_DSI_SEL 125
-
-static unsigned mipi_dsi_gpio[] = {
-		GPIO_CFG(GPIO_LCDC_BRDG_RESET_N, 0, GPIO_CFG_OUTPUT,
-		GPIO_CFG_NO_PULL, GPIO_CFG_2MA), /* LCDC_BRDG_RESET_N */
-		GPIO_CFG(GPIO_LCDC_BRDG_PD, 0, GPIO_CFG_OUTPUT,
-		GPIO_CFG_NO_PULL, GPIO_CFG_2MA), /* LCDC_BRDG_PD */
-};
-
-static unsigned lcd_dsi_sel_gpio[] = {
-	GPIO_CFG(GPIO_LCD_DSI_SEL, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
-			GPIO_CFG_2MA),
-};
-
-enum {
-	DSI_SINGLE_LANE = 1,
-	DSI_TWO_LANES,
-};
-
-static int msm_fb_get_lane_config(void)
-{
-	pr_info("DSI_TWO_LANES\n");
-	return DSI_TWO_LANES;
-}
-
-static int mipi_truly_sel_mode(int video_mode)
-{
-	int rc = 0;
-
-	rc = gpio_request(GPIO_LCD_DSI_SEL, "lcd_dsi_sel");
-	if (rc < 0)
-		goto gpio_error;
-
-	rc = gpio_tlmm_config(lcd_dsi_sel_gpio[0], GPIO_CFG_ENABLE);
-	if (rc)
-		goto gpio_error;
-
-	rc = gpio_direction_output(GPIO_LCD_DSI_SEL, 1);
-	if (!rc) {
-		gpio_set_value_cansleep(GPIO_LCD_DSI_SEL, video_mode);
-		return rc;
-	} else {
-		goto gpio_error;
-	}
-
-gpio_error:
-	pr_err("mipi_truly_sel_mode failed\n");
-	gpio_free(GPIO_LCD_DSI_SEL);
-	return rc;
-}
-
-static int msm_fb_dsi_client_qrd1_reset(void)
-{
-	int rc = 0;
-
-	rc = gpio_request(GPIO_LCDC_BRDG_RESET_N, "lcdc_brdg_reset_n");
-	if (rc < 0) {
-		pr_err("failed to request lcd brdg reset_n\n");
-		return rc;
-	}
-
-	rc = gpio_tlmm_config(mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
-	if (rc < 0) {
-		pr_err("Failed to enable LCDC Bridge reset enable\n");
-		return rc;
-	}
-
-	rc = gpio_direction_output(GPIO_LCDC_BRDG_RESET_N, 1);
-	if (rc < 0) {
-		pr_err("Failed GPIO bridge pd\n");
-		gpio_free(GPIO_LCDC_BRDG_RESET_N);
-		return rc;
-	}
-
-	mipi_truly_sel_mode(1);
-
-	return rc;
-}
-
-static int msm_fb_dsi_client_reset(void)
-{
-	int rc = 0;
-
-	rc = msm_fb_dsi_client_qrd1_reset();
-	return rc;
-}
-
-static int dsi_gpio_initialized;
-
-static int mipi_dsi_panel_qrd1_power(int on)
-{
-	int rc = 0;
-
-	if (!dsi_gpio_initialized) {
-		rc = gpio_request(QRD_GPIO_BACKLIGHT_EN, "gpio_bkl_en");
-		if (rc < 0)
-			return rc;
-
-		rc = gpio_tlmm_config(GPIO_CFG(QRD_GPIO_BACKLIGHT_EN, 0,
-			GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
-			GPIO_CFG_ENABLE);
-		if (rc < 0) {
-			pr_err("failed GPIO_BACKLIGHT_EN tlmm config\n");
-			return rc;
-		}
-
-		rc = gpio_direction_output(QRD_GPIO_BACKLIGHT_EN, 1);
-		if (rc < 0) {
-			pr_err("failed to enable backlight\n");
-			gpio_free(QRD_GPIO_BACKLIGHT_EN);
-			return rc;
-		}
-		dsi_gpio_initialized = 1;
-	}
-
-	gpio_set_value_cansleep(QRD_GPIO_BACKLIGHT_EN, !!on);
-
-	if (!on) {
-		gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
-		msleep(20);
-		gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 0);
-		msleep(20);
-		gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
-
-	}
-
-	return rc;
-}
-
-static int mipi_dsi_panel_power(int on)
-{
-	int rc = 0;
-
-	rc = mipi_dsi_panel_qrd1_power(on);
-	return rc;
-}
-
-#define MDP_303_VSYNC_GPIO 97
-
-#ifdef CONFIG_FB_MSM_MDP303
-static struct mipi_dsi_platform_data mipi_dsi_pdata = {
-	.vsync_gpio		= MDP_303_VSYNC_GPIO,
-	.dsi_power_save		= mipi_dsi_panel_power,
-	.dsi_client_reset	= msm_fb_dsi_client_reset,
-	.get_lane_config	= msm_fb_get_lane_config,
-};
-#endif
-
-static void __init msm_fb_add_devices(void)
-{
-	msm_fb_register_device("mdp", &mdp_pdata);
-	msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
-}
-
 static void __init size_pmem_devices(void)
 {
 #ifdef CONFIG_ANDROID_PMEM
@@ -1036,8 +793,231 @@
 				__func__, rc);
 }
 
+/* 8625 keypad device information */
+static unsigned int kp_row_gpios_8625[] = {31};
+static unsigned int kp_col_gpios_8625[] = {36, 37};
+
+static const unsigned short keymap_8625[] = {
+	KEY_VOLUMEUP,
+	KEY_VOLUMEDOWN,
+};
+
+static struct gpio_event_matrix_info kp_matrix_info_8625 = {
+	.info.func      = gpio_event_matrix_func,
+	.keymap         = keymap_8625,
+	.output_gpios   = kp_row_gpios_8625,
+	.input_gpios    = kp_col_gpios_8625,
+	.noutputs       = ARRAY_SIZE(kp_row_gpios_8625),
+	.ninputs        = ARRAY_SIZE(kp_col_gpios_8625),
+	.settle_time.tv_nsec = 40 * NSEC_PER_USEC,
+	.poll_time.tv_nsec = 20 * NSEC_PER_MSEC,
+	.flags          = GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_DRIVE_INACTIVE |
+			  GPIOKPF_PRINT_UNMAPPED_KEYS,
+};
+
+static struct gpio_event_info *kp_info_8625[] = {
+	&kp_matrix_info_8625.info,
+};
+static struct gpio_event_platform_data kp_pdata_8625 = {
+	.name           = "8625_kp",
+	.info           = kp_info_8625,
+	.info_count     = ARRAY_SIZE(kp_info_8625)
+};
+
+static struct platform_device kp_pdev_8625 = {
+	.name   = GPIO_EVENT_DEV_NAME,
+	.id     = -1,
+	.dev    = {
+		.platform_data  = &kp_pdata_8625,
+	},
+};
+
+#define LED_RED_GPIO_8625 49
+#define LED_GREEN_GPIO_8625 34
+
+static struct gpio_led gpio_leds_config_8625[] = {
+	{
+		.name = "green",
+		.gpio = LED_GREEN_GPIO_8625,
+	},
+	{
+		.name = "red",
+		.gpio = LED_RED_GPIO_8625,
+	},
+};
+
+static struct gpio_led_platform_data gpio_leds_pdata_8625 = {
+	.num_leds = ARRAY_SIZE(gpio_leds_config_8625),
+	.leds = gpio_leds_config_8625,
+};
+
+static struct platform_device gpio_leds_8625 = {
+	.name          = "leds-gpio",
+	.id            = -1,
+	.dev           = {
+		.platform_data = &gpio_leds_pdata_8625,
+	},
+};
+
+#define MXT_TS_IRQ_GPIO         48
+#define MXT_TS_RESET_GPIO       26
+
+static const u8 mxt_config_data[] = {
+	/* T6 Object */
+	0, 0, 0, 0, 0, 0,
+	/* T38 Object */
+	16, 0, 0, 0, 0, 0, 0, 0,
+	/* T7 Object */
+	255, 255, 10,
+	/* T8 Object */
+	30, 0, 20, 20, 0, 0, 20, 0, 50, 0,
+	/* T9 Object */
+	3, 0, 0, 18, 11, 0, 32, 75, 3, 3,
+	0, 1, 1, 0, 10, 10, 10, 10, 31, 3,
+	223, 1, 11, 11, 15, 15, 151, 43, 145, 80,
+	100, 15, 0, 0, 0,
+	/* T15 Object */
+	131, 0, 11, 11, 1, 1, 0, 45, 3, 0,
+	0,
+	/* T18 Object */
+	0, 0,
+	/* T19 Object */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0,
+	/* T23 Object */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0,
+	/* T25 Object */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0,
+	/* T40 Object */
+	0, 0, 0, 0, 0,
+	/* T42 Object */
+	0, 0, 0, 0, 0, 0, 0, 0,
+	/* T46 Object */
+	0, 2, 32, 48, 0, 0, 0, 0, 0,
+	/* T47 Object */
+	1, 20, 60, 5, 2, 50, 40, 0, 0, 40,
+	/* T48 Object */
+	1, 12, 80, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 6, 6, 0, 0, 100, 4, 64,
+	10, 0, 20, 5, 0, 38, 0, 20, 0, 0,
+	0, 0, 0, 0, 16, 65, 3, 1, 1, 0,
+	10, 10, 10, 0, 0, 15, 15, 154, 58, 145,
+	80, 100, 15, 3,
+};
+
+static struct mxt_config_info mxt_config_array[] = {
+	{
+		.config		= mxt_config_data,
+		.config_length	= ARRAY_SIZE(mxt_config_data),
+		.family_id	= 0x81,
+		.variant_id	= 0x01,
+		.version	= 0x10,
+		.build		= 0xAA,
+	},
+};
+
+static int mxt_key_codes[MXT_KEYARRAY_MAX_KEYS] = {
+	[0] = KEY_HOME,
+	[1] = KEY_MENU,
+	[9] = KEY_BACK,
+	[10] = KEY_SEARCH,
+};
+
+static struct mxt_platform_data mxt_platform_data = {
+	.config_array		= mxt_config_array,
+	.config_array_size	= ARRAY_SIZE(mxt_config_array),
+	.x_size                 = 479,
+	.y_size                 = 799,
+	.irqflags               = IRQF_TRIGGER_FALLING,
+	.i2c_pull_up            = true,
+	.reset_gpio		= MXT_TS_RESET_GPIO,
+	.irq_gpio		= MXT_TS_IRQ_GPIO,
+	.key_codes		= mxt_key_codes,
+};
+
+static struct i2c_board_info mxt_device_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("atmel_mxt_ts", 0x4a),
+		.platform_data = &mxt_platform_data,
+		.irq = MSM_GPIO_TO_INT(MXT_TS_IRQ_GPIO),
+	},
+};
+
+static void msm7627a_add_io_devices(void)
+{
+	int rc;
+
+	/* touchscreen */
+	if (machine_is_msm7627a_qrd1()) {
+		i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
+					synaptic_i2c_clearpad3k,
+					ARRAY_SIZE(synaptic_i2c_clearpad3k));
+	} else if (machine_is_msm7627a_evb()) {
+		rc = gpio_tlmm_config(GPIO_CFG(MXT_TS_IRQ_GPIO, 0,
+				GPIO_CFG_INPUT, GPIO_CFG_PULL_UP,
+				GPIO_CFG_8MA), GPIO_CFG_ENABLE);
+		if (rc) {
+			pr_err("%s: gpio_tlmm_config for %d failed\n",
+				__func__, MXT_TS_IRQ_GPIO);
+		}
+
+		rc = gpio_tlmm_config(GPIO_CFG(MXT_TS_RESET_GPIO, 0,
+				GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
+				GPIO_CFG_8MA), GPIO_CFG_ENABLE);
+		if (rc) {
+			pr_err("%s: gpio_tlmm_config for %d failed\n",
+				__func__, MXT_TS_RESET_GPIO);
+		}
+
+		i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
+					mxt_device_info,
+					ARRAY_SIZE(mxt_device_info));
+	}
+
+	/* headset */
+	platform_device_register(&hs_pdev);
+
+	/* vibrator */
+#ifdef CONFIG_MSM_RPC_VIBRATOR
+	msm_init_pmic_vibrator();
+#endif
+
+	/* keypad */
+	if (machine_is_msm7627a_evb())
+		platform_device_register(&kp_pdev_8625);
+
+	/* leds */
+	if (machine_is_msm7627a_evb()) {
+		rc = gpio_tlmm_config(GPIO_CFG(LED_RED_GPIO_8625, 0,
+				GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
+				GPIO_CFG_16MA), GPIO_CFG_ENABLE);
+		if (rc) {
+			pr_err("%s: gpio_tlmm_config for %d failed\n",
+				__func__, LED_RED_GPIO_8625);
+		}
+
+		rc = gpio_tlmm_config(GPIO_CFG(LED_GREEN_GPIO_8625, 0,
+				GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
+				GPIO_CFG_16MA), GPIO_CFG_ENABLE);
+		if (rc) {
+			pr_err("%s: gpio_tlmm_config for %d failed\n",
+				__func__, LED_GREEN_GPIO_8625);
+		}
+
+		platform_device_register(&gpio_leds_8625);
+	}
+}
+
+static int __init msm_qrd_init_ar6000pm(void)
+{
+	msm_wlan_ar6000_pm_device.dev.platform_data = &ar600x_wlan_power;
+	return platform_device_register(&msm_wlan_ar6000_pm_device);
+}
+
 #define UART1DM_RX_GPIO		45
-static void __init msm_qrd1_init(void)
+static void __init msm_qrd_init(void)
 {
 	msm7x2x_misc_init();
 	msm7627a_init_regulators();
@@ -1054,8 +1034,12 @@
 #endif
 	msm_device_gadget_peripheral.dev.platform_data =
 		&msm_gadget_pdata;
-	platform_add_devices(qrd1_devices,
-			ARRAY_SIZE(qrd1_devices));
+
+	platform_add_devices(qrd_common_devices,
+			ARRAY_SIZE(qrd_common_devices));
+
+	/* Ensure ar6000pm device is registered before MMC/SDC */
+	msm_qrd_init_ar6000pm();
 	msm7627a_init_mmc();
 
 #ifdef CONFIG_USB_EHCI_MSM_72K
@@ -1073,17 +1057,7 @@
 
 	msm7627a_camera_init();
 
-#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C) || \
-	defined(CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C_MODULE)
-	i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
-				synaptic_i2c_clearpad3k,
-				ARRAY_SIZE(synaptic_i2c_clearpad3k));
-#endif
-	platform_device_register(&hs_pdev);
-
-#ifdef CONFIG_MSM_RPC_VIBRATOR
-	msm_init_pmic_vibrator();
-#endif
+	msm7627a_add_io_devices();
 }
 
 static void __init qrd7627a_init_early(void)
@@ -1096,7 +1070,17 @@
 	.map_io		= msm_common_io_init,
 	.reserve	= msm7627a_reserve,
 	.init_irq	= msm_init_irq,
-	.init_machine	= msm_qrd1_init,
+	.init_machine	= msm_qrd_init,
+	.timer		= &msm_timer,
+	.init_early	= qrd7627a_init_early,
+	.handle_irq	= vic_handle_irq,
+MACHINE_END
+MACHINE_START(MSM7627A_EVB, "QRD MSM7627a EVB")
+	.boot_params	= PHYS_OFFSET + 0x100,
+	.map_io		= msm_common_io_init,
+	.reserve	= msm7627a_reserve,
+	.init_irq	= msm_init_irq,
+	.init_machine	= msm_qrd_init,
 	.timer		= &msm_timer,
 	.init_early	= qrd7627a_init_early,
 	.handle_irq	= vic_handle_irq,
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index 65aaa9a..5a77333 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -54,7 +54,7 @@
 #include "timer.h"
 #include "msm-keypad-devices.h"
 #include "acpuclock.h"
-#include <mach/pm.h>
+#include "pm.h"
 #include "pm-boot.h"
 #include "proc_comm.h"
 #ifdef CONFIG_USB_ANDROID
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index 9170842..8374636 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -120,11 +120,8 @@
 #define SRC_SEL_gnd		7 /* No clock */
 
 /* Clock declaration macros. */
-#define MN_MODE_DUAL_EDGE	0x2
-#define MD8(m, n)		(BVAL(15, 8, m) | BVAL(7, 0, ~(n)))
 #define N8(msb, lsb, m, n)	(BVAL(msb, lsb, ~(n-m)) | BVAL(6, 5, \
 					(MN_MODE_DUAL_EDGE * !!(n))))
-#define MD16(m, n)		(BVAL(31, 16, m) | BVAL(15, 0, ~(n)))
 #define N16(m, n)		(BVAL(31, 16, ~(n-m)) | BVAL(6, 5, \
 					(MN_MODE_DUAL_EDGE * !!(n))))
 #define SPDIV(s, d)		(BVAL(4, 3, d-1) | BVAL(2, 0, s))
@@ -156,7 +153,7 @@
 	{ \
 		.freq_hz = f, \
 		.src_clk = &s##_clk.c, \
-		.md_val = MD8(m, n), \
+		.md_val = MD8(8, m, 0, n), \
 		.ns_val = N8(nmsb, nlsb, m, n) | SPDIV(SRC_SEL_##s, div), \
 		.mnd_en_mask = BIT(8) * !!(n), \
 	}
@@ -2752,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") },
 
@@ -2839,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 09f70f1..8ecfea2 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -69,6 +69,7 @@
 #define PDM_CLK_NS_REG				REG(0x2CC0)
 /* 8064 name BB_PLL_ENA_APCS_REG */
 #define BB_PLL_ENA_SC0_REG			REG(0x34C0)
+#define BB_PLL_ENA_RPM_REG			REG(0x34A0)
 #define BB_PLL0_STATUS_REG			REG(0x30D8)
 #define BB_PLL5_STATUS_REG			REG(0x30F8)
 #define BB_PLL6_STATUS_REG			REG(0x3118)
@@ -353,57 +354,6 @@
 
 #define MN_MODE_DUAL_EDGE 0x2
 
-/* MD Registers */
-#define MD4(m_lsb, m, n_lsb, n) \
-		(BVAL((m_lsb+3), m_lsb, m) | BVAL((n_lsb+3), n_lsb, ~(n)))
-#define MD8(m_lsb, m, n_lsb, n) \
-		(BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n)))
-#define MD16(m, n) (BVAL(31, 16, m) | BVAL(15, 0, ~(n)))
-
-/* NS Registers */
-#define NS(n_msb, n_lsb, n, m, mde_lsb, d_msb, d_lsb, d, s_msb, s_lsb, s) \
-		(BVAL(n_msb, n_lsb, ~(n-m)) \
-		| (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n)) \
-		| BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
-
-#define NS_MM(n_msb, n_lsb, n, m, d_msb, d_lsb, d, s_msb, s_lsb, s) \
-		(BVAL(n_msb, n_lsb, ~(n-m)) | BVAL(d_msb, d_lsb, (d-1)) \
-		| BVAL(s_msb, s_lsb, s))
-
-#define NS_DIVSRC(d_msb , d_lsb, d, s_msb, s_lsb, s) \
-		(BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
-
-#define NS_DIV(d_msb , d_lsb, d) \
-		BVAL(d_msb, d_lsb, (d-1))
-
-#define NS_SRC_SEL(s_msb, s_lsb, s) \
-		BVAL(s_msb, s_lsb, s)
-
-#define NS_MND_BANKED4(n0_lsb, n1_lsb, n, m, s0_lsb, s1_lsb, s) \
-		 (BVAL((n0_lsb+3), n0_lsb, ~(n-m)) \
-		| BVAL((n1_lsb+3), n1_lsb, ~(n-m)) \
-		| BVAL((s0_lsb+2), s0_lsb, s) \
-		| BVAL((s1_lsb+2), s1_lsb, s))
-
-#define NS_MND_BANKED8(n0_lsb, n1_lsb, n, m, s0_lsb, s1_lsb, s) \
-		 (BVAL((n0_lsb+7), n0_lsb, ~(n-m)) \
-		| BVAL((n1_lsb+7), n1_lsb, ~(n-m)) \
-		| BVAL((s0_lsb+2), s0_lsb, s) \
-		| BVAL((s1_lsb+2), s1_lsb, s))
-
-#define NS_DIVSRC_BANKED(d0_msb, d0_lsb, d1_msb, d1_lsb, d, \
-	s0_msb, s0_lsb, s1_msb, s1_lsb, s) \
-		 (BVAL(d0_msb, d0_lsb, (d-1)) | BVAL(d1_msb, d1_lsb, (d-1)) \
-		| BVAL(s0_msb, s0_lsb, s) \
-		| BVAL(s1_msb, s1_lsb, s))
-
-/* CC Registers */
-#define CC(mde_lsb, n) (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n))
-#define CC_BANKED(mde0_lsb, mde1_lsb, n) \
-		((BVAL((mde0_lsb+1), mde0_lsb, MN_MODE_DUAL_EDGE) \
-		| BVAL((mde1_lsb+1), mde1_lsb, MN_MODE_DUAL_EDGE)) \
-		* !!(n))
-
 struct pll_rate {
 	const uint32_t	l_val;
 	const uint32_t	m_val;
@@ -414,6 +364,9 @@
 };
 #define PLL_RATE(l, m, n, v, d, i) { l, m, n, v, (d>>1), i }
 
+static int rpm_vreg_id_vdd_dig;
+static int rpm_vreg_id_vdd_sr2_pll;
+
 enum vdd_dig_levels {
 	VDD_DIG_NONE,
 	VDD_DIG_LOW,
@@ -429,8 +382,7 @@
 		[VDD_DIG_NOMINAL] = 1050000,
 		[VDD_DIG_HIGH]    = 1150000
 	};
-
-	return rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S3, RPM_VREG_VOTER3,
+	return rpm_vreg_set_voltage(rpm_vreg_id_vdd_dig, RPM_VREG_VOTER3,
 				    vdd_uv[level], 1150000, 1);
 }
 
@@ -449,41 +401,54 @@
 	.fmax[VDD_DIG_##l2] = (f2), \
 	.fmax[VDD_DIG_##l3] = (f3)
 
-enum vdd_l23_levels {
-	VDD_L23_OFF,
-	VDD_L23_ON
+enum vdd_sr2_pll_levels {
+	VDD_SR2_PLL_OFF,
+	VDD_SR2_PLL_ON
 };
 
-static int set_vdd_l23(struct clk_vdd_class *vdd_class, int level)
+static int set_vdd_sr2_pll(struct clk_vdd_class *vdd_class, int level)
 {
-	int rc;
-
-	if (level == VDD_L23_OFF) {
-		rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_L23,
-				RPM_VREG_VOTER3, 0, 0, 1);
-		if (rc)
-			return rc;
-		rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S8,
-				RPM_VREG_VOTER3, 0, 0, 1);
-		if (rc)
-			rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_L23,
-				RPM_VREG_VOTER3, 1800000, 1800000, 1);
+	int rc = 0;
+	if (cpu_is_msm8960()) {
+		if (level == VDD_SR2_PLL_OFF) {
+			rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_L23,
+					RPM_VREG_VOTER3, 0, 0, 1);
+			if (rc)
+				return rc;
+			rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S8,
+					RPM_VREG_VOTER3, 0, 0, 1);
+			if (rc)
+				rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_L23,
+					RPM_VREG_VOTER3, 1800000, 1800000, 1);
+		} else {
+			rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S8,
+					RPM_VREG_VOTER3, 2200000, 2200000, 1);
+			if (rc)
+				return rc;
+			rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_L23,
+					RPM_VREG_VOTER3, 1800000, 1800000, 1);
+			if (rc)
+				rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S8,
+						RPM_VREG_VOTER3, 0, 0, 1);
+		}
 	} else {
-		rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S8,
-				RPM_VREG_VOTER3, 2200000, 2200000, 1);
-		if (rc)
-			return rc;
-		rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_L23,
-				RPM_VREG_VOTER3, 1800000, 1800000, 1);
-		if (rc)
-			rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S8,
-				RPM_VREG_VOTER3, 0, 0, 1);
+		if (level == VDD_SR2_PLL_OFF) {
+			rc = rpm_vreg_set_voltage(rpm_vreg_id_vdd_sr2_pll,
+					RPM_VREG_VOTER3, 0, 0, 1);
+			if (rc)
+				return rc;
+		} else {
+			rc = rpm_vreg_set_voltage(rpm_vreg_id_vdd_sr2_pll,
+					RPM_VREG_VOTER3, 1800000, 1800000, 1);
+			if (rc)
+				return rc;
+		}
 	}
 
 	return rc;
 }
 
-static DEFINE_VDD_CLASS(vdd_l23, set_vdd_l23);
+static DEFINE_VDD_CLASS(vdd_sr2_pll, set_vdd_sr2_pll);
 
 /*
  * Clock Descriptions
@@ -561,8 +526,8 @@
 	.c = {
 		.dbg_name = "pll3_clk",
 		.ops = &clk_ops_pll,
-		.vdd_class = &vdd_l23,
-		.fmax[VDD_L23_ON] = ULONG_MAX,
+		.vdd_class = &vdd_sr2_pll,
+		.fmax[VDD_SR2_PLL_ON] = ULONG_MAX,
 		CLK_INIT(pll3_clk.c),
 	},
 };
@@ -633,6 +598,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 = {
@@ -648,6 +614,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 = {
@@ -662,6 +629,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",
@@ -698,6 +667,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",
@@ -728,6 +699,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",
@@ -744,6 +717,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",
@@ -763,6 +738,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",
@@ -798,6 +775,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",
@@ -816,6 +795,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",
@@ -834,6 +815,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",
@@ -1204,6 +1188,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",
@@ -1330,10 +1316,10 @@
 	}
 static struct clk_freq_tbl clk_tbl_gsbi_uart[] = {
 	F_GSBI_UART(       0, gnd,  1,  0,   0),
-	F_GSBI_UART( 1843200, pll8, 1,  3, 625),
-	F_GSBI_UART( 3686400, pll8, 1,  6, 625),
-	F_GSBI_UART( 7372800, pll8, 1, 12, 625),
-	F_GSBI_UART(14745600, pll8, 1, 24, 625),
+	F_GSBI_UART( 1843200, pll8, 2,  6, 625),
+	F_GSBI_UART( 3686400, pll8, 2, 12, 625),
+	F_GSBI_UART( 7372800, pll8, 2, 24, 625),
+	F_GSBI_UART(14745600, pll8, 2, 48, 625),
 	F_GSBI_UART(16000000, pll8, 4,  1,   6),
 	F_GSBI_UART(24000000, pll8, 4,  1,   4),
 	F_GSBI_UART(32000000, pll8, 4,  1,   3),
@@ -3119,6 +3105,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),
@@ -3141,6 +3129,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),
@@ -3248,6 +3238,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),
@@ -3290,6 +3282,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),
@@ -3331,37 +3325,12 @@
 	F_GFX3D(200000000, pll2, 1,  4),
 	F_GFX3D(228571000, pll2, 2,  7),
 	F_GFX3D(266667000, pll2, 1,  3),
-	F_GFX3D(320000000, pll2, 2,  5),
-	F_END
-};
-
-static struct clk_freq_tbl clk_tbl_gfx3d_8960_v2[] = {
-	F_GFX3D(        0, gnd,  0,  0),
-	F_GFX3D( 27000000, pxo,  0,  0),
-	F_GFX3D( 48000000, pll8, 1,  8),
-	F_GFX3D( 54857000, pll8, 1,  7),
-	F_GFX3D( 64000000, pll8, 1,  6),
-	F_GFX3D( 76800000, pll8, 1,  5),
-	F_GFX3D( 96000000, pll8, 1,  4),
-	F_GFX3D(128000000, pll8, 1,  3),
-	F_GFX3D(145455000, pll2, 2, 11),
-	F_GFX3D(160000000, pll2, 1,  5),
-	F_GFX3D(177778000, pll2, 2,  9),
-	F_GFX3D(200000000, pll2, 1,  4),
-	F_GFX3D(228571000, pll2, 2,  7),
-	F_GFX3D(266667000, pll2, 1,  3),
 	F_GFX3D(300000000, pll3, 1,  4),
 	F_GFX3D(320000000, pll2, 2,  5),
 	F_GFX3D(400000000, pll2, 1,  2),
 	F_END
 };
 
-static unsigned long fmax_gfx3d_8960_v2[MAX_VDD_LEVELS] __initdata = {
-	[VDD_DIG_LOW]     = 128000000,
-	[VDD_DIG_NOMINAL] = 300000000,
-	[VDD_DIG_HIGH]    = 400000000
-};
-
 static struct clk_freq_tbl clk_tbl_gfx3d_8064[] = {
 	F_GFX3D(        0, gnd,   0,  0),
 	F_GFX3D( 27000000, pxo,   0,  0),
@@ -3414,6 +3383,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),
@@ -3424,8 +3395,8 @@
 	.c = {
 		.dbg_name = "gfx3d_clk",
 		.ops = &clk_ops_rcg_8960,
-		VDD_DIG_FMAX_MAP3(LOW,  128000000, NOMINAL, 266667000,
-				  HIGH, 320000000),
+		VDD_DIG_FMAX_MAP3(LOW,  128000000, NOMINAL, 300000000,
+				  HIGH, 400000000),
 		CLK_INIT(gfx3d_clk.c),
 		.depends = &gmem_axi_clk.c,
 	},
@@ -3534,12 +3505,6 @@
 	F_END
 };
 
-static unsigned long fmax_ijpeg_8960_v2[MAX_VDD_LEVELS] __initdata = {
-	[VDD_DIG_LOW]     = 110000000,
-	[VDD_DIG_NOMINAL] = 266667000,
-	[VDD_DIG_HIGH]    = 320000000
-};
-
 static unsigned long fmax_ijpeg_8064[MAX_VDD_LEVELS] __initdata = {
 	[VDD_DIG_LOW]     = 128000000,
 	[VDD_DIG_NOMINAL] = 266667000,
@@ -3554,6 +3519,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,
@@ -3566,7 +3533,8 @@
 	.c = {
 		.dbg_name = "ijpeg_clk",
 		.ops = &clk_ops_rcg_8960,
-		VDD_DIG_FMAX_MAP2(LOW, 110000000, NOMINAL, 266667000),
+		VDD_DIG_FMAX_MAP3(LOW, 110000000, NOMINAL, 266667000,
+				  HIGH, 320000000),
 		CLK_INIT(ijpeg_clk.c),
 		.depends = &ijpeg_axi_clk.c,
 	},
@@ -3596,6 +3564,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),
@@ -3672,6 +3642,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),
@@ -3694,6 +3666,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 = {
@@ -3780,6 +3754,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),
@@ -3890,6 +3866,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),
@@ -3946,6 +3924,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 = {
@@ -4035,6 +4015,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),
@@ -4079,6 +4061,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),
@@ -4127,12 +4111,6 @@
 	F_END
 };
 
-static unsigned long fmax_vfe_8960_v2[MAX_VDD_LEVELS] __initdata = {
-	[VDD_DIG_LOW]     = 110000000,
-	[VDD_DIG_NOMINAL] = 266667000,
-	[VDD_DIG_HIGH]    = 320000000
-};
-
 static unsigned long fmax_vfe_8064[MAX_VDD_LEVELS] __initdata = {
 	[VDD_DIG_LOW]     = 128000000,
 	[VDD_DIG_NOMINAL] = 266667000,
@@ -4147,6 +4125,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,
@@ -4159,7 +4139,8 @@
 	.c = {
 		.dbg_name = "vfe_clk",
 		.ops = &clk_ops_rcg_8960,
-		VDD_DIG_FMAX_MAP2(LOW, 110000000, NOMINAL, 266667000),
+		VDD_DIG_FMAX_MAP3(LOW, 110000000, NOMINAL, 266667000,
+				  HIGH, 320000000),
 		CLK_INIT(vfe_clk.c),
 		.depends = &vfe_axi_clk.c,
 	},
@@ -4285,7 +4266,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), \
@@ -4461,6 +4442,8 @@
 static DEFINE_CLK_MEASURE(l2_m_clk);
 static DEFINE_CLK_MEASURE(krait0_m_clk);
 static DEFINE_CLK_MEASURE(krait1_m_clk);
+static DEFINE_CLK_MEASURE(krait2_m_clk);
+static DEFINE_CLK_MEASURE(krait3_m_clk);
 static DEFINE_CLK_MEASURE(q6sw_clk);
 static DEFINE_CLK_MEASURE(q6fw_clk);
 static DEFINE_CLK_MEASURE(q6_func_clk);
@@ -4647,8 +4630,8 @@
 	{ TEST_MM_HS(0x32), &csi_rdi2_clk.c },
 	{ TEST_MM_HS(0x33), &vcap_clk.c },
 	{ TEST_MM_HS(0x34), &vcap_npl_clk.c },
-	{ TEST_MM_HS(0x36), &vcap_axi_clk.c },
-	{ TEST_MM_HS(0x39), &gfx3d_axi_clk.c },
+	{ TEST_MM_HS(0x35), &vcap_axi_clk.c },
+	{ TEST_MM_HS(0x38), &gfx3d_axi_clk.c },
 
 	{ TEST_LPA(0x0F), &mi2s_bit_clk.c },
 	{ TEST_LPA(0x10), &codec_i2s_mic_bit_clk.c },
@@ -4663,6 +4646,8 @@
 	{ TEST_CPUL2(0x2), &l2_m_clk },
 	{ TEST_CPUL2(0x0), &krait0_m_clk },
 	{ TEST_CPUL2(0x1), &krait1_m_clk },
+	{ TEST_CPUL2(0x4), &krait2_m_clk },
+	{ TEST_CPUL2(0x5), &krait3_m_clk },
 };
 
 static struct measure_sel *find_measure_sel(struct clk *clk)
@@ -4849,67 +4834,74 @@
 };
 
 static struct clk_lookup msm_clocks_8064[] = {
-	CLK_LOOKUP("cxo",		cxo_clk.c,		NULL),
-	CLK_LOOKUP("pll2",		pll2_clk.c,		NULL),
-	CLK_LOOKUP("pll8",		pll8_clk.c,		NULL),
-	CLK_LOOKUP("pll4",		pll4_clk.c,		NULL),
-	CLK_LOOKUP("measure",		measure_clk.c,		"debug"),
+	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"),
+	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_qdsp6v4.1"),
+	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_qdsp6v4.2"),
+	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_gss"),
+	CLK_LOOKUP("pll2",		pll2_clk.c,	NULL),
+	CLK_LOOKUP("pll8",		pll8_clk.c,	NULL),
+	CLK_LOOKUP("pll4",		pll4_clk.c,	NULL),
+	CLK_LOOKUP("measure",		measure_clk.c,	"debug"),
 
-	CLK_DUMMY("bus_clk",		AFAB_CLK,	"msm_apps_fab", 0),
-	CLK_DUMMY("bus_a_clk",		AFAB_A_CLK,	"msm_apps_fab", 0),
-	CLK_DUMMY("bus_clk",		SFAB_CLK,	"msm_sys_fab", 0),
-	CLK_DUMMY("bus_a_clk",		SFAB_A_CLK,	"msm_sys_fab", 0),
-	CLK_DUMMY("bus_clk",		SFPB_CLK,	"msm_sys_fpb", 0),
-	CLK_DUMMY("bus_a_clk",		SFPB_A_CLK,	"msm_sys_fpb", 0),
-	CLK_DUMMY("bus_clk",		MMFAB_CLK,	"msm_mm_fab", 0),
-	CLK_DUMMY("bus_a_clk",		MMFAB_A_CLK,	"msm_mm_fab", 0),
-	CLK_DUMMY("bus_clk",		CFPB_CLK,	"msm_cpss_fpb", 0),
-	CLK_DUMMY("bus_a_clk",		CFPB_A_CLK,	"msm_cpss_fpb", 0),
-	CLK_LOOKUP("mem_clk",		ebi1_msmbus_clk.c, "msm_bus"),
-	CLK_DUMMY("mem_a_clk",		EBI1_A_CLK,        "msm_bus", 0),
+	CLK_LOOKUP("bus_clk",		afab_clk.c,		"msm_apps_fab"),
+	CLK_LOOKUP("bus_a_clk",		afab_a_clk.c,		"msm_apps_fab"),
+	CLK_LOOKUP("bus_clk",		cfpb_clk.c,		"msm_cpss_fpb"),
+	CLK_LOOKUP("bus_a_clk",		cfpb_a_clk.c,		"msm_cpss_fpb"),
+	CLK_LOOKUP("bus_clk",		sfab_clk.c,		"msm_sys_fab"),
+	CLK_LOOKUP("bus_a_clk",		sfab_a_clk.c,		"msm_sys_fab"),
+	CLK_LOOKUP("bus_clk",		sfpb_clk.c,		"msm_sys_fpb"),
+	CLK_LOOKUP("bus_a_clk",		sfpb_a_clk.c,		"msm_sys_fpb"),
+	CLK_LOOKUP("bus_clk",		mmfab_clk.c,		"msm_mm_fab"),
+	CLK_LOOKUP("bus_a_clk",		mmfab_a_clk.c,		"msm_mm_fab"),
+	CLK_LOOKUP("mem_clk",		ebi1_msmbus_clk.c,	"msm_bus"),
+	CLK_LOOKUP("mem_a_clk",		ebi1_a_clk.c,		"msm_bus"),
 
-	CLK_DUMMY("ebi1_clk",		EBI1_CLK,	NULL, 0),
-	CLK_DUMMY("dfab_clk",		DFAB_CLK,	NULL, 0),
-	CLK_DUMMY("dfab_a_clk",		DFAB_A_CLK,	NULL, 0),
-	CLK_DUMMY("bus_clk",		MMFPB_CLK,	NULL, 0),
-	CLK_DUMMY("bus_a_clk",		MMFPB_A_CLK,	NULL, 0),
+	CLK_LOOKUP("ebi1_clk",		ebi1_clk.c,		""),
+	CLK_LOOKUP("dfab_clk",		dfab_clk.c,		""),
+	CLK_LOOKUP("dfab_a_clk",	dfab_a_clk.c,		""),
+	CLK_LOOKUP("mmfpb_clk",		mmfpb_clk.c,		""),
+	CLK_LOOKUP("mmfpb_a_clk",	mmfpb_a_clk.c,		"clock-8960"),
+	CLK_LOOKUP("cfpb_a_clk",	cfpb_a_clk.c,		"clock-8960"),
 
-	CLK_LOOKUP("core_clk",		gp0_clk.c,		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("pmem_clk",		pmem_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, "msm_serial_hsl.1"),
+	CLK_LOOKUP("core_clk",		gsbi2_uart_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi3_uart_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi4_uart_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi5_uart_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi6_uart_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi7_uart_clk.c, "msm_serial_hsl.0"),
+	CLK_LOOKUP("core_clk",		gsbi1_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi2_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi3_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi4_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi5_qup_clk.c,	"spi_qsd.0"),
+	CLK_LOOKUP("core_clk",		gsbi6_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi7_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		pdm_clk.c,		""),
+	CLK_LOOKUP("mem_clk",		pmem_clk.c,		"msm_sps"),
 	CLK_DUMMY("core_clk",           PRNG_CLK,	"msm_rng.0", OFF),
 	CLK_LOOKUP("core_clk",		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"),
@@ -4917,15 +4909,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,	"msm_serial_hsl.1"),
+	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,		"spi_qsd.0"),
+	CLK_LOOKUP("iface_clk",		gsbi6_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		gsbi7_p_clk.c,	"msm_serial_hsl.0"),
+	CLK_LOOKUP("iface_clk",		tsif_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		usb_fs1_p_clk.c,	""),
 	CLK_LOOKUP("iface_clk",		usb_hs1_p_clk.c,	"msm_otg"),
 	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"),
@@ -4933,80 +4925,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"),
@@ -5014,83 +5006,107 @@
 	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,		"msm_iommu"),
 	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("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,	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_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_SCM_CLK,	"scm", 0),
+	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_LOOKUP("dfab_dsps_clk",	dfab_dsps_clk.c, NULL),
+	CLK_LOOKUP("core_clk",		dfab_usb_hs_clk.c,	"msm_otg"),
+	CLK_LOOKUP("core_clk",		dfab_usb_hs3_clk.c, "msm_ehci_host.0"),
+	CLK_LOOKUP("core_clk",		dfab_usb_hs3_clk.c, "msm_ehci_host.1"),
+	CLK_LOOKUP("bus_clk",		dfab_sdc1_clk.c, "msm_sdcc.1"),
+	CLK_LOOKUP("bus_clk",		dfab_sdc2_clk.c, "msm_sdcc.2"),
+	CLK_LOOKUP("bus_clk",		dfab_sdc3_clk.c, "msm_sdcc.3"),
+	CLK_LOOKUP("bus_clk",		dfab_sdc4_clk.c, "msm_sdcc.4"),
+	CLK_LOOKUP("dfab_clk",		dfab_sps_clk.c,	"msm_sps"),
+	CLK_LOOKUP("bus_clk",		dfab_bam_dmux_clk.c,	"BAM_RMNT"),
+	CLK_LOOKUP("bus_clk",		dfab_scm_clk.c,	"scm"),
+
 	CLK_LOOKUP("alt_core_clk",    usb_hsic_xcvr_fs_clk.c,  "msm_hsic_host"),
 	CLK_LOOKUP("phy_clk",	      usb_hsic_hsic_clk.c,     "msm_hsic_host"),
 	CLK_LOOKUP("cal_clk",	      usb_hsic_hsio_cal_clk.c, "msm_hsic_host"),
 	CLK_LOOKUP("core_clk",	      usb_hsic_system_clk.c,   "msm_hsic_host"),
 	CLK_LOOKUP("iface_clk",	      usb_hsic_p_clk.c,        "msm_hsic_host"),
 
+	CLK_LOOKUP("core_clk",		jpegd_axi_clk.c,	"msm_iommu.0"),
+	CLK_LOOKUP("core_clk",		vpe_axi_clk.c,		"msm_iommu.1"),
+	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,		"msm_iommu.2"),
+	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,		"msm_iommu.3"),
+	CLK_LOOKUP("core_clk",		rot_axi_clk.c,		"msm_iommu.4"),
+	CLK_LOOKUP("core_clk",		ijpeg_axi_clk.c,	"msm_iommu.5"),
+	CLK_LOOKUP("core_clk",		vfe_axi_clk.c,		"msm_iommu.6"),
+	CLK_LOOKUP("core_clk",		vcodec_axi_a_clk.c,	"msm_iommu.7"),
+	CLK_LOOKUP("core_clk",		vcodec_axi_b_clk.c,	"msm_iommu.8"),
+	CLK_LOOKUP("core_clk",		gfx3d_axi_clk.c,	"msm_iommu.9"),
+	CLK_LOOKUP("core_clk",		gfx3d_axi_clk.c,	"msm_iommu.10"),
+	CLK_LOOKUP("core_clk",		vcap_axi_clk.c,		"msm_iommu.11"),
+
 	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, ""),
+	CLK_LOOKUP("krait2_mclk",	krait2_m_clk, ""),
+	CLK_LOOKUP("krait3_mclk",	krait3_m_clk, ""),
 };
 
-static struct clk_lookup msm_clocks_8960_v1[] __initdata = {
-	CLK_LOOKUP("cxo",		cxo_clk.c,		NULL),
-	CLK_LOOKUP("pll2",		pll2_clk.c,		NULL),
-	CLK_LOOKUP("pll8",		pll8_clk.c,		NULL),
-	CLK_LOOKUP("pll4",		pll4_clk.c,		NULL),
-	CLK_LOOKUP("measure",		measure_clk.c,		"debug"),
+static struct clk_lookup msm_clocks_8960[] = {
+	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"),
+	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_qdsp6v4.1"),
+	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_qdsp6v4.2"),
+	CLK_LOOKUP("pll2",		pll2_clk.c,	NULL),
+	CLK_LOOKUP("pll8",		pll8_clk.c,	NULL),
+	CLK_LOOKUP("pll4",		pll4_clk.c,	NULL),
+	CLK_LOOKUP("measure",		measure_clk.c,	"debug"),
 
 	CLK_LOOKUP("bus_clk",		afab_clk.c,		"msm_apps_fab"),
 	CLK_LOOKUP("bus_a_clk",		afab_a_clk.c,		"msm_apps_fab"),
@@ -5112,34 +5128,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"),
@@ -5148,36 +5164,41 @@
 	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("alt_core_clk",    usb_hsic_xcvr_fs_clk.c,  "msm_hsic_host"),
+	CLK_LOOKUP("phy_clk",	      usb_hsic_hsic_clk.c,     "msm_hsic_host"),
+	CLK_LOOKUP("cal_clk",	      usb_hsic_hsio_cal_clk.c, "msm_hsic_host"),
+	CLK_LOOKUP("core_clk",	      usb_hsic_system_clk.c,   "msm_hsic_host"),
+	CLK_LOOKUP("iface_clk",	      usb_hsic_p_clk.c,        "msm_hsic_host"),
 	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"),
@@ -5186,14 +5207,16 @@
 	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"),
+	CLK_LOOKUP("cam_clk",		cam2_clk.c,		NULL),
+	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-0020"),
 	CLK_LOOKUP("csi_src_clk",	csi0_src_clk.c,		"msm_csid.0"),
 	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		"msm_csid.1"),
 	CLK_LOOKUP("csi_clk",		csi0_clk.c,		"msm_csid.0"),
@@ -5202,6 +5225,13 @@
 	CLK_LOOKUP("csi_phy_clk",	csi1_phy_clk.c,		"msm_csid.1"),
 	CLK_LOOKUP("csi_pix_clk",	csi_pix_clk.c,		"msm_ispif.0"),
 	CLK_LOOKUP("csi_rdi_clk",	csi_rdi_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csi_src_clk",	csi2_src_clk.c,		NULL),
+	CLK_LOOKUP("csi_clk",		csi2_clk.c,		NULL),
+	CLK_LOOKUP("csi_pix1_clk",	csi_pix1_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csi_rdi1_clk",	csi_rdi1_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csi_rdi2_clk",	csi_rdi2_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csi_phy_clk",	csi2_phy_clk.c,		NULL),
+	CLK_LOOKUP("csi2phy_timer_clk",	csi2phy_timer_clk.c,	NULL),
 	CLK_LOOKUP("csiphy_timer_src_clk",
 			   csiphy_timer_src_clk.c, "msm_csiphy.0"),
 	CLK_LOOKUP("csiphy_timer_src_clk",
@@ -5219,10 +5249,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),
@@ -5270,8 +5300,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"),
@@ -5329,34 +5359,14 @@
 
 	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 = {
-	CLK_LOOKUP("cam_clk",		cam2_clk.c,		NULL),
-	CLK_LOOKUP("csi_src_clk",	csi2_src_clk.c,		NULL),
-	CLK_LOOKUP("csi_clk",		csi2_clk.c,		NULL),
-	CLK_LOOKUP("csi_pix1_clk",	csi_pix1_clk.c,		"msm_ispif.0"),
-	CLK_LOOKUP("csi_rdi1_clk",	csi_rdi1_clk.c,		"msm_ispif.0"),
-	CLK_LOOKUP("csi_rdi2_clk",	csi_rdi2_clk.c,		"msm_ispif.0"),
-	CLK_LOOKUP("csi_phy_clk",	csi2_phy_clk.c,		NULL),
-	CLK_LOOKUP("csi2phy_timer_clk",	csi2phy_timer_clk.c,	NULL),
-	CLK_LOOKUP("alt_core_clk",    usb_hsic_xcvr_fs_clk.c,  "msm_hsic_host"),
-	CLK_LOOKUP("phy_clk",	      usb_hsic_hsic_clk.c,     "msm_hsic_host"),
-	CLK_LOOKUP("cal_clk",	      usb_hsic_hsio_cal_clk.c, "msm_hsic_host"),
-	CLK_LOOKUP("core_clk",	      usb_hsic_system_clk.c,   "msm_hsic_host"),
-	CLK_LOOKUP("iface_clk",	      usb_hsic_p_clk.c,        "msm_hsic_host"),
-};
-
-/* Add v2 clocks dynamically at runtime */
-static struct clk_lookup msm_clocks_8960[ARRAY_SIZE(msm_clocks_8960_v1) +
-					 ARRAY_SIZE(msm_clocks_8960_v2)];
-
 /*
  * Miscellaneous clock register initializations
  */
@@ -5406,13 +5416,12 @@
 	 */
 	/*
 	 * Initialize MM AHB registers: Enable the FPB clock and disable HW
-	 * gating on 8960v1/8064 for all clocks. Also set VFE_AHB's
+	 * gating on non-8960 for all clocks. Also set VFE_AHB's
 	 * FORCE_CORE_ON bit to prevent its memory from being collapsed when
 	 * the clock is halted. The sleep and wake-up delays are set to safe
 	 * values.
 	 */
-	if (cpu_is_msm8960() &&
-			SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2) {
+	if (cpu_is_msm8960()) {
 		rmwreg(0x44000000, AHB_EN_REG,  0x6C000103);
 		writel_relaxed(0x3C7097F9, AHB_EN2_REG);
 	} else {
@@ -5442,8 +5451,7 @@
 	rmwreg(0x0027FCFF, MAXI_EN3_REG, 0x003FFFFF);
 	if (cpu_is_apq8064())
 		rmwreg(0x009FE4FF, MAXI_EN5_REG, 0x01FFEFFF);
-	if (cpu_is_msm8960() &&
-			SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2)
+	if (cpu_is_msm8960())
 		rmwreg(0x00003C38, SAXI_EN_REG,  0x00003FFF);
 	else
 		rmwreg(0x000003C7, SAXI_EN_REG,  0x00003FFF);
@@ -5536,125 +5544,34 @@
 	 *       after bootloaders program them.
 	 */
 	if (cpu_is_apq8064()) {
-		u32 regval, is_pll_enabled;
+		u32 is_pll_enabled;
 
 		/* Program pxo_src_clk to source from PXO */
 		rmwreg(0x1, PXO_SRC_CLK_CTL_REG, 0x7);
 
-		/* Check if PLL8 is active */
-		is_pll_enabled = readl_relaxed(BB_PLL8_STATUS_REG) & BIT(16);
-		if (!is_pll_enabled) {
-			/* Ref clk = 27MHz and program pll8 to 384MHz */
-			writel_relaxed(0xE, BB_PLL8_L_VAL_REG);
-			writel_relaxed(0x2, BB_PLL8_M_VAL_REG);
-			writel_relaxed(0x9, BB_PLL8_N_VAL_REG);
-
-			regval = readl_relaxed(BB_PLL8_CONFIG_REG);
-
-			/* Enable the main output and the MN accumulator */
-			regval |= BIT(23) | BIT(22);
-
-			/* Set pre-divider and post-divider values to 1 and 1 */
-			regval &= ~BIT(19);
-			regval &= ~BM(21, 20);
-
-			writel_relaxed(regval, BB_PLL8_CONFIG_REG);
-
-			/* Set VCO frequency */
-			rmwreg(0x10000, BB_PLL8_CONFIG_REG, 0x30000);
-
-			/* Enable AUX output */
-			regval = readl_relaxed(BB_PLL8_TEST_CTL_REG);
-			regval |= BIT(12);
-			writel_relaxed(regval, BB_PLL8_TEST_CTL_REG);
-
-			set_fsm_mode(BB_PLL8_MODE_REG);
-		}
-		/* Check if PLL3 is active */
-		is_pll_enabled = readl_relaxed(GPLL1_STATUS_REG) & BIT(16);
-		if (!is_pll_enabled) {
-			/* Ref clk = 27MHz and program pll3 to 1200MHz */
-			writel_relaxed(0x2C, GPLL1_L_VAL_REG);
-			writel_relaxed(0x4,  GPLL1_M_VAL_REG);
-			writel_relaxed(0x9,  GPLL1_N_VAL_REG);
-
-			regval = readl_relaxed(GPLL1_CONFIG_REG);
-
-			/* Set pre-divider and post-divider values to 1 and 1 */
-			regval &= ~BIT(15);
-			regval |= BIT(16);
-
-			writel_relaxed(regval, GPLL1_CONFIG_REG);
-
-			/* Set VCO frequency */
-			rmwreg(0x180, GPLL1_CONFIG_REG, 0x180);
-		}
 		/* Check if PLL14 is active */
 		is_pll_enabled = readl_relaxed(BB_PLL14_STATUS_REG) & BIT(16);
 		if (!is_pll_enabled) {
 			/* Ref clk = 27MHz and program pll14 to 480MHz */
-			writel_relaxed(0x11, BB_PLL14_L_VAL_REG);
+			writel_relaxed(0x00031011, BB_PLL14_L_VAL_REG);
 			writel_relaxed(0x7,  BB_PLL14_M_VAL_REG);
 			writel_relaxed(0x9,  BB_PLL14_N_VAL_REG);
 
-			regval = readl_relaxed(BB_PLL14_CONFIG_REG);
-
-			/* Enable the main output and the MN accumulator */
-			regval |= BIT(23) | BIT(22);
-
-			/* Set pre-divider and post-divider values to 1 and 1 */
-			regval &= ~BIT(19);
-			regval &= ~BM(21, 20);
-
-			writel_relaxed(regval, BB_PLL14_CONFIG_REG);
-
-			/* Set VCO frequency */
-			rmwreg(0x10000, BB_PLL14_CONFIG_REG, 0x30000);
+			/*
+			 * Enable the main output and the MN accumulator
+			 * Set pre-divider and post-divider values to 1 and 1
+			 */
+			writel_relaxed(0x00C00000, BB_PLL14_CONFIG_REG);
 
 			set_fsm_mode(BB_PLL14_MODE_REG);
 		}
-		/* Program PLL2 to 800MHz with ref clk = 27MHz */
-		writel_relaxed(0x1D, MM_PLL1_L_VAL_REG);
-		writel_relaxed(0x11, MM_PLL1_M_VAL_REG);
-		writel_relaxed(0x1B, MM_PLL1_N_VAL_REG);
-
-		regval = readl_relaxed(MM_PLL1_CONFIG_REG);
-
-		/* Enable the main output and the MN accumulator */
-		regval |= BIT(23) | BIT(22);
-
-		/* Set pre-divider and post-divider values to 1 and 1 */
-		regval &= ~BIT(19);
-		regval &= ~BM(21, 20);
-
-		writel_relaxed(regval, MM_PLL1_CONFIG_REG);
-
-		/* Set VCO frequency */
-		rmwreg(0x20000, MM_PLL1_CONFIG_REG, 0x30000);
 
 		/* Program PLL15 to 975MHz with ref clk = 27MHz */
-		writel_relaxed(0x24, MM_PLL3_L_VAL_REG);
-		writel_relaxed(0x1,  MM_PLL3_M_VAL_REG);
-		writel_relaxed(0x9,  MM_PLL3_N_VAL_REG);
+		writel_relaxed(0x31024, MM_PLL3_L_VAL_REG);
+		writel_relaxed(0x1,	MM_PLL3_M_VAL_REG);
+		writel_relaxed(0x9,	MM_PLL3_N_VAL_REG);
 
-		regval = readl_relaxed(MM_PLL3_CONFIG_REG);
-
-		/* Enable the main output and the MN accumulator */
-		regval |= BIT(23) | BIT(22);
-
-		/* Set pre-divider and post-divider values to 1 and 1 */
-		regval &= ~BIT(19);
-		regval &= ~BM(21, 20);
-
-		writel_relaxed(regval, MM_PLL3_CONFIG_REG);
-
-		/* Set VCO frequency */
-		rmwreg(0x20000, MM_PLL3_CONFIG_REG, 0x30000);
-
-		/* Enable AUX output */
-		regval = readl_relaxed(MM_PLL3_TEST_CTL_REG);
-		regval |= BIT(12);
-		writel_relaxed(regval, MM_PLL3_TEST_CTL_REG);
+		writel_relaxed(0xC20000, MM_PLL3_CONFIG_REG);
 
 		/* Check if PLL4 is active */
 		is_pll_enabled = readl_relaxed(LCC_PLL0_STATUS_REG) & BIT(16);
@@ -5664,18 +5581,7 @@
 			writel_relaxed(0x27A, LCC_PLL0_M_VAL_REG);
 			writel_relaxed(0x465, LCC_PLL0_N_VAL_REG);
 
-			regval = readl_relaxed(LCC_PLL0_CONFIG_REG);
-
-			/* Enable the main output and the MN accumulator */
-			regval |= BIT(23) | BIT(22);
-
-			/* Set pre-divider and post-divider values to 1 and 1 */
-			regval &= ~BIT(19);
-			regval &= ~BM(21, 20);
-
-			/* Set VCO frequency */
-			regval &= ~BM(17, 16);
-			writel_relaxed(regval, LCC_PLL0_CONFIG_REG);
+			writel_relaxed(0xC00000, LCC_PLL0_CONFIG_REG);
 
 			set_fsm_mode(LCC_PLL0_MODE_REG);
 		}
@@ -5685,12 +5591,21 @@
 	}
 }
 
-struct clock_init_data msm8960_clock_init_data __initdata;
-
 /* Local clock driver initialization. */
 static void __init msm8960_clock_init(void)
 {
-	size_t num_lookups = ARRAY_SIZE(msm_clocks_8960_v1);
+
+	if (cpu_is_msm8960()) {
+		rpm_vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3;
+	} else if (cpu_is_apq8064()) {
+		rpm_vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3;
+		rpm_vreg_id_vdd_sr2_pll = RPM_VREG_ID_PM8921_LVS7;
+	} else if (cpu_is_msm8930() || cpu_is_msm8627()) {
+		rpm_vreg_id_vdd_dig = RPM_VREG_ID_PM8038_S1;
+		rpm_vreg_id_vdd_sr2_pll = RPM_VREG_ID_PM8038_L23;
+	} else {
+		BUG();
+	}
 
 	xo_pxo = msm_xo_get(MSM_XO_PXO, "clock-8960");
 	if (IS_ERR(xo_pxo)) {
@@ -5703,26 +5618,6 @@
 		BUG();
 	}
 
-	if (cpu_is_msm8960() || cpu_is_msm8930()) {
-		memcpy(msm_clocks_8960, msm_clocks_8960_v1,
-				sizeof(msm_clocks_8960_v1));
-		if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2) {
-			gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8960_v2;
-
-			memcpy(gfx3d_clk.c.fmax, fmax_gfx3d_8960_v2,
-			       sizeof(gfx3d_clk.c.fmax));
-			memcpy(ijpeg_clk.c.fmax, fmax_ijpeg_8960_v2,
-			       sizeof(ijpeg_clk.c.fmax));
-			memcpy(vfe_clk.c.fmax, fmax_vfe_8960_v2,
-			       sizeof(vfe_clk.c.fmax));
-
-			memcpy(msm_clocks_8960 + ARRAY_SIZE(msm_clocks_8960_v1),
-				msm_clocks_8960_v2, sizeof(msm_clocks_8960_v2));
-			num_lookups = ARRAY_SIZE(msm_clocks_8960);
-		}
-		msm8960_clock_init_data.size = num_lookups;
-	}
-
 	/*
 	 * Change the freq tables for and voltage requirements for
 	 * clocks which differ between 8960 and 8064.
@@ -5784,22 +5679,8 @@
 	rcg_clk_disable(&pdm_clk.c);
 	rcg_clk_enable(&tssc_clk.c);
 	rcg_clk_disable(&tssc_clk.c);
-	if (cpu_is_msm8960() &&
-			SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2) {
-		clk_enable(&usb_hsic_hsic_clk.c);
-		clk_disable(&usb_hsic_hsic_clk.c);
-	} 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);
-	}
+	clk_enable(&usb_hsic_hsic_clk.c);
+	clk_disable(&usb_hsic_hsic_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 d61547fa..043cdbc 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -262,58 +262,6 @@
 /*
  * Clock frequency definitions and macros
  */
-#define MN_MODE_DUAL_EDGE 0x2
-
-/* MD Registers */
-#define MD4(m_lsb, m, n_lsb, n) \
-		(BVAL((m_lsb+3), m_lsb, m) | BVAL((n_lsb+3), n_lsb, ~(n)))
-#define MD8(m_lsb, m, n_lsb, n) \
-		(BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n)))
-#define MD16(m, n) (BVAL(31, 16, m) | BVAL(15, 0, ~(n)))
-
-/* NS Registers */
-#define NS(n_msb, n_lsb, n, m, mde_lsb, d_msb, d_lsb, d, s_msb, s_lsb, s) \
-		(BVAL(n_msb, n_lsb, ~(n-m)) \
-		| (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n)) \
-		| BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
-
-#define NS_MM(n_msb, n_lsb, n, m, d_msb, d_lsb, d, s_msb, s_lsb, s) \
-		(BVAL(n_msb, n_lsb, ~(n-m)) | BVAL(d_msb, d_lsb, (d-1)) \
-		| BVAL(s_msb, s_lsb, s))
-
-#define NS_DIVSRC(d_msb , d_lsb, d, s_msb, s_lsb, s) \
-		(BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
-
-#define NS_DIV(d_msb , d_lsb, d) \
-		BVAL(d_msb, d_lsb, (d-1))
-
-#define NS_SRC_SEL(s_msb, s_lsb, s) \
-		BVAL(s_msb, s_lsb, s)
-
-#define NS_MND_BANKED4(n0_lsb, n1_lsb, n, m, s0_lsb, s1_lsb, s) \
-		 (BVAL((n0_lsb+3), n0_lsb, ~(n-m)) \
-		| BVAL((n1_lsb+3), n1_lsb, ~(n-m)) \
-		| BVAL((s0_lsb+2), s0_lsb, s) \
-		| BVAL((s1_lsb+2), s1_lsb, s))
-
-#define NS_MND_BANKED8(n0_lsb, n1_lsb, n, m, s0_lsb, s1_lsb, s) \
-		 (BVAL((n0_lsb+7), n0_lsb, ~(n-m)) \
-		| BVAL((n1_lsb+7), n1_lsb, ~(n-m)) \
-		| BVAL((s0_lsb+2), s0_lsb, s) \
-		| BVAL((s1_lsb+2), s1_lsb, s))
-
-#define NS_DIVSRC_BANKED(d0_msb, d0_lsb, d1_msb, d1_lsb, d, \
-	s0_msb, s0_lsb, s1_msb, s1_lsb, s) \
-		 (BVAL(d0_msb, d0_lsb, (d-1)) | BVAL(d1_msb, d1_lsb, (d-1)) \
-		| BVAL(s0_msb, s0_lsb, s) \
-		| BVAL(s1_msb, s1_lsb, s))
-
-/* CC Registers */
-#define CC(mde_lsb, n) (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n))
-#define CC_BANKED(mde0_lsb, mde1_lsb, n) \
-		((BVAL((mde0_lsb+1), mde0_lsb, MN_MODE_DUAL_EDGE) \
-		| BVAL((mde1_lsb+1), mde1_lsb, MN_MODE_DUAL_EDGE)) \
-		* !!(n))
 
 enum vdd_dig_levels {
 	VDD_DIG_NONE,
@@ -548,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 = {
@@ -559,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 = {
@@ -609,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",
@@ -639,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",
@@ -1019,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",
@@ -2206,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),
@@ -2286,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),
@@ -2328,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),
@@ -2398,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),
@@ -2446,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,
@@ -2488,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),
@@ -2558,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),
@@ -2643,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)),
@@ -2716,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),
@@ -2765,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),
@@ -2893,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,
@@ -2940,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),
@@ -2995,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,
@@ -3572,6 +3554,7 @@
 
 static struct clk_lookup msm_clocks_8x60[] = {
 	CLK_LOOKUP("cxo",		cxo_clk.c,	NULL),
+	CLK_LOOKUP("xo",		pxo_clk.c,	"pil_modem"),
 	CLK_LOOKUP("pll4",		pll4_clk.c,	"pil_qdsp6v3"),
 	CLK_LOOKUP("measure",		measure_clk.c,	"debug"),
 
@@ -3596,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"),
@@ -3634,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"),
@@ -3799,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 3e57ebc..98d9cb2 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -174,22 +174,6 @@
 #define TEST_LPA(s)		TEST_VECTOR((s), TEST_TYPE_LPA)
 #define TEST_LPA_HS(s)		TEST_VECTOR((s), TEST_TYPE_LPA_HS)
 
-#define MN_MODE_DUAL_EDGE 0x2
-
-/* MD Registers */
-#define MD8(m_lsb, m, n_lsb, n) \
-		(BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n)))
-#define MD16(m, n) (BVAL(31, 16, m) | BVAL(15, 0, ~(n)))
-
-/* NS Registers */
-#define NS(n_msb, n_lsb, n, m, mde_lsb, d_msb, d_lsb, d, s_msb, s_lsb, s) \
-		(BVAL(n_msb, n_lsb, ~(n-m)) \
-		| (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n)) \
-		| BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
-
-#define NS_SRC_SEL(s_msb, s_lsb, s) \
-		BVAL(s_msb, s_lsb, s)
-
 enum vdd_dig_levels {
 	VDD_DIG_NONE,
 	VDD_DIG_LOW,
@@ -499,9 +483,9 @@
 	}
 static struct clk_freq_tbl clk_tbl_gsbi_uart[] = {
 	F_GSBI_UART(       0, gnd,  1,  0,   0),
-	F_GSBI_UART( 3686400, pll8, 1,  6, 625),
-	F_GSBI_UART( 7372800, pll8, 1, 12, 625),
-	F_GSBI_UART(14745600, pll8, 1, 24, 625),
+	F_GSBI_UART( 3686400, pll8, 2, 12, 625),
+	F_GSBI_UART( 7372800, pll8, 2, 24, 625),
+	F_GSBI_UART(14745600, pll8, 2, 48, 625),
 	F_GSBI_UART(16000000, pll8, 4,  1,   6),
 	F_GSBI_UART(24000000, pll8, 4,  1,   4),
 	F_GSBI_UART(32000000, pll8, 4,  1,   3),
@@ -1217,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), \
@@ -1614,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),
@@ -1638,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"),
@@ -1681,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-dss-8960.c b/arch/arm/mach-msm/clock-dss-8960.c
index 7374f92..8331899 100644
--- a/arch/arm/mach-msm/clock-dss-8960.c
+++ b/arch/arm/mach-msm/clock-dss-8960.c
@@ -102,16 +102,38 @@
 	ahb_enabled = ahb_en_reg & BIT(4);
 	if (!ahb_enabled) {
 		writel_relaxed(ahb_en_reg | BIT(4), AHB_EN_REG);
+		/* Make sure iface clock is enabled before register access */
 		mb();
 	}
 
+	/* Assert PLL S/W reset */
+	writel_relaxed(0x8D, HDMI_PHY_PLL_LOCKDET_CFG2);
+	writel_relaxed(0x10, HDMI_PHY_PLL_LOCKDET_CFG0);
+	writel_relaxed(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1);
+	/* De-assert PLL S/W reset */
+	writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
+
+	val = readl_relaxed(HDMI_PHY_REG_12);
+	val |= BIT(5);
+	/* Assert PHY S/W reset */
+	writel_relaxed(val, HDMI_PHY_REG_12);
+	val &= ~BIT(5);
+	/* De-assert PHY S/W reset */
+	writel_relaxed(val, HDMI_PHY_REG_12);
+	writel_relaxed(0x3f, HDMI_PHY_REG_2);
+
+	val = readl_relaxed(HDMI_PHY_REG_12);
+	val |= PWRDN_B;
+	writel_relaxed(val, HDMI_PHY_REG_12);
+	/* Wait 10 us for enabling global power for PHY */
+	mb();
+	udelay(10);
+
 	val = readl_relaxed(HDMI_PHY_PLL_PWRDN_B);
 	val |= PLL_PWRDN_B;
-	writel_relaxed(val, HDMI_PHY_PLL_PWRDN_B);
-	mb();
 	val &= ~PD_PLL;
 	writel_relaxed(val, HDMI_PHY_PLL_PWRDN_B);
-	mb();
+	writel_relaxed(0x80, HDMI_PHY_REG_2);
 
 	while (!(readl_relaxed(HDMI_PHY_PLL_STATUS0) & BIT(0)))
 		cpu_relax();
@@ -134,13 +156,15 @@
 		mb();
 	}
 
+	val = readl_relaxed(HDMI_PHY_REG_12);
+	val &= (~PWRDN_B);
+	writel_relaxed(val, HDMI_PHY_REG_12);
+
 	val = readl_relaxed(HDMI_PHY_PLL_PWRDN_B);
 	val |= PD_PLL;
+	val &= (~PLL_PWRDN_B);
 	writel_relaxed(val, HDMI_PHY_PLL_PWRDN_B);
-	mb();
-
-	val = val & (~PLL_PWRDN_B);
-	writel_relaxed(val, HDMI_PHY_PLL_PWRDN_B);
+	/* Make sure HDMI PHY/PLL are powered down */
 	mb();
 
 	if (!ahb_enabled)
@@ -156,25 +180,15 @@
 int hdmi_pll_set_rate(unsigned rate)
 {
 	unsigned int set_power_dwn = 0;
-	unsigned int val;
 	u32 ahb_en_reg = readl_relaxed(AHB_EN_REG);
 	u32 ahb_enabled = ahb_en_reg & BIT(4);
 
 	if (!ahb_enabled) {
 		writel_relaxed(ahb_en_reg | BIT(4), AHB_EN_REG);
+		/* Make sure iface clock is enabled before register access */
 		mb();
 	}
 
-	writel_relaxed(0x7f, HDMI_PHY_REG_2);
-	writel_relaxed(0x3f, HDMI_PHY_REG_2);
-	writel_relaxed(0x1f, HDMI_PHY_REG_2);
-
-	val = readl_relaxed(HDMI_PHY_REG_12);
-	val |= PWRDN_B;
-	writel_relaxed(val, HDMI_PHY_REG_12);
-	mb();
-
-	writel_relaxed(0x81, HDMI_PHY_REG_2);
 	if (hdmi_pll_on) {
 		hdmi_pll_disable();
 		set_power_dwn = 1;
@@ -198,9 +212,6 @@
 		writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG1);
 		writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG2);
 		writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG3);
-		writel_relaxed(0x10, HDMI_PHY_PLL_LOCKDET_CFG0);
-		writel_relaxed(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1);
-		writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
 		writel_relaxed(0x2A, HDMI_PHY_PLL_VCOCAL_CFG0);
 		writel_relaxed(0x03, HDMI_PHY_PLL_VCOCAL_CFG1);
 		writel_relaxed(0x2B, HDMI_PHY_PLL_VCOCAL_CFG2);
@@ -228,9 +239,6 @@
 		writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG1);
 		writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG2);
 		writel_relaxed(0x20, HDMI_PHY_PLL_SSC_CFG3);
-		writel_relaxed(0x10, HDMI_PHY_PLL_LOCKDET_CFG0);
-		writel_relaxed(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1);
-		writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
 		writel_relaxed(0xF4, HDMI_PHY_PLL_VCOCAL_CFG0);
 		writel_relaxed(0x02, HDMI_PHY_PLL_VCOCAL_CFG1);
 		writel_relaxed(0x2B, HDMI_PHY_PLL_VCOCAL_CFG2);
@@ -258,9 +266,6 @@
 		writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG1);
 		writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG2);
 		writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG3);
-		writel_relaxed(0x10, HDMI_PHY_PLL_LOCKDET_CFG0);
-		writel_relaxed(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1);
-		writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
 		writel_relaxed(0x2a, HDMI_PHY_PLL_VCOCAL_CFG0);
 		writel_relaxed(0x03, HDMI_PHY_PLL_VCOCAL_CFG1);
 		writel_relaxed(0x2B, HDMI_PHY_PLL_VCOCAL_CFG2);
@@ -300,9 +305,6 @@
 		writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG1);
 		writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG2);
 		writel_relaxed(0x00, HDMI_PHY_PLL_SSC_CFG3);
-		writel_relaxed(0x10, HDMI_PHY_PLL_LOCKDET_CFG0);
-		writel_relaxed(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1);
-		writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
 		writel_relaxed(0xe6, HDMI_PHY_PLL_VCOCAL_CFG0);
 		writel_relaxed(0x02, HDMI_PHY_PLL_VCOCAL_CFG1);
 		writel_relaxed(0x2B, HDMI_PHY_PLL_VCOCAL_CFG2);
@@ -311,10 +313,10 @@
 		writel_relaxed(0x00, HDMI_PHY_PLL_VCOCAL_CFG5);
 		writel_relaxed(0x33, HDMI_PHY_PLL_VCOCAL_CFG6);
 		writel_relaxed(0x00, HDMI_PHY_PLL_VCOCAL_CFG7);
-		writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
 	break;
 	}
 
+	/* Make sure writes complete before disabling iface clock */
 	mb();
 
 	if (set_power_dwn)
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 2a1c013..c02c6f3 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -454,12 +454,20 @@
  * Frequency-related functions
  */
 
-/* Set a clock's frequency. */
-static int _rcg_clk_set_rate(struct rcg_clk *clk, struct clk_freq_tbl *nf)
+/* Set a clock to an exact rate. */
+int rcg_clk_set_rate(struct clk *c, unsigned long rate)
 {
-	struct clk_freq_tbl *cf;
-	int rc = 0;
+	struct rcg_clk *clk = to_rcg_clk(c);
+	struct clk_freq_tbl *nf, *cf;
 	struct clk *chld;
+	int rc = 0;
+
+	for (nf = clk->freq_tbl; nf->freq_hz != FREQ_END
+			&& nf->freq_hz != rate; nf++)
+		;
+
+	if (nf->freq_hz == FREQ_END)
+		return -EINVAL;
 
 	/* Check if frequency is actually changed. */
 	cf = clk->current_freq;
@@ -523,22 +531,6 @@
 	return rc;
 }
 
-/* Set a clock to an exact rate. */
-int rcg_clk_set_rate(struct clk *c, unsigned long rate)
-{
-	struct rcg_clk *clk = to_rcg_clk(c);
-	struct clk_freq_tbl *nf;
-
-	for (nf = clk->freq_tbl; nf->freq_hz != FREQ_END
-			&& nf->freq_hz != rate; nf++)
-		;
-
-	if (nf->freq_hz == FREQ_END)
-		return -EINVAL;
-
-	return _rcg_clk_set_rate(clk, nf);
-}
-
 /* Get the currently-set rate of a clock in Hz. */
 unsigned long rcg_clk_get_rate(struct clk *c)
 {
@@ -639,7 +631,8 @@
 			bank_info = &bank_masks->bank1_mask;
 
 		ns_mask = bank_info->ns_mask;
-		md_val = readl_relaxed(bank_info->md_reg);
+		md_val = bank_info->md_reg ?
+				readl_relaxed(bank_info->md_reg) : 0;
 	} else {
 		ns_mask = clk->ns_mask;
 		md_val = clk->md_reg ? readl_relaxed(clk->md_reg) : 0;
@@ -648,7 +641,7 @@
 	ns_val = readl_relaxed(clk->ns_reg) & ns_mask;
 	for (freq = clk->freq_tbl; freq->freq_hz != FREQ_END; freq++) {
 		if ((freq->ns_val & ns_mask) == ns_val &&
-		    (freq->mnd_en_mask || freq->md_val == md_val)) {
+		    (!freq->mnd_en_mask || freq->md_val == md_val)) {
 			pr_info("%s rate=%d\n", clk->c.dbg_name, freq->freq_hz);
 			break;
 		}
@@ -931,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);
@@ -955,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 a561802d..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
@@ -23,6 +23,59 @@
 #define BM(msb, lsb)	(((((uint32_t)-1) << (31-msb)) >> (31-msb+lsb)) << lsb)
 #define BVAL(msb, lsb, val)	(((val) << lsb) & BM(msb, lsb))
 
+#define MN_MODE_DUAL_EDGE 0x2
+
+/* MD Registers */
+#define MD4(m_lsb, m, n_lsb, n) \
+		(BVAL((m_lsb+3), m_lsb, m) | BVAL((n_lsb+3), n_lsb, ~(n)))
+#define MD8(m_lsb, m, n_lsb, n) \
+		(BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n)))
+#define MD16(m, n) (BVAL(31, 16, m) | BVAL(15, 0, ~(n)))
+
+/* NS Registers */
+#define NS(n_msb, n_lsb, n, m, mde_lsb, d_msb, d_lsb, d, s_msb, s_lsb, s) \
+		(BVAL(n_msb, n_lsb, ~(n-m) * !!(n)) \
+		| (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n)) \
+		| BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
+
+#define NS_MM(n_msb, n_lsb, n, m, d_msb, d_lsb, d, s_msb, s_lsb, s) \
+		(BVAL(n_msb, n_lsb, ~(n-m) * !!(n))|BVAL(d_msb, d_lsb, (d-1)) \
+		| BVAL(s_msb, s_lsb, s))
+
+#define NS_DIVSRC(d_msb, d_lsb, d, s_msb, s_lsb, s) \
+		(BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
+
+#define NS_DIV(d_msb, d_lsb, d) \
+		BVAL(d_msb, d_lsb, (d-1))
+
+#define NS_SRC_SEL(s_msb, s_lsb, s) \
+		BVAL(s_msb, s_lsb, s)
+
+#define NS_MND_BANKED4(n0_lsb, n1_lsb, n, m, s0_lsb, s1_lsb, s) \
+		 (BVAL((n0_lsb+3), n0_lsb, ~(n-m) * !!(n)) \
+		| BVAL((n1_lsb+3), n1_lsb, ~(n-m) * !!(n)) \
+		| BVAL((s0_lsb+2), s0_lsb, s) \
+		| BVAL((s1_lsb+2), s1_lsb, s))
+
+#define NS_MND_BANKED8(n0_lsb, n1_lsb, n, m, s0_lsb, s1_lsb, s) \
+		 (BVAL((n0_lsb+7), n0_lsb, ~(n-m) * !!(n)) \
+		| BVAL((n1_lsb+7), n1_lsb, ~(n-m) * !!(n)) \
+		| BVAL((s0_lsb+2), s0_lsb, s) \
+		| BVAL((s1_lsb+2), s1_lsb, s))
+
+#define NS_DIVSRC_BANKED(d0_msb, d0_lsb, d1_msb, d1_lsb, d, \
+	s0_msb, s0_lsb, s1_msb, s1_lsb, s) \
+		 (BVAL(d0_msb, d0_lsb, (d-1)) | BVAL(d1_msb, d1_lsb, (d-1)) \
+		| BVAL(s0_msb, s0_lsb, s) \
+		| BVAL(s1_msb, s1_lsb, s))
+
+/* CC Registers */
+#define CC(mde_lsb, n) (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n))
+#define CC_BANKED(mde0_lsb, mde1_lsb, n) \
+		((BVAL((mde0_lsb+1), mde0_lsb, MN_MODE_DUAL_EDGE) \
+		| BVAL((mde1_lsb+1), mde1_lsb, MN_MODE_DUAL_EDGE)) \
+		* !!(n))
+
 /*
  * Halt/Status Checking Mode Macros
  */
@@ -111,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
@@ -160,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 7a3f49e..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"),
@@ -273,6 +273,12 @@
 	CLK_LOOKUP("csi_clk",		csi1_clk.c,	NULL),
 	CLK_LOOKUP("csi_pclk",		csi1_p_clk.c,	NULL),
 	CLK_LOOKUP("csi_vfe_clk",	csi1_vfe_clk.c,	NULL),
+	CLK_LOOKUP("csi_clk",		csi0_clk.c,	"msm_csic.0"),
+	CLK_LOOKUP("csi_pclk",		csi0_p_clk.c,   "msm_csic.0"),
+	CLK_LOOKUP("csi_vfe_clk",	csi0_vfe_clk.c,	"msm_csic.0"),
+	CLK_LOOKUP("csi_clk",		csi1_clk.c,	"msm_csic.1"),
+	CLK_LOOKUP("csi_pclk",		csi1_p_clk.c,	"msm_csic.1"),
+	CLK_LOOKUP("csi_vfe_clk",	csi1_vfe_clk.c,	"msm_csic.1"),
 	CLK_LOOKUP("dsi_byte_clk",	dsi_byte_clk.c,	NULL),
 	CLK_LOOKUP("dsi_clk",		dsi_clk.c,	NULL),
 	CLK_LOOKUP("dsi_esc_clk",	dsi_esc_clk.c,	NULL),
@@ -281,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"),
@@ -324,6 +330,7 @@
 	CLK_LOOKUP("vdc_clk",		vdc_clk.c,	NULL),
 	CLK_LOOKUP("core_clk",		vdc_clk.c,	"footswitch-pcom.7"),
 	CLK_LOOKUP("vfe_clk",		vfe_clk.c,	NULL),
+	CLK_LOOKUP("vfe_clk",		vfe_clk.c,	"msm_vfe.0"),
 	CLK_LOOKUP("core_clk",		vfe_clk.c,	"footswitch-pcom.8"),
 	CLK_LOOKUP("vfe_mdc_clk",	vfe_mdc_clk.c,	NULL),
 
@@ -347,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),
@@ -390,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 91121e6..4210bd9 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -1,7 +1,7 @@
 /* arch/arm/mach-msm/clock.h
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-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
@@ -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
@@ -136,6 +138,7 @@
 extern struct clock_init_data msm8960_dummy_clock_init_data;
 extern struct clock_init_data msm8x60_clock_init_data;
 extern struct clock_init_data qds8x50_clock_init_data;
+extern struct clock_init_data msm8625_dummy_clock_init_data;
 
 void msm_clock_init(struct clock_init_data *data);
 int vote_vdd_level(struct clk_vdd_class *vdd_class, int level);
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 2477221..81d01c2 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -3,7 +3,7 @@
  * MSM architecture cpufreq driver
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2012, Code Aurora Forum. All rights reserved.
  * Author: Mike A. Chan <mikechan@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -173,10 +173,9 @@
 	struct cpufreq_work_struct *cpu_work = NULL;
 #endif
 
-	if (cpu_is_apq8064())
-		return -ENODEV;
-
 	table = cpufreq_frequency_get_table(policy->cpu);
+	if (table == NULL)
+		return -ENODEV;
 	if (cpufreq_frequency_table_cpuinfo(policy, table)) {
 #ifdef CONFIG_MSM_CPU_FREQ_SET_MIN_MAX
 		policy->cpuinfo.min_freq = CONFIG_MSM_CPU_FREQ_MIN;
diff --git a/arch/arm/mach-msm/cpuidle.c b/arch/arm/mach-msm/cpuidle.c
index abaa925..cccba2d 100644
--- a/arch/arm/mach-msm/cpuidle.c
+++ b/arch/arm/mach-msm/cpuidle.c
@@ -17,7 +17,8 @@
 #include <linux/cpu_pm.h>
 
 #include <mach/cpuidle.h>
-#include <mach/pm.h>
+
+#include "pm.h"
 
 static DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuidle_device, msm_cpuidle_devs);
 static struct cpuidle_driver msm_cpuidle_driver = {
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 9c77f3d..cb63395 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/msm_rotator.h>
 #include <linux/clkdev.h>
+#include <linux/dma-mapping.h>
 #include <mach/irqs-8064.h>
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
@@ -25,9 +26,14 @@
 #include <sound/msm-dai-q6.h>
 #include <sound/apr_audio.h>
 #include <mach/msm_bus_board.h>
+#include <mach/rpm.h>
+#include <mach/mdm2.h>
 #include "clock.h"
 #include "devices.h"
 #include "msm_watchdog.h"
+#include "rpm_stats.h"
+#include "rpm_log.h"
+#include "mpm.h"
 
 /* Address of GSBI blocks */
 #define MSM_GSBI1_PHYS		0x12440000
@@ -40,6 +46,7 @@
 /* GSBI UART devices */
 #define MSM_UART1DM_PHYS	(MSM_GSBI1_PHYS + 0x10000)
 #define MSM_UART3DM_PHYS	(MSM_GSBI3_PHYS + 0x40000)
+#define MSM_UART7DM_PHYS	(MSM_GSBI7_PHYS + 0x40000)
 
 /* GSBI QUP devices */
 #define MSM_GSBI3_QUP_PHYS	(MSM_GSBI3_PHYS + 0x80000)
@@ -55,8 +62,8 @@
 #define MSM_PMIC_SSBI_SIZE	SZ_4K
 
 /* Address of HS USBOTG1 */
-#define MSM_HSUSB_PHYS		0x12500000
-#define MSM_HSUSB_SIZE		SZ_4K
+#define MSM_HSUSB1_PHYS		0x12500000
+#define MSM_HSUSB1_SIZE		SZ_4K
 
 static struct msm_watchdog_pdata msm_watchdog_pdata = {
 	.pet_time = 10000,
@@ -121,7 +128,7 @@
 
 struct platform_device apq8064_device_uart_gsbi1 = {
 	.name	= "msm_serial_hsl",
-	.id	= 0,
+	.id	= 1,
 	.num_resources	= ARRAY_SIZE(resources_uart_gsbi1),
 	.resource	= resources_uart_gsbi1,
 };
@@ -209,6 +216,33 @@
 	.resource	= resources_qup_spi_gsbi5,
 };
 
+static struct resource resources_uart_gsbi7[] = {
+	{
+		.start	= GSBI7_UARTDM_IRQ,
+		.end	= GSBI7_UARTDM_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= MSM_UART7DM_PHYS,
+		.end	= MSM_UART7DM_PHYS + PAGE_SIZE - 1,
+		.name	= "uartdm_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MSM_GSBI7_PHYS,
+		.end	= MSM_GSBI7_PHYS + PAGE_SIZE - 1,
+		.name	= "gsbi_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device apq8064_device_uart_gsbi7 = {
+	.name	= "msm_serial_hsl",
+	.id	= 0,
+	.num_resources	= ARRAY_SIZE(resources_uart_gsbi7),
+	.resource	= resources_uart_gsbi7,
+};
+
 struct platform_device apq_pcm = {
 	.name	= "msm-pcm-dsp",
 	.id	= -1,
@@ -409,8 +443,8 @@
 
 static struct resource resources_otg[] = {
 	{
-		.start	= MSM_HSUSB_PHYS,
-		.end	= MSM_HSUSB_PHYS + MSM_HSUSB_SIZE - 1,
+		.start	= MSM_HSUSB1_PHYS,
+		.end	= MSM_HSUSB1_PHYS + MSM_HSUSB1_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
@@ -432,8 +466,8 @@
 
 static struct resource resources_hsusb[] = {
 	{
-		.start	= MSM_HSUSB_PHYS,
-		.end	= MSM_HSUSB_PHYS + MSM_HSUSB_SIZE - 1,
+		.start	= MSM_HSUSB1_PHYS,
+		.end	= MSM_HSUSB1_PHYS + MSM_HSUSB1_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
@@ -453,6 +487,61 @@
 	},
 };
 
+static struct resource resources_hsusb_host[] = {
+	{
+		.start  = MSM_HSUSB1_PHYS,
+		.end    = MSM_HSUSB1_PHYS + MSM_HSUSB1_SIZE - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.start  = USB1_HS_IRQ,
+		.end    = USB1_HS_IRQ,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource resources_hsic_host[] = {
+	{
+		.start	= 0x12510000,
+		.end	= 0x12510000 + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= USB2_HSIC_IRQ,
+		.end	= USB2_HSIC_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= MSM_GPIO_TO_INT(49),
+		.end	= MSM_GPIO_TO_INT(49),
+		.name	= "peripheral_status_irq",
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 dma_mask = DMA_BIT_MASK(32);
+struct platform_device apq8064_device_hsusb_host = {
+	.name           = "msm_hsusb_host",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(resources_hsusb_host),
+	.resource       = resources_hsusb_host,
+	.dev            = {
+		.dma_mask               = &dma_mask,
+		.coherent_dma_mask      = 0xffffffff,
+	},
+};
+
+struct platform_device apq8064_device_hsic_host = {
+	.name		= "msm_hsic_host",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(resources_hsic_host),
+	.resource	= resources_hsic_host,
+	.dev		= {
+		.dma_mask		= &dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
 #define MSM_SDC1_BASE         0x12400000
 #define MSM_SDC1_DML_BASE     (MSM_SDC1_BASE + 0x800)
 #define MSM_SDC1_BAM_BASE     (MSM_SDC1_BASE + 0x2000)
@@ -750,6 +839,26 @@
 };
 #endif
 
+static struct resource msm_gss_resources[] = {
+	{
+		.start  = 0x10000000,
+		.end    = 0x10000000 + SZ_256 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.start  = 0x10008000,
+		.end    = 0x10008000 + SZ_256 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device msm_gss = {
+	.name = "pil_gss",
+	.id = -1,
+	.num_resources  = ARRAY_SIZE(msm_gss_resources),
+	.resource       = msm_gss_resources,
+};
+
 static struct clk_lookup msm_clocks_8064_dummy[] = {
 	CLK_DUMMY("pll2",		PLL2,		NULL, 0),
 	CLK_DUMMY("pll8",		PLL8,		NULL, 0),
@@ -942,3 +1051,433 @@
 	.table = msm_clocks_8064_dummy,
 	.size = ARRAY_SIZE(msm_clocks_8064_dummy),
 };
+
+struct msm_rpm_platform_data apq8064_rpm_data __initdata = {
+	.reg_base_addrs = {
+		[MSM_RPM_PAGE_STATUS] = MSM_RPM_BASE,
+		[MSM_RPM_PAGE_CTRL] = MSM_RPM_BASE + 0x400,
+		[MSM_RPM_PAGE_REQ] = MSM_RPM_BASE + 0x600,
+		[MSM_RPM_PAGE_ACK] = MSM_RPM_BASE + 0xa00,
+	},
+	.irq_ack = RPM_APCC_CPU0_GP_HIGH_IRQ,
+	.ipc_rpm_reg = MSM_APCS_GCC_BASE + 0x008,
+	.ipc_rpm_val = 4,
+	.target_id =  {
+		MSM_RPM_MAP(8064, NOTIFICATION_CONFIGURED_0, NOTIFICATION, 4),
+		MSM_RPM_MAP(8064, NOTIFICATION_REGISTERED_0, NOTIFICATION, 4),
+		MSM_RPM_MAP(8064, INVALIDATE_0, INVALIDATE, 8),
+		MSM_RPM_MAP(8064, TRIGGER_TIMED_TO, TRIGGER_TIMED, 1),
+		MSM_RPM_MAP(8064, TRIGGER_TIMED_SCLK_COUNT, TRIGGER_TIMED, 1),
+		MSM_RPM_MAP(8064, RPM_CTL, RPM_CTL, 1),
+		MSM_RPM_MAP(8064, CXO_CLK, CXO_CLK, 1),
+		MSM_RPM_MAP(8064, PXO_CLK, PXO_CLK, 1),
+		MSM_RPM_MAP(8064, APPS_FABRIC_CLK, APPS_FABRIC_CLK, 1),
+		MSM_RPM_MAP(8064, SYSTEM_FABRIC_CLK, SYSTEM_FABRIC_CLK, 1),
+		MSM_RPM_MAP(8064, MM_FABRIC_CLK, MM_FABRIC_CLK, 1),
+		MSM_RPM_MAP(8064, DAYTONA_FABRIC_CLK, DAYTONA_FABRIC_CLK, 1),
+		MSM_RPM_MAP(8064, SFPB_CLK, SFPB_CLK, 1),
+		MSM_RPM_MAP(8064, CFPB_CLK, CFPB_CLK, 1),
+		MSM_RPM_MAP(8064, MMFPB_CLK, MMFPB_CLK, 1),
+		MSM_RPM_MAP(8064, EBI1_CLK, EBI1_CLK, 1),
+		MSM_RPM_MAP(8064, APPS_FABRIC_CFG_HALT_0,
+				APPS_FABRIC_CFG_HALT, 2),
+		MSM_RPM_MAP(8064, APPS_FABRIC_CFG_CLKMOD_0,
+				APPS_FABRIC_CFG_CLKMOD, 3),
+		MSM_RPM_MAP(8064, APPS_FABRIC_CFG_IOCTL,
+				APPS_FABRIC_CFG_IOCTL, 1),
+		MSM_RPM_MAP(8064, APPS_FABRIC_ARB_0, APPS_FABRIC_ARB, 12),
+		MSM_RPM_MAP(8064, SYS_FABRIC_CFG_HALT_0,
+				SYS_FABRIC_CFG_HALT, 2),
+		MSM_RPM_MAP(8064, SYS_FABRIC_CFG_CLKMOD_0,
+				SYS_FABRIC_CFG_CLKMOD, 3),
+		MSM_RPM_MAP(8064, SYS_FABRIC_CFG_IOCTL,
+				SYS_FABRIC_CFG_IOCTL, 1),
+		MSM_RPM_MAP(8064, SYSTEM_FABRIC_ARB_0, SYSTEM_FABRIC_ARB, 30),
+		MSM_RPM_MAP(8064, MMSS_FABRIC_CFG_HALT_0,
+				MMSS_FABRIC_CFG_HALT, 2),
+		MSM_RPM_MAP(8064, MMSS_FABRIC_CFG_CLKMOD_0,
+				MMSS_FABRIC_CFG_CLKMOD, 3),
+		MSM_RPM_MAP(8064, MMSS_FABRIC_CFG_IOCTL,
+				MMSS_FABRIC_CFG_IOCTL, 1),
+		MSM_RPM_MAP(8064, MM_FABRIC_ARB_0, MM_FABRIC_ARB, 21),
+		MSM_RPM_MAP(8064, PM8921_S1_0, PM8921_S1, 2),
+		MSM_RPM_MAP(8064, PM8921_S2_0, PM8921_S2, 2),
+		MSM_RPM_MAP(8064, PM8921_S3_0, PM8921_S3, 2),
+		MSM_RPM_MAP(8064, PM8921_S4_0, PM8921_S4, 2),
+		MSM_RPM_MAP(8064, PM8921_S5_0, PM8921_S5, 2),
+		MSM_RPM_MAP(8064, PM8921_S6_0, PM8921_S6, 2),
+		MSM_RPM_MAP(8064, PM8921_S7_0, PM8921_S7, 2),
+		MSM_RPM_MAP(8064, PM8921_S8_0, PM8921_S8, 2),
+		MSM_RPM_MAP(8064, PM8921_L1_0, PM8921_L1, 2),
+		MSM_RPM_MAP(8064, PM8921_L2_0, PM8921_L2, 2),
+		MSM_RPM_MAP(8064, PM8921_L3_0, PM8921_L3, 2),
+		MSM_RPM_MAP(8064, PM8921_L4_0, PM8921_L4, 2),
+		MSM_RPM_MAP(8064, PM8921_L5_0, PM8921_L5, 2),
+		MSM_RPM_MAP(8064, PM8921_L6_0, PM8921_L6, 2),
+		MSM_RPM_MAP(8064, PM8921_L7_0, PM8921_L7, 2),
+		MSM_RPM_MAP(8064, PM8921_L8_0, PM8921_L8, 2),
+		MSM_RPM_MAP(8064, PM8921_L9_0, PM8921_L9, 2),
+		MSM_RPM_MAP(8064, PM8921_L10_0, PM8921_L10, 2),
+		MSM_RPM_MAP(8064, PM8921_L11_0, PM8921_L11, 2),
+		MSM_RPM_MAP(8064, PM8921_L12_0, PM8921_L12, 2),
+		MSM_RPM_MAP(8064, PM8921_L13_0, PM8921_L13, 2),
+		MSM_RPM_MAP(8064, PM8921_L14_0, PM8921_L14, 2),
+		MSM_RPM_MAP(8064, PM8921_L15_0, PM8921_L15, 2),
+		MSM_RPM_MAP(8064, PM8921_L16_0, PM8921_L16, 2),
+		MSM_RPM_MAP(8064, PM8921_L17_0, PM8921_L17, 2),
+		MSM_RPM_MAP(8064, PM8921_L18_0, PM8921_L18, 2),
+		MSM_RPM_MAP(8064, PM8921_L19_0, PM8921_L19, 2),
+		MSM_RPM_MAP(8064, PM8921_L20_0, PM8921_L20, 2),
+		MSM_RPM_MAP(8064, PM8921_L21_0, PM8921_L21, 2),
+		MSM_RPM_MAP(8064, PM8921_L22_0, PM8921_L22, 2),
+		MSM_RPM_MAP(8064, PM8921_L23_0, PM8921_L23, 2),
+		MSM_RPM_MAP(8064, PM8921_L24_0, PM8921_L24, 2),
+		MSM_RPM_MAP(8064, PM8921_L25_0, PM8921_L25, 2),
+		MSM_RPM_MAP(8064, PM8921_L26_0, PM8921_L26, 2),
+		MSM_RPM_MAP(8064, PM8921_L27_0, PM8921_L27, 2),
+		MSM_RPM_MAP(8064, PM8921_L28_0, PM8921_L28, 2),
+		MSM_RPM_MAP(8064, PM8921_L29_0, PM8921_L29, 2),
+		MSM_RPM_MAP(8064, PM8921_CLK1_0, PM8921_CLK1, 2),
+		MSM_RPM_MAP(8064, PM8921_CLK2_0, PM8921_CLK2, 2),
+		MSM_RPM_MAP(8064, PM8921_LVS1, PM8921_LVS1, 1),
+		MSM_RPM_MAP(8064, PM8921_LVS2, PM8921_LVS2, 1),
+		MSM_RPM_MAP(8064, PM8921_LVS3, PM8921_LVS3, 1),
+		MSM_RPM_MAP(8064, PM8921_LVS4, PM8921_LVS4, 1),
+		MSM_RPM_MAP(8064, PM8921_LVS5, PM8921_LVS5, 1),
+		MSM_RPM_MAP(8064, PM8921_LVS6, PM8921_LVS6, 1),
+		MSM_RPM_MAP(8064, PM8921_LVS7, PM8921_LVS7, 1),
+		MSM_RPM_MAP(8064, PM8821_S1_0, PM8821_S1, 2),
+		MSM_RPM_MAP(8064, PM8821_S2_0, PM8821_S2, 2),
+		MSM_RPM_MAP(8064, PM8821_L1_0, PM8821_L1, 2),
+		MSM_RPM_MAP(8064, NCP_0, NCP, 2),
+		MSM_RPM_MAP(8064, CXO_BUFFERS, CXO_BUFFERS, 1),
+		MSM_RPM_MAP(8064, USB_OTG_SWITCH, USB_OTG_SWITCH, 1),
+		MSM_RPM_MAP(8064, HDMI_SWITCH, HDMI_SWITCH, 1),
+		MSM_RPM_MAP(8064, DDR_DMM_0, DDR_DMM, 2),
+		MSM_RPM_MAP(8064, QDSS_CLK, QDSS_CLK, 1),
+	},
+	.target_status = {
+		MSM_RPM_STATUS_ID_MAP(8064, VERSION_MAJOR),
+		MSM_RPM_STATUS_ID_MAP(8064, VERSION_MINOR),
+		MSM_RPM_STATUS_ID_MAP(8064, VERSION_BUILD),
+		MSM_RPM_STATUS_ID_MAP(8064, SUPPORTED_RESOURCES_0),
+		MSM_RPM_STATUS_ID_MAP(8064, SUPPORTED_RESOURCES_1),
+		MSM_RPM_STATUS_ID_MAP(8064, SUPPORTED_RESOURCES_2),
+		MSM_RPM_STATUS_ID_MAP(8064, RESERVED_SUPPORTED_RESOURCES_0),
+		MSM_RPM_STATUS_ID_MAP(8064, SEQUENCE),
+		MSM_RPM_STATUS_ID_MAP(8064, RPM_CTL),
+		MSM_RPM_STATUS_ID_MAP(8064, CXO_CLK),
+		MSM_RPM_STATUS_ID_MAP(8064, PXO_CLK),
+		MSM_RPM_STATUS_ID_MAP(8064, APPS_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(8064, SYSTEM_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(8064, MM_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(8064, DAYTONA_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(8064, SFPB_CLK),
+		MSM_RPM_STATUS_ID_MAP(8064, CFPB_CLK),
+		MSM_RPM_STATUS_ID_MAP(8064, MMFPB_CLK),
+		MSM_RPM_STATUS_ID_MAP(8064, EBI1_CLK),
+		MSM_RPM_STATUS_ID_MAP(8064, APPS_FABRIC_CFG_HALT),
+		MSM_RPM_STATUS_ID_MAP(8064, APPS_FABRIC_CFG_CLKMOD),
+		MSM_RPM_STATUS_ID_MAP(8064, APPS_FABRIC_CFG_IOCTL),
+		MSM_RPM_STATUS_ID_MAP(8064, APPS_FABRIC_ARB),
+		MSM_RPM_STATUS_ID_MAP(8064, SYS_FABRIC_CFG_HALT),
+		MSM_RPM_STATUS_ID_MAP(8064, SYS_FABRIC_CFG_CLKMOD),
+		MSM_RPM_STATUS_ID_MAP(8064, SYS_FABRIC_CFG_IOCTL),
+		MSM_RPM_STATUS_ID_MAP(8064, SYSTEM_FABRIC_ARB),
+		MSM_RPM_STATUS_ID_MAP(8064, MMSS_FABRIC_CFG_HALT),
+		MSM_RPM_STATUS_ID_MAP(8064, MMSS_FABRIC_CFG_CLKMOD),
+		MSM_RPM_STATUS_ID_MAP(8064, MMSS_FABRIC_CFG_IOCTL),
+		MSM_RPM_STATUS_ID_MAP(8064, MM_FABRIC_ARB),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_S1_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_S1_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_S2_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_S2_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_S3_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_S3_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_S4_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_S4_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_S5_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_S5_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_S6_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_S6_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_S7_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_S7_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_S8_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_S8_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L1_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L1_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L2_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L2_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L3_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L3_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L4_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L4_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L5_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L5_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L6_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L6_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L7_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L7_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L8_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L8_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L9_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L9_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L10_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L10_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L11_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L11_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L12_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L12_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L13_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L13_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L14_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L14_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L15_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L15_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L16_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L16_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L17_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L17_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L18_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L18_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L19_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L19_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L20_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L20_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L21_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L21_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L22_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L22_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L23_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L23_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L24_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L24_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L25_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L25_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L26_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L26_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L27_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L27_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L28_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L28_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L29_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_L29_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_CLK1_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_CLK1_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_CLK2_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_CLK2_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_LVS1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_LVS2),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_LVS3),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_LVS4),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_LVS5),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_LVS6),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8921_LVS7),
+		MSM_RPM_STATUS_ID_MAP(8064, NCP_0),
+		MSM_RPM_STATUS_ID_MAP(8064, NCP_1),
+		MSM_RPM_STATUS_ID_MAP(8064, CXO_BUFFERS),
+		MSM_RPM_STATUS_ID_MAP(8064, USB_OTG_SWITCH),
+		MSM_RPM_STATUS_ID_MAP(8064, HDMI_SWITCH),
+		MSM_RPM_STATUS_ID_MAP(8064, DDR_DMM_0),
+		MSM_RPM_STATUS_ID_MAP(8064, DDR_DMM_1),
+		MSM_RPM_STATUS_ID_MAP(8064, EBI1_CH0_RANGE),
+		MSM_RPM_STATUS_ID_MAP(8064, EBI1_CH1_RANGE),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8821_S1_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8821_S1_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8821_S2_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8821_S2_1),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8821_L1_0),
+		MSM_RPM_STATUS_ID_MAP(8064, PM8821_L1_1),
+	},
+	.target_ctrl_id = {
+		MSM_RPM_CTRL_MAP(8064, VERSION_MAJOR),
+		MSM_RPM_CTRL_MAP(8064, VERSION_MINOR),
+		MSM_RPM_CTRL_MAP(8064, VERSION_BUILD),
+		MSM_RPM_CTRL_MAP(8064, REQ_CTX_0),
+		MSM_RPM_CTRL_MAP(8064, REQ_SEL_0),
+		MSM_RPM_CTRL_MAP(8064, ACK_CTX_0),
+		MSM_RPM_CTRL_MAP(8064, ACK_SEL_0),
+	},
+	.sel_invalidate = MSM_RPM_8064_SEL_INVALIDATE,
+	.sel_notification = MSM_RPM_8064_SEL_NOTIFICATION,
+	.sel_last = MSM_RPM_8064_SEL_LAST,
+	.ver = {3, 0, 0},
+};
+
+struct platform_device apq8064_rpm_device = {
+	.name   = "msm_rpm",
+	.id     = -1,
+};
+
+static struct msm_rpmstats_platform_data msm_rpm_stat_pdata = {
+	.phys_addr_base = 0x0010D204,
+	.phys_size = SZ_8K,
+};
+
+struct platform_device apq8064_rpm_stat_device = {
+	.name = "msm_rpm_stat",
+	.id = -1,
+	.dev = {
+		.platform_data = &msm_rpm_stat_pdata,
+	},
+};
+
+static struct msm_rpm_log_platform_data msm_rpm_log_pdata = {
+	.phys_addr_base = 0x0010C000,
+	.reg_offsets = {
+		[MSM_RPM_LOG_PAGE_INDICES] = 0x00000080,
+		[MSM_RPM_LOG_PAGE_BUFFER]  = 0x000000A0,
+	},
+	.phys_size = SZ_8K,
+	.log_len = 4096,		  /* log's buffer length in bytes */
+	.log_len_mask = (4096 >> 2) - 1,  /* length mask in units of u32 */
+};
+
+struct platform_device apq8064_rpm_log_device = {
+	.name	= "msm_rpm_log",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &msm_rpm_log_pdata,
+	},
+};
+
+#ifdef CONFIG_MSM_MPM
+static uint16_t msm_mpm_irqs_m2a[MSM_MPM_NR_MPM_IRQS] __initdata = {
+	[1] = MSM_GPIO_TO_INT(26),
+	[2] = MSM_GPIO_TO_INT(88),
+	[4] = MSM_GPIO_TO_INT(73),
+	[5] = MSM_GPIO_TO_INT(74),
+	[6] = MSM_GPIO_TO_INT(75),
+	[7] = MSM_GPIO_TO_INT(76),
+	[8] = MSM_GPIO_TO_INT(77),
+	[9] = MSM_GPIO_TO_INT(36),
+	[10] = MSM_GPIO_TO_INT(84),
+	[11] = MSM_GPIO_TO_INT(7),
+	[12] = MSM_GPIO_TO_INT(11),
+	[13] = MSM_GPIO_TO_INT(52),
+	[14] = MSM_GPIO_TO_INT(15),
+	[15] = MSM_GPIO_TO_INT(83),
+	[16] = USB3_HS_IRQ,
+	[19] = MSM_GPIO_TO_INT(61),
+	[20] = MSM_GPIO_TO_INT(58),
+	[23] = MSM_GPIO_TO_INT(65),
+	[24] = MSM_GPIO_TO_INT(63),
+	[25] = USB1_HS_IRQ,
+	[27] = HDMI_IRQ,
+	[29] = MSM_GPIO_TO_INT(22),
+	[30] = MSM_GPIO_TO_INT(72),
+	[31] = USB4_HS_IRQ,
+	[33] = MSM_GPIO_TO_INT(44),
+	[34] = MSM_GPIO_TO_INT(39),
+	[35] = MSM_GPIO_TO_INT(19),
+	[36] = MSM_GPIO_TO_INT(23),
+	[37] = MSM_GPIO_TO_INT(41),
+	[38] = MSM_GPIO_TO_INT(30),
+	[41] = MSM_GPIO_TO_INT(42),
+	[42] = MSM_GPIO_TO_INT(56),
+	[43] = MSM_GPIO_TO_INT(55),
+	[44] = MSM_GPIO_TO_INT(50),
+	[45] = MSM_GPIO_TO_INT(49),
+	[46] = MSM_GPIO_TO_INT(47),
+	[47] = MSM_GPIO_TO_INT(45),
+	[48] = MSM_GPIO_TO_INT(38),
+	[49] = MSM_GPIO_TO_INT(34),
+	[50] = MSM_GPIO_TO_INT(32),
+	[51] = MSM_GPIO_TO_INT(29),
+	[52] = MSM_GPIO_TO_INT(18),
+	[53] = MSM_GPIO_TO_INT(10),
+	[54] = MSM_GPIO_TO_INT(81),
+	[55] = MSM_GPIO_TO_INT(6),
+};
+
+static uint16_t msm_mpm_bypassed_apps_irqs[] __initdata = {
+	TLMM_MSM_SUMMARY_IRQ,
+	RPM_APCC_CPU0_GP_HIGH_IRQ,
+	RPM_APCC_CPU0_GP_MEDIUM_IRQ,
+	RPM_APCC_CPU0_GP_LOW_IRQ,
+	RPM_APCC_CPU0_WAKE_UP_IRQ,
+	RPM_APCC_CPU1_GP_HIGH_IRQ,
+	RPM_APCC_CPU1_GP_MEDIUM_IRQ,
+	RPM_APCC_CPU1_GP_LOW_IRQ,
+	RPM_APCC_CPU1_WAKE_UP_IRQ,
+	MSS_TO_APPS_IRQ_0,
+	MSS_TO_APPS_IRQ_1,
+	MSS_TO_APPS_IRQ_2,
+	MSS_TO_APPS_IRQ_3,
+	MSS_TO_APPS_IRQ_4,
+	MSS_TO_APPS_IRQ_5,
+	MSS_TO_APPS_IRQ_6,
+	MSS_TO_APPS_IRQ_7,
+	MSS_TO_APPS_IRQ_8,
+	MSS_TO_APPS_IRQ_9,
+	LPASS_SCSS_GP_LOW_IRQ,
+	LPASS_SCSS_GP_MEDIUM_IRQ,
+	LPASS_SCSS_GP_HIGH_IRQ,
+	SPS_MTI_30,
+	SPS_MTI_31,
+	RIVA_APSS_SPARE_IRQ,
+	RIVA_APPS_WLAN_SMSM_IRQ,
+	RIVA_APPS_WLAN_RX_DATA_AVAIL_IRQ,
+	RIVA_APPS_WLAN_DATA_XFER_DONE_IRQ,
+};
+
+struct msm_mpm_device_data apq8064_mpm_dev_data __initdata = {
+	.irqs_m2a = msm_mpm_irqs_m2a,
+	.irqs_m2a_size = ARRAY_SIZE(msm_mpm_irqs_m2a),
+	.bypassed_apps_irqs = msm_mpm_bypassed_apps_irqs,
+	.bypassed_apps_irqs_size = ARRAY_SIZE(msm_mpm_bypassed_apps_irqs),
+	.mpm_request_reg_base = MSM_RPM_BASE + 0x9d8,
+	.mpm_status_reg_base = MSM_RPM_BASE + 0xdf8,
+	.mpm_apps_ipc_reg = MSM_APCS_GCC_BASE + 0x008,
+	.mpm_apps_ipc_val =  BIT(1),
+	.mpm_ipc_irq = RPM_APCC_CPU0_GP_MEDIUM_IRQ,
+
+};
+#endif
+
+#define MDM2AP_ERRFATAL			19
+#define AP2MDM_ERRFATAL			18
+#define MDM2AP_STATUS			49
+#define AP2MDM_STATUS			48
+#define AP2MDM_PMIC_RESET_N		27
+
+static struct resource mdm_resources[] = {
+	{
+		.start	= MDM2AP_ERRFATAL,
+		.end	= MDM2AP_ERRFATAL,
+		.name	= "MDM2AP_ERRFATAL",
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.start	= AP2MDM_ERRFATAL,
+		.end	= AP2MDM_ERRFATAL,
+		.name	= "AP2MDM_ERRFATAL",
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.start	= MDM2AP_STATUS,
+		.end	= MDM2AP_STATUS,
+		.name	= "MDM2AP_STATUS",
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.start	= AP2MDM_STATUS,
+		.end	= AP2MDM_STATUS,
+		.name	= "AP2MDM_STATUS",
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.start	= AP2MDM_PMIC_RESET_N,
+		.end	= AP2MDM_PMIC_RESET_N,
+		.name	= "AP2MDM_PMIC_RESET_N",
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+struct platform_device mdm_8064_device = {
+	.name		= "mdm2_modem",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(mdm_resources),
+	.resource	= mdm_resources,
+};
+
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
new file mode 100644
index 0000000..c75a4e3
--- /dev/null
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -0,0 +1,274 @@
+/* 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/platform_device.h>
+#include <mach/msm_iomap.h>
+#include <mach/irqs-8930.h>
+#include <mach/rpm.h>
+
+#include "devices.h"
+#include "rpm_log.h"
+#include "rpm_stats.h"
+
+#ifdef CONFIG_MSM_MPM
+#include "mpm.h"
+#endif
+
+struct msm_rpm_platform_data msm8930_rpm_data __initdata = {
+	.reg_base_addrs = {
+		[MSM_RPM_PAGE_STATUS] = MSM_RPM_BASE,
+		[MSM_RPM_PAGE_CTRL] = MSM_RPM_BASE + 0x400,
+		[MSM_RPM_PAGE_REQ] = MSM_RPM_BASE + 0x600,
+		[MSM_RPM_PAGE_ACK] = MSM_RPM_BASE + 0xa00,
+	},
+	.irq_ack = RPM_APCC_CPU0_GP_HIGH_IRQ,
+	.ipc_rpm_reg = MSM_APCS_GCC_BASE + 0x008,
+	.ipc_rpm_val = 4,
+	.target_id = {
+		MSM_RPM_MAP(8930, NOTIFICATION_CONFIGURED_0, NOTIFICATION, 4),
+		MSM_RPM_MAP(8930, NOTIFICATION_REGISTERED_0, NOTIFICATION, 4),
+		MSM_RPM_MAP(8930, INVALIDATE_0, INVALIDATE, 8),
+		MSM_RPM_MAP(8960, TRIGGER_TIMED_TO, TRIGGER_TIMED, 1),
+		MSM_RPM_MAP(8960, TRIGGER_TIMED_SCLK_COUNT, TRIGGER_TIMED, 1),
+		MSM_RPM_MAP(8930, RPM_CTL, RPM_CTL, 1),
+		MSM_RPM_MAP(8930, CXO_CLK, CXO_CLK, 1),
+		MSM_RPM_MAP(8930, PXO_CLK, PXO_CLK, 1),
+		MSM_RPM_MAP(8930, APPS_FABRIC_CLK, APPS_FABRIC_CLK, 1),
+		MSM_RPM_MAP(8930, SYSTEM_FABRIC_CLK, SYSTEM_FABRIC_CLK, 1),
+		MSM_RPM_MAP(8930, MM_FABRIC_CLK, MM_FABRIC_CLK, 1),
+		MSM_RPM_MAP(8930, DAYTONA_FABRIC_CLK, DAYTONA_FABRIC_CLK, 1),
+		MSM_RPM_MAP(8930, SFPB_CLK, SFPB_CLK, 1),
+		MSM_RPM_MAP(8930, CFPB_CLK, CFPB_CLK, 1),
+		MSM_RPM_MAP(8930, MMFPB_CLK, MMFPB_CLK, 1),
+		MSM_RPM_MAP(8930, EBI1_CLK, EBI1_CLK, 1),
+		MSM_RPM_MAP(8930, APPS_FABRIC_CFG_HALT_0,
+				APPS_FABRIC_CFG_HALT, 2),
+		MSM_RPM_MAP(8930, APPS_FABRIC_CFG_CLKMOD_0,
+				APPS_FABRIC_CFG_CLKMOD, 3),
+		MSM_RPM_MAP(8930, APPS_FABRIC_CFG_IOCTL,
+				APPS_FABRIC_CFG_IOCTL, 1),
+		MSM_RPM_MAP(8930, APPS_FABRIC_ARB_0, APPS_FABRIC_ARB, 12),
+		MSM_RPM_MAP(8930, SYS_FABRIC_CFG_HALT_0,
+				SYS_FABRIC_CFG_HALT, 2),
+		MSM_RPM_MAP(8930, SYS_FABRIC_CFG_CLKMOD_0,
+				SYS_FABRIC_CFG_CLKMOD, 3),
+		MSM_RPM_MAP(8930, SYS_FABRIC_CFG_IOCTL,
+				SYS_FABRIC_CFG_IOCTL, 1),
+		MSM_RPM_MAP(8930, SYSTEM_FABRIC_ARB_0,
+				SYSTEM_FABRIC_ARB, 29),
+		MSM_RPM_MAP(8930, MMSS_FABRIC_CFG_HALT_0,
+				MMSS_FABRIC_CFG_HALT, 2),
+		MSM_RPM_MAP(8930, MMSS_FABRIC_CFG_CLKMOD_0,
+				MMSS_FABRIC_CFG_CLKMOD, 3),
+		MSM_RPM_MAP(8930, MMSS_FABRIC_CFG_IOCTL,
+				MMSS_FABRIC_CFG_IOCTL, 1),
+		MSM_RPM_MAP(8930, MM_FABRIC_ARB_0, MM_FABRIC_ARB, 23),
+		MSM_RPM_MAP(8930, PM8038_S1_0, PM8038_S1, 2),
+		MSM_RPM_MAP(8930, PM8038_S2_0, PM8038_S2, 2),
+		MSM_RPM_MAP(8930, PM8038_S3_0, PM8038_S3, 2),
+		MSM_RPM_MAP(8930, PM8038_S4_0, PM8038_S4, 2),
+		MSM_RPM_MAP(8930, PM8038_S5_0, PM8038_S5, 2),
+		MSM_RPM_MAP(8930, PM8038_S6_0, PM8038_S6, 2),
+		MSM_RPM_MAP(8930, PM8038_L1_0, PM8038_L1, 2),
+		MSM_RPM_MAP(8930, PM8038_L2_0, PM8038_L2, 2),
+		MSM_RPM_MAP(8930, PM8038_L3_0, PM8038_L3, 2),
+		MSM_RPM_MAP(8930, PM8038_L4_0, PM8038_L4, 2),
+		MSM_RPM_MAP(8930, PM8038_L5_0, PM8038_L5, 2),
+		MSM_RPM_MAP(8930, PM8038_L6_0, PM8038_L6, 2),
+		MSM_RPM_MAP(8930, PM8038_L7_0, PM8038_L7, 2),
+		MSM_RPM_MAP(8930, PM8038_L8_0, PM8038_L8, 2),
+		MSM_RPM_MAP(8930, PM8038_L9_0, PM8038_L9, 2),
+		MSM_RPM_MAP(8930, PM8038_L10_0, PM8038_L10, 2),
+		MSM_RPM_MAP(8930, PM8038_L11_0, PM8038_L11, 2),
+		MSM_RPM_MAP(8930, PM8038_L12_0, PM8038_L12, 2),
+		MSM_RPM_MAP(8930, PM8038_L13_0, PM8038_L13, 2),
+		MSM_RPM_MAP(8930, PM8038_L14_0, PM8038_L14, 2),
+		MSM_RPM_MAP(8930, PM8038_L15_0, PM8038_L15, 2),
+		MSM_RPM_MAP(8930, PM8038_L16_0, PM8038_L16, 2),
+		MSM_RPM_MAP(8930, PM8038_L17_0, PM8038_L17, 2),
+		MSM_RPM_MAP(8930, PM8038_L18_0, PM8038_L18, 2),
+		MSM_RPM_MAP(8930, PM8038_L19_0, PM8038_L19, 2),
+		MSM_RPM_MAP(8930, PM8038_L20_0, PM8038_L20, 2),
+		MSM_RPM_MAP(8930, PM8038_L21_0, PM8038_L21, 2),
+		MSM_RPM_MAP(8930, PM8038_L22_0, PM8038_L22, 2),
+		MSM_RPM_MAP(8930, PM8038_L23_0, PM8038_L23, 2),
+		MSM_RPM_MAP(8930, PM8038_L24_0, PM8038_L24, 2),
+		MSM_RPM_MAP(8930, PM8038_L25_0, PM8038_L25, 2),
+		MSM_RPM_MAP(8930, PM8038_L26_0, PM8038_L26, 2),
+		MSM_RPM_MAP(8930, PM8038_L27_0, PM8038_L27, 2),
+		MSM_RPM_MAP(8930, PM8038_CLK1_0, PM8038_CLK1, 2),
+		MSM_RPM_MAP(8930, PM8038_CLK2_0, PM8038_CLK2, 2),
+		MSM_RPM_MAP(8930, PM8038_LVS1, PM8038_LVS1, 1),
+		MSM_RPM_MAP(8930, PM8038_LVS2, PM8038_LVS2, 1),
+		MSM_RPM_MAP(8930, NCP_0, NCP, 2),
+		MSM_RPM_MAP(8930, CXO_BUFFERS, CXO_BUFFERS, 1),
+		MSM_RPM_MAP(8930, USB_OTG_SWITCH, USB_OTG_SWITCH, 1),
+		MSM_RPM_MAP(8930, HDMI_SWITCH, HDMI_SWITCH, 1),
+		MSM_RPM_MAP(8930, QDSS_CLK, QDSS_CLK, 1),
+	},
+	.target_status = {
+		MSM_RPM_STATUS_ID_MAP(8930, VERSION_MAJOR),
+		MSM_RPM_STATUS_ID_MAP(8930, VERSION_MINOR),
+		MSM_RPM_STATUS_ID_MAP(8930, VERSION_BUILD),
+		MSM_RPM_STATUS_ID_MAP(8930, SUPPORTED_RESOURCES_0),
+		MSM_RPM_STATUS_ID_MAP(8930, SUPPORTED_RESOURCES_1),
+		MSM_RPM_STATUS_ID_MAP(8930, SUPPORTED_RESOURCES_2),
+		MSM_RPM_STATUS_ID_MAP(8930, RESERVED_SUPPORTED_RESOURCES_0),
+		MSM_RPM_STATUS_ID_MAP(8930, SEQUENCE),
+		MSM_RPM_STATUS_ID_MAP(8930, RPM_CTL),
+		MSM_RPM_STATUS_ID_MAP(8930, CXO_CLK),
+		MSM_RPM_STATUS_ID_MAP(8930, PXO_CLK),
+		MSM_RPM_STATUS_ID_MAP(8930, APPS_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(8930, SYSTEM_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(8930, MM_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(8930, DAYTONA_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(8930, SFPB_CLK),
+		MSM_RPM_STATUS_ID_MAP(8930, CFPB_CLK),
+		MSM_RPM_STATUS_ID_MAP(8930, MMFPB_CLK),
+		MSM_RPM_STATUS_ID_MAP(8930, EBI1_CLK),
+		MSM_RPM_STATUS_ID_MAP(8930, APPS_FABRIC_CFG_HALT),
+		MSM_RPM_STATUS_ID_MAP(8930, APPS_FABRIC_CFG_CLKMOD),
+		MSM_RPM_STATUS_ID_MAP(8930, APPS_FABRIC_CFG_IOCTL),
+		MSM_RPM_STATUS_ID_MAP(8930, APPS_FABRIC_ARB),
+		MSM_RPM_STATUS_ID_MAP(8930, SYS_FABRIC_CFG_HALT),
+		MSM_RPM_STATUS_ID_MAP(8930, SYS_FABRIC_CFG_CLKMOD),
+		MSM_RPM_STATUS_ID_MAP(8930, SYS_FABRIC_CFG_IOCTL),
+		MSM_RPM_STATUS_ID_MAP(8930, SYSTEM_FABRIC_ARB),
+		MSM_RPM_STATUS_ID_MAP(8930, MMSS_FABRIC_CFG_HALT),
+		MSM_RPM_STATUS_ID_MAP(8930, MMSS_FABRIC_CFG_CLKMOD),
+		MSM_RPM_STATUS_ID_MAP(8930, MMSS_FABRIC_CFG_IOCTL),
+		MSM_RPM_STATUS_ID_MAP(8930, MM_FABRIC_ARB),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_S1_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_S1_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_S2_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_S2_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_S3_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_S3_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_S4_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_S4_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L1_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L1_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L2_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L2_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L3_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L3_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L4_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L4_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L5_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L5_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L6_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L6_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L7_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L7_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L8_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L8_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L9_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L9_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L10_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L10_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L11_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L11_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L12_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L12_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L13_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L13_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L14_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L14_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L15_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L15_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L16_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L16_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L17_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L17_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L18_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L18_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L19_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L19_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L20_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L20_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L21_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L21_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L22_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L22_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L23_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L23_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L24_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L24_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L25_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_L25_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_CLK1_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_CLK1_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_CLK2_0),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_CLK2_1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_LVS1),
+		MSM_RPM_STATUS_ID_MAP(8930, PM8038_LVS2),
+		MSM_RPM_STATUS_ID_MAP(8930, NCP_0),
+		MSM_RPM_STATUS_ID_MAP(8930, NCP_1),
+		MSM_RPM_STATUS_ID_MAP(8930, CXO_BUFFERS),
+		MSM_RPM_STATUS_ID_MAP(8930, USB_OTG_SWITCH),
+		MSM_RPM_STATUS_ID_MAP(8930, HDMI_SWITCH),
+		MSM_RPM_STATUS_ID_MAP(8930, QDSS_CLK),
+	},
+	.target_ctrl_id = {
+		MSM_RPM_CTRL_MAP(8930, VERSION_MAJOR),
+		MSM_RPM_CTRL_MAP(8930, VERSION_MINOR),
+		MSM_RPM_CTRL_MAP(8930, VERSION_BUILD),
+		MSM_RPM_CTRL_MAP(8930, REQ_CTX_0),
+		MSM_RPM_CTRL_MAP(8930, REQ_SEL_0),
+		MSM_RPM_CTRL_MAP(8930, ACK_CTX_0),
+		MSM_RPM_CTRL_MAP(8930, ACK_SEL_0),
+	},
+	.sel_invalidate = MSM_RPM_8930_SEL_INVALIDATE,
+	.sel_notification = MSM_RPM_8930_SEL_NOTIFICATION,
+	.sel_last = MSM_RPM_8930_SEL_LAST,
+	.ver = {3, 0, 0},
+};
+
+struct platform_device msm8930_rpm_device = {
+	.name   = "msm_rpm",
+	.id     = -1,
+};
+
+static struct msm_rpm_log_platform_data msm_rpm_log_pdata = {
+	.phys_addr_base = 0x0010C000,
+	.reg_offsets = {
+		[MSM_RPM_LOG_PAGE_INDICES] = 0x00000080,
+		[MSM_RPM_LOG_PAGE_BUFFER]  = 0x000000A0,
+	},
+	.phys_size = SZ_8K,
+	.log_len = 4096,		  /* log's buffer length in bytes */
+	.log_len_mask = (4096 >> 2) - 1,  /* length mask in units of u32 */
+};
+
+struct platform_device msm8930_rpm_log_device = {
+	.name	= "msm_rpm_log",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &msm_rpm_log_pdata,
+	},
+};
+
+static struct msm_rpmstats_platform_data msm_rpm_stat_pdata = {
+	.phys_addr_base = 0x0010D204,
+	.phys_size = SZ_8K,
+};
+
+struct platform_device msm8930_rpm_stat_device = {
+	.name = "msm_rpm_stat",
+	.id = -1,
+	.dev = {
+		.platform_data = &msm_rpm_stat_pdata,
+	},
+};
+
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 4fa3e92..872d9d4 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -30,7 +30,6 @@
 #include <mach/rpm.h>
 #include <mach/msm_bus_board.h>
 #include <mach/msm_memtypes.h>
-#include <mach/msm_xo.h>
 #include <sound/msm-dai-q6.h>
 #include <sound/apr_audio.h>
 #include "clock.h"
@@ -38,6 +37,7 @@
 #include "devices-msm8x60.h"
 #include "footswitch.h"
 #include "msm_watchdog.h"
+#include "rpm_log.h"
 #include "rpm_stats.h"
 #include "pil-q6v4.h"
 #include "scm-pas.h"
@@ -842,7 +842,6 @@
 	.strap_ahb_upper = 0x00290000,
 	.strap_ahb_lower = 0x00000280,
 	.aclk_reg = SFAB_LPASS_Q6_ACLK_CTL,
-	.xo_id = MSM_XO_PXO,
 	.name = "q6",
 	.pas_id = PAS_Q6,
 	.bus_port = MSM_BUS_MASTER_LPASS_PROC,
@@ -880,7 +879,6 @@
 	.strap_ahb_lower = 0x00000080,
 	.aclk_reg = SFAB_MSS_Q6_FW_ACLK_CTL,
 	.jtag_clk_reg = MSS_Q6FW_JTAG_CLK_CTL,
-	.xo_id = MSM_XO_CXO,
 	.name = "modem_fw",
 	.depends = "q6",
 	.pas_id = PAS_MODEM_FW,
@@ -918,7 +916,6 @@
 	.strap_ahb_lower = 0x00000080,
 	.aclk_reg = SFAB_MSS_Q6_SW_ACLK_CTL,
 	.jtag_clk_reg = MSS_Q6SW_JTAG_CLK_CTL,
-	.xo_id = MSM_XO_CXO,
 	.name = "modem",
 	.depends = "modem_fw",
 	.pas_id = PAS_MODEM_SW,
@@ -1536,6 +1533,7 @@
 };
 
 struct platform_device *msm_footswitch_devices[] = {
+	FS_8X60(FS_MDP,    "fs_mdp"),
 	FS_8X60(FS_ROT,    "fs_rot"),
 	FS_8X60(FS_IJPEG,  "fs_ijpeg"),
 	FS_8X60(FS_VFE,    "fs_vfe"),
@@ -1660,12 +1658,19 @@
 };
 #endif
 
+static struct platform_device msm_lvds_device = {
+	.name   = "lvds",
+	.id     = 0,
+};
+
 void __init msm_fb_register_device(char *name, void *data)
 {
 	if (!strncmp(name, "mdp", 3))
 		msm_register_device(&msm_mdp_device, data);
 	else if (!strncmp(name, "mipi_dsi", 8))
 		msm_register_device(&msm_mipi_dsi1_device, data);
+	else if (!strncmp(name, "lvds", 4))
+		msm_register_device(&msm_lvds_device, data);
 #ifdef CONFIG_MSM_BUS_SCALING
 	else if (!strncmp(name, "dtv", 3))
 		msm_register_device(&msm_dtv_device, data);
@@ -1714,7 +1719,7 @@
 };
 
 #ifdef CONFIG_MSM_MPM
-static uint16_t msm_mpm_irqs_m2a[MSM_MPM_NR_MPM_IRQS] = {
+static uint16_t msm_mpm_irqs_m2a[MSM_MPM_NR_MPM_IRQS] __initdata = {
 	[1] = MSM_GPIO_TO_INT(46),
 	[2] = MSM_GPIO_TO_INT(150),
 	[4] = MSM_GPIO_TO_INT(103),
@@ -1764,7 +1769,7 @@
 	[55] = MSM_GPIO_TO_INT(14),
 };
 
-static uint16_t msm_mpm_bypassed_apps_irqs[] = {
+static uint16_t msm_mpm_bypassed_apps_irqs[] __initdata = {
 	TLMM_MSM_SUMMARY_IRQ,
 	RPM_APCC_CPU0_GP_HIGH_IRQ,
 	RPM_APCC_CPU0_GP_MEDIUM_IRQ,
@@ -1795,7 +1800,7 @@
 	RIVA_APPS_WLAN_DATA_XFER_DONE_IRQ,
 };
 
-struct msm_mpm_device_data msm_mpm_dev_data = {
+struct msm_mpm_device_data msm8960_mpm_dev_data __initdata = {
 	.irqs_m2a = msm_mpm_irqs_m2a,
 	.irqs_m2a_size = ARRAY_SIZE(msm_mpm_irqs_m2a),
 	.bypassed_apps_irqs = msm_mpm_bypassed_apps_irqs,
@@ -2065,7 +2070,7 @@
 		.src = MSM_BUS_MASTER_GRAPHICS_3D,
 		.dst = MSM_BUS_SLAVE_EBI_CH0,
 		.ab = 0,
-		.ib = KGSL_CONVERT_TO_MBPS(1200),
+		.ib = KGSL_CONVERT_TO_MBPS(1000),
 	},
 };
 
@@ -2139,7 +2144,7 @@
 		.src = MSM_BUS_MASTER_GRAPHICS_2D_CORE0,
 		.dst = MSM_BUS_SLAVE_EBI_CH0,
 		.ab = 0,
-		.ib = KGSL_CONVERT_TO_MBPS(1200),
+		.ib = KGSL_CONVERT_TO_MBPS(1000),
 	},
 };
 
@@ -2187,7 +2192,7 @@
 		.src = MSM_BUS_MASTER_GRAPHICS_2D_CORE1,
 		.dst = MSM_BUS_SLAVE_EBI_CH0,
 		.ab = 0,
-		.ib = KGSL_CONVERT_TO_MBPS(1200),
+		.ib = KGSL_CONVERT_TO_MBPS(1000),
 	},
 };
 
@@ -2414,105 +2419,280 @@
 };
 #endif
 
-struct msm_rpm_map_data rpm_map_data[] __initdata = {
-	MSM_RPM_MAP(TRIGGER_TIMED_TO, TRIGGER_TIMED, 1),
-	MSM_RPM_MAP(TRIGGER_TIMED_SCLK_COUNT, TRIGGER_TIMED, 1),
-
-	MSM_RPM_MAP(RPM_CTL, RPM_CTL, 1),
-
-	MSM_RPM_MAP(CXO_CLK, CXO_CLK, 1),
-	MSM_RPM_MAP(PXO_CLK, PXO_CLK, 1),
-	MSM_RPM_MAP(APPS_FABRIC_CLK, APPS_FABRIC_CLK, 1),
-	MSM_RPM_MAP(SYSTEM_FABRIC_CLK, SYSTEM_FABRIC_CLK, 1),
-	MSM_RPM_MAP(MM_FABRIC_CLK, MM_FABRIC_CLK, 1),
-	MSM_RPM_MAP(DAYTONA_FABRIC_CLK, DAYTONA_FABRIC_CLK, 1),
-	MSM_RPM_MAP(SFPB_CLK, SFPB_CLK, 1),
-	MSM_RPM_MAP(CFPB_CLK, CFPB_CLK, 1),
-	MSM_RPM_MAP(MMFPB_CLK, MMFPB_CLK, 1),
-	MSM_RPM_MAP(EBI1_CLK, EBI1_CLK, 1),
-
-	MSM_RPM_MAP(APPS_FABRIC_CFG_HALT_0, APPS_FABRIC_CFG_HALT, 2),
-	MSM_RPM_MAP(APPS_FABRIC_CFG_CLKMOD_0, APPS_FABRIC_CFG_CLKMOD, 3),
-	MSM_RPM_MAP(APPS_FABRIC_CFG_IOCTL, APPS_FABRIC_CFG_IOCTL, 1),
-	MSM_RPM_MAP(APPS_FABRIC_ARB_0, APPS_FABRIC_ARB, 12),
-
-	MSM_RPM_MAP(SYS_FABRIC_CFG_HALT_0, SYS_FABRIC_CFG_HALT, 2),
-	MSM_RPM_MAP(SYS_FABRIC_CFG_CLKMOD_0, SYS_FABRIC_CFG_CLKMOD, 3),
-	MSM_RPM_MAP(SYS_FABRIC_CFG_IOCTL, SYS_FABRIC_CFG_IOCTL, 1),
-	MSM_RPM_MAP(SYSTEM_FABRIC_ARB_0, SYSTEM_FABRIC_ARB, 29),
-
-	MSM_RPM_MAP(MMSS_FABRIC_CFG_HALT_0, MMSS_FABRIC_CFG_HALT, 2),
-	MSM_RPM_MAP(MMSS_FABRIC_CFG_CLKMOD_0, MMSS_FABRIC_CFG_CLKMOD, 3),
-	MSM_RPM_MAP(MMSS_FABRIC_CFG_IOCTL, MMSS_FABRIC_CFG_IOCTL, 1),
-	MSM_RPM_MAP(MM_FABRIC_ARB_0, MM_FABRIC_ARB, 23),
-
-	MSM_RPM_MAP(PM8921_S1_0, PM8921_S1, 2),
-	MSM_RPM_MAP(PM8921_S2_0, PM8921_S2, 2),
-	MSM_RPM_MAP(PM8921_S3_0, PM8921_S3, 2),
-	MSM_RPM_MAP(PM8921_S4_0, PM8921_S4, 2),
-	MSM_RPM_MAP(PM8921_S5_0, PM8921_S5, 2),
-	MSM_RPM_MAP(PM8921_S6_0, PM8921_S6, 2),
-	MSM_RPM_MAP(PM8921_S7_0, PM8921_S7, 2),
-	MSM_RPM_MAP(PM8921_S8_0, PM8921_S8, 2),
-	MSM_RPM_MAP(PM8921_L1_0, PM8921_L1, 2),
-	MSM_RPM_MAP(PM8921_L2_0, PM8921_L2, 2),
-	MSM_RPM_MAP(PM8921_L3_0, PM8921_L3, 2),
-	MSM_RPM_MAP(PM8921_L4_0, PM8921_L4, 2),
-	MSM_RPM_MAP(PM8921_L5_0, PM8921_L5, 2),
-	MSM_RPM_MAP(PM8921_L6_0, PM8921_L6, 2),
-	MSM_RPM_MAP(PM8921_L7_0, PM8921_L7, 2),
-	MSM_RPM_MAP(PM8921_L8_0, PM8921_L8, 2),
-	MSM_RPM_MAP(PM8921_L9_0, PM8921_L9, 2),
-	MSM_RPM_MAP(PM8921_L10_0, PM8921_L10, 2),
-	MSM_RPM_MAP(PM8921_L11_0, PM8921_L11, 2),
-	MSM_RPM_MAP(PM8921_L12_0, PM8921_L12, 2),
-	MSM_RPM_MAP(PM8921_L13_0, PM8921_L13, 2),
-	MSM_RPM_MAP(PM8921_L14_0, PM8921_L14, 2),
-	MSM_RPM_MAP(PM8921_L15_0, PM8921_L15, 2),
-	MSM_RPM_MAP(PM8921_L16_0, PM8921_L16, 2),
-	MSM_RPM_MAP(PM8921_L17_0, PM8921_L17, 2),
-	MSM_RPM_MAP(PM8921_L18_0, PM8921_L18, 2),
-	MSM_RPM_MAP(PM8921_L19_0, PM8921_L19, 2),
-	MSM_RPM_MAP(PM8921_L20_0, PM8921_L20, 2),
-	MSM_RPM_MAP(PM8921_L21_0, PM8921_L21, 2),
-	MSM_RPM_MAP(PM8921_L22_0, PM8921_L22, 2),
-	MSM_RPM_MAP(PM8921_L23_0, PM8921_L23, 2),
-	MSM_RPM_MAP(PM8921_L24_0, PM8921_L24, 2),
-	MSM_RPM_MAP(PM8921_L25_0, PM8921_L25, 2),
-	MSM_RPM_MAP(PM8921_L26_0, PM8921_L26, 2),
-	MSM_RPM_MAP(PM8921_L27_0, PM8921_L27, 2),
-	MSM_RPM_MAP(PM8921_L28_0, PM8921_L28, 2),
-	MSM_RPM_MAP(PM8921_L29_0, PM8921_L29, 2),
-	MSM_RPM_MAP(PM8921_CLK1_0, PM8921_CLK1, 2),
-	MSM_RPM_MAP(PM8921_CLK2_0, PM8921_CLK2, 2),
-	MSM_RPM_MAP(PM8921_LVS1, PM8921_LVS1, 1),
-	MSM_RPM_MAP(PM8921_LVS2, PM8921_LVS2, 1),
-	MSM_RPM_MAP(PM8921_LVS3, PM8921_LVS3, 1),
-	MSM_RPM_MAP(PM8921_LVS4, PM8921_LVS4, 1),
-	MSM_RPM_MAP(PM8921_LVS5, PM8921_LVS5, 1),
-	MSM_RPM_MAP(PM8921_LVS6, PM8921_LVS6, 1),
-	MSM_RPM_MAP(PM8921_LVS7, PM8921_LVS7, 1),
-	MSM_RPM_MAP(NCP_0, NCP, 2),
-	MSM_RPM_MAP(CXO_BUFFERS, CXO_BUFFERS, 1),
-	MSM_RPM_MAP(USB_OTG_SWITCH, USB_OTG_SWITCH, 1),
-	MSM_RPM_MAP(HDMI_SWITCH, HDMI_SWITCH, 1),
-	MSM_RPM_MAP(DDR_DMM_0, DDR_DMM, 2),
-	MSM_RPM_MAP(QDSS_CLK, QDSS_CLK, 1),
+struct msm_rpm_platform_data msm8960_rpm_data __initdata = {
+	.reg_base_addrs = {
+		[MSM_RPM_PAGE_STATUS] = MSM_RPM_BASE,
+		[MSM_RPM_PAGE_CTRL] = MSM_RPM_BASE + 0x400,
+		[MSM_RPM_PAGE_REQ] = MSM_RPM_BASE + 0x600,
+		[MSM_RPM_PAGE_ACK] = MSM_RPM_BASE + 0xa00,
+	},
+	.irq_ack = RPM_APCC_CPU0_GP_HIGH_IRQ,
+	.ipc_rpm_reg = MSM_APCS_GCC_BASE + 0x008,
+	.ipc_rpm_val = 4,
+	.target_id = {
+		MSM_RPM_MAP(8960, NOTIFICATION_CONFIGURED_0, NOTIFICATION, 4),
+		MSM_RPM_MAP(8960, NOTIFICATION_REGISTERED_0, NOTIFICATION, 4),
+		MSM_RPM_MAP(8960, INVALIDATE_0, INVALIDATE, 8),
+		MSM_RPM_MAP(8960, TRIGGER_TIMED_TO, TRIGGER_TIMED, 1),
+		MSM_RPM_MAP(8960, TRIGGER_TIMED_SCLK_COUNT, TRIGGER_TIMED, 1),
+		MSM_RPM_MAP(8960, RPM_CTL, RPM_CTL, 1),
+		MSM_RPM_MAP(8960, CXO_CLK, CXO_CLK, 1),
+		MSM_RPM_MAP(8960, PXO_CLK, PXO_CLK, 1),
+		MSM_RPM_MAP(8960, APPS_FABRIC_CLK, APPS_FABRIC_CLK, 1),
+		MSM_RPM_MAP(8960, SYSTEM_FABRIC_CLK, SYSTEM_FABRIC_CLK, 1),
+		MSM_RPM_MAP(8960, MM_FABRIC_CLK, MM_FABRIC_CLK, 1),
+		MSM_RPM_MAP(8960, DAYTONA_FABRIC_CLK, DAYTONA_FABRIC_CLK, 1),
+		MSM_RPM_MAP(8960, SFPB_CLK, SFPB_CLK, 1),
+		MSM_RPM_MAP(8960, CFPB_CLK, CFPB_CLK, 1),
+		MSM_RPM_MAP(8960, MMFPB_CLK, MMFPB_CLK, 1),
+		MSM_RPM_MAP(8960, EBI1_CLK, EBI1_CLK, 1),
+		MSM_RPM_MAP(8960, APPS_FABRIC_CFG_HALT_0,
+				APPS_FABRIC_CFG_HALT, 2),
+		MSM_RPM_MAP(8960, APPS_FABRIC_CFG_CLKMOD_0,
+				APPS_FABRIC_CFG_CLKMOD, 3),
+		MSM_RPM_MAP(8960, APPS_FABRIC_CFG_IOCTL,
+				APPS_FABRIC_CFG_IOCTL, 1),
+		MSM_RPM_MAP(8960, APPS_FABRIC_ARB_0, APPS_FABRIC_ARB, 12),
+		MSM_RPM_MAP(8960, SYS_FABRIC_CFG_HALT_0,
+				SYS_FABRIC_CFG_HALT, 2),
+		MSM_RPM_MAP(8960, SYS_FABRIC_CFG_CLKMOD_0,
+				SYS_FABRIC_CFG_CLKMOD, 3),
+		MSM_RPM_MAP(8960, SYS_FABRIC_CFG_IOCTL,
+				SYS_FABRIC_CFG_IOCTL, 1),
+		MSM_RPM_MAP(8960, SYSTEM_FABRIC_ARB_0,
+				SYSTEM_FABRIC_ARB, 29),
+		MSM_RPM_MAP(8960, MMSS_FABRIC_CFG_HALT_0,
+				MMSS_FABRIC_CFG_HALT, 2),
+		MSM_RPM_MAP(8960, MMSS_FABRIC_CFG_CLKMOD_0,
+				MMSS_FABRIC_CFG_CLKMOD, 3),
+		MSM_RPM_MAP(8960, MMSS_FABRIC_CFG_IOCTL,
+				MMSS_FABRIC_CFG_IOCTL, 1),
+		MSM_RPM_MAP(8960, MM_FABRIC_ARB_0, MM_FABRIC_ARB, 23),
+		MSM_RPM_MAP(8960, PM8921_S1_0, PM8921_S1, 2),
+		MSM_RPM_MAP(8960, PM8921_S2_0, PM8921_S2, 2),
+		MSM_RPM_MAP(8960, PM8921_S3_0, PM8921_S3, 2),
+		MSM_RPM_MAP(8960, PM8921_S4_0, PM8921_S4, 2),
+		MSM_RPM_MAP(8960, PM8921_S5_0, PM8921_S5, 2),
+		MSM_RPM_MAP(8960, PM8921_S6_0, PM8921_S6, 2),
+		MSM_RPM_MAP(8960, PM8921_S7_0, PM8921_S7, 2),
+		MSM_RPM_MAP(8960, PM8921_S8_0, PM8921_S8, 2),
+		MSM_RPM_MAP(8960, PM8921_L1_0, PM8921_L1, 2),
+		MSM_RPM_MAP(8960, PM8921_L2_0, PM8921_L2, 2),
+		MSM_RPM_MAP(8960, PM8921_L3_0, PM8921_L3, 2),
+		MSM_RPM_MAP(8960, PM8921_L4_0, PM8921_L4, 2),
+		MSM_RPM_MAP(8960, PM8921_L5_0, PM8921_L5, 2),
+		MSM_RPM_MAP(8960, PM8921_L6_0, PM8921_L6, 2),
+		MSM_RPM_MAP(8960, PM8921_L7_0, PM8921_L7, 2),
+		MSM_RPM_MAP(8960, PM8921_L8_0, PM8921_L8, 2),
+		MSM_RPM_MAP(8960, PM8921_L9_0, PM8921_L9, 2),
+		MSM_RPM_MAP(8960, PM8921_L10_0, PM8921_L10, 2),
+		MSM_RPM_MAP(8960, PM8921_L11_0, PM8921_L11, 2),
+		MSM_RPM_MAP(8960, PM8921_L12_0, PM8921_L12, 2),
+		MSM_RPM_MAP(8960, PM8921_L13_0, PM8921_L13, 2),
+		MSM_RPM_MAP(8960, PM8921_L14_0, PM8921_L14, 2),
+		MSM_RPM_MAP(8960, PM8921_L15_0, PM8921_L15, 2),
+		MSM_RPM_MAP(8960, PM8921_L16_0, PM8921_L16, 2),
+		MSM_RPM_MAP(8960, PM8921_L17_0, PM8921_L17, 2),
+		MSM_RPM_MAP(8960, PM8921_L18_0, PM8921_L18, 2),
+		MSM_RPM_MAP(8960, PM8921_L19_0, PM8921_L19, 2),
+		MSM_RPM_MAP(8960, PM8921_L20_0, PM8921_L20, 2),
+		MSM_RPM_MAP(8960, PM8921_L21_0, PM8921_L21, 2),
+		MSM_RPM_MAP(8960, PM8921_L22_0, PM8921_L22, 2),
+		MSM_RPM_MAP(8960, PM8921_L23_0, PM8921_L23, 2),
+		MSM_RPM_MAP(8960, PM8921_L24_0, PM8921_L24, 2),
+		MSM_RPM_MAP(8960, PM8921_L25_0, PM8921_L25, 2),
+		MSM_RPM_MAP(8960, PM8921_L26_0, PM8921_L26, 2),
+		MSM_RPM_MAP(8960, PM8921_L27_0, PM8921_L27, 2),
+		MSM_RPM_MAP(8960, PM8921_L28_0, PM8921_L28, 2),
+		MSM_RPM_MAP(8960, PM8921_L29_0, PM8921_L29, 2),
+		MSM_RPM_MAP(8960, PM8921_CLK1_0, PM8921_CLK1, 2),
+		MSM_RPM_MAP(8960, PM8921_CLK2_0, PM8921_CLK2, 2),
+		MSM_RPM_MAP(8960, PM8921_LVS1, PM8921_LVS1, 1),
+		MSM_RPM_MAP(8960, PM8921_LVS2, PM8921_LVS2, 1),
+		MSM_RPM_MAP(8960, PM8921_LVS3, PM8921_LVS3, 1),
+		MSM_RPM_MAP(8960, PM8921_LVS4, PM8921_LVS4, 1),
+		MSM_RPM_MAP(8960, PM8921_LVS5, PM8921_LVS5, 1),
+		MSM_RPM_MAP(8960, PM8921_LVS6, PM8921_LVS6, 1),
+		MSM_RPM_MAP(8960, PM8921_LVS7, PM8921_LVS7, 1),
+		MSM_RPM_MAP(8960, NCP_0, NCP, 2),
+		MSM_RPM_MAP(8960, CXO_BUFFERS, CXO_BUFFERS, 1),
+		MSM_RPM_MAP(8960, USB_OTG_SWITCH, USB_OTG_SWITCH, 1),
+		MSM_RPM_MAP(8960, HDMI_SWITCH, HDMI_SWITCH, 1),
+		MSM_RPM_MAP(8960, DDR_DMM_0, DDR_DMM, 2),
+		MSM_RPM_MAP(8960, QDSS_CLK, QDSS_CLK, 1),
+	},
+	.target_status = {
+		MSM_RPM_STATUS_ID_MAP(8960, VERSION_MAJOR),
+		MSM_RPM_STATUS_ID_MAP(8960, VERSION_MINOR),
+		MSM_RPM_STATUS_ID_MAP(8960, VERSION_BUILD),
+		MSM_RPM_STATUS_ID_MAP(8960, SUPPORTED_RESOURCES_0),
+		MSM_RPM_STATUS_ID_MAP(8960, SUPPORTED_RESOURCES_1),
+		MSM_RPM_STATUS_ID_MAP(8960, SUPPORTED_RESOURCES_2),
+		MSM_RPM_STATUS_ID_MAP(8960, RESERVED_SUPPORTED_RESOURCES_0),
+		MSM_RPM_STATUS_ID_MAP(8960, SEQUENCE),
+		MSM_RPM_STATUS_ID_MAP(8960, RPM_CTL),
+		MSM_RPM_STATUS_ID_MAP(8960, CXO_CLK),
+		MSM_RPM_STATUS_ID_MAP(8960, PXO_CLK),
+		MSM_RPM_STATUS_ID_MAP(8960, APPS_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(8960, SYSTEM_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(8960, MM_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(8960, DAYTONA_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(8960, SFPB_CLK),
+		MSM_RPM_STATUS_ID_MAP(8960, CFPB_CLK),
+		MSM_RPM_STATUS_ID_MAP(8960, MMFPB_CLK),
+		MSM_RPM_STATUS_ID_MAP(8960, EBI1_CLK),
+		MSM_RPM_STATUS_ID_MAP(8960, APPS_FABRIC_CFG_HALT),
+		MSM_RPM_STATUS_ID_MAP(8960, APPS_FABRIC_CFG_CLKMOD),
+		MSM_RPM_STATUS_ID_MAP(8960, APPS_FABRIC_CFG_IOCTL),
+		MSM_RPM_STATUS_ID_MAP(8960, APPS_FABRIC_ARB),
+		MSM_RPM_STATUS_ID_MAP(8960, SYS_FABRIC_CFG_HALT),
+		MSM_RPM_STATUS_ID_MAP(8960, SYS_FABRIC_CFG_CLKMOD),
+		MSM_RPM_STATUS_ID_MAP(8960, SYS_FABRIC_CFG_IOCTL),
+		MSM_RPM_STATUS_ID_MAP(8960, SYSTEM_FABRIC_ARB),
+		MSM_RPM_STATUS_ID_MAP(8960, MMSS_FABRIC_CFG_HALT),
+		MSM_RPM_STATUS_ID_MAP(8960, MMSS_FABRIC_CFG_CLKMOD),
+		MSM_RPM_STATUS_ID_MAP(8960, MMSS_FABRIC_CFG_IOCTL),
+		MSM_RPM_STATUS_ID_MAP(8960, MM_FABRIC_ARB),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_S1_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_S1_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_S2_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_S2_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_S3_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_S3_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_S4_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_S4_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_S5_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_S5_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_S6_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_S6_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_S7_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_S7_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_S8_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_S8_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L1_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L1_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L2_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L2_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L3_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L3_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L4_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L4_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L5_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L5_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L6_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L6_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L7_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L7_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L8_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L8_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L9_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L9_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L10_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L10_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L11_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L11_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L12_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L12_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L13_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L13_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L14_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L14_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L15_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L15_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L16_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L16_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L17_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L17_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L18_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L18_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L19_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L19_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L20_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L20_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L21_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L21_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L22_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L22_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L23_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L23_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L24_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L24_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L25_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L25_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L26_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L26_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L27_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L27_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L28_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L28_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L29_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_L29_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_CLK1_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_CLK1_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_CLK2_0),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_CLK2_1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_LVS1),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_LVS2),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_LVS3),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_LVS4),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_LVS5),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_LVS6),
+		MSM_RPM_STATUS_ID_MAP(8960, PM8921_LVS7),
+		MSM_RPM_STATUS_ID_MAP(8960, NCP_0),
+		MSM_RPM_STATUS_ID_MAP(8960, NCP_1),
+		MSM_RPM_STATUS_ID_MAP(8960, CXO_BUFFERS),
+		MSM_RPM_STATUS_ID_MAP(8960, USB_OTG_SWITCH),
+		MSM_RPM_STATUS_ID_MAP(8960, HDMI_SWITCH),
+		MSM_RPM_STATUS_ID_MAP(8960, DDR_DMM_0),
+		MSM_RPM_STATUS_ID_MAP(8960, DDR_DMM_1),
+		MSM_RPM_STATUS_ID_MAP(8960, EBI1_CH0_RANGE),
+		MSM_RPM_STATUS_ID_MAP(8960, EBI1_CH1_RANGE),
+	},
+	.target_ctrl_id = {
+		MSM_RPM_CTRL_MAP(8960, VERSION_MAJOR),
+		MSM_RPM_CTRL_MAP(8960, VERSION_MINOR),
+		MSM_RPM_CTRL_MAP(8960, VERSION_BUILD),
+		MSM_RPM_CTRL_MAP(8960, REQ_CTX_0),
+		MSM_RPM_CTRL_MAP(8960, REQ_SEL_0),
+		MSM_RPM_CTRL_MAP(8960, ACK_CTX_0),
+		MSM_RPM_CTRL_MAP(8960, ACK_SEL_0),
+	},
+	.sel_invalidate = MSM_RPM_8960_SEL_INVALIDATE,
+	.sel_notification = MSM_RPM_8960_SEL_NOTIFICATION,
+	.sel_last = MSM_RPM_8960_SEL_LAST,
+	.ver = {3, 0, 0},
 };
 
-unsigned int rpm_map_data_size = ARRAY_SIZE(rpm_map_data);
-
-struct platform_device msm_rpm_device = {
+struct platform_device msm8960_rpm_device = {
 	.name   = "msm_rpm",
 	.id     = -1,
 };
 
+static struct msm_rpm_log_platform_data msm_rpm_log_pdata = {
+	.phys_addr_base = 0x0010C000,
+	.reg_offsets = {
+		[MSM_RPM_LOG_PAGE_INDICES] = 0x00000080,
+		[MSM_RPM_LOG_PAGE_BUFFER]  = 0x000000A0,
+	},
+	.phys_size = SZ_8K,
+	.log_len = 4096,		  /* log's buffer length in bytes */
+	.log_len_mask = (4096 >> 2) - 1,  /* length mask in units of u32 */
+};
+
+struct platform_device msm8960_rpm_log_device = {
+	.name	= "msm_rpm_log",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &msm_rpm_log_pdata,
+	},
+};
+
 static struct msm_rpmstats_platform_data msm_rpm_stat_pdata = {
 	.phys_addr_base = 0x0010D204,
 	.phys_size = SZ_8K,
 };
 
-struct platform_device msm_rpm_stat_device = {
+struct platform_device msm8960_rpm_stat_device = {
 	.name = "msm_rpm_stat",
 	.id = -1,
 	.dev = {
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 314d064..3944a93 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -30,12 +30,14 @@
 #include <asm/hardware/cache-l2x0.h>
 #include <mach/msm_sps.h>
 #include <mach/dma.h>
+#include "pm.h"
 #include "devices.h"
 #include "mpm.h"
 #include "spm.h"
-#include <mach/pm.h>
 #include "rpm_resources.h"
 #include "msm_watchdog.h"
+#include "rpm_stats.h"
+#include "rpm_log.h"
 
 /* Address of GSBI blocks */
 #define MSM_GSBI1_PHYS          0x16000000
@@ -100,7 +102,9 @@
 };
 
 #define MSM_USB_BAM_BASE     0x12502000
-#define MSM_USB_BAM_SIZE     0x3DFFF
+#define MSM_USB_BAM_SIZE     SZ_16K
+#define MSM_HSIC_BAM_BASE    0x12542000
+#define MSM_HSIC_BAM_SIZE    SZ_16K
 
 static struct resource resources_otg[] = {
 	{
@@ -142,7 +146,7 @@
 	{
 		.name	= "usb_bam_addr",
 		.start	= MSM_USB_BAM_BASE,
-		.end	= MSM_USB_BAM_BASE + MSM_USB_BAM_SIZE,
+		.end	= MSM_USB_BAM_BASE + MSM_USB_BAM_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
@@ -151,6 +155,18 @@
 		.end	= USB1_HS_BAM_IRQ,
 		.flags	= IORESOURCE_IRQ,
 	},
+	{
+		.name	= "hsic_bam_addr",
+		.start	= MSM_HSIC_BAM_BASE,
+		.end	= MSM_HSIC_BAM_BASE + MSM_HSIC_BAM_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "hsic_bam_irq",
+		.start	= USB_HSIC_BAM_IRQ,
+		.end	= USB_HSIC_BAM_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 struct platform_device msm_device_usb_bam = {
@@ -724,72 +740,148 @@
 static int __init l2x0_cache_init(void){ return 0; }
 #endif
 
-struct msm_rpm_map_data rpm_map_data[] __initdata = {
-	MSM_RPM_MAP(TRIGGER_TIMED_TO, TRIGGER_TIMED, 1),
-	MSM_RPM_MAP(TRIGGER_TIMED_SCLK_COUNT, TRIGGER_TIMED, 1),
-
-	MSM_RPM_MAP(RPM_CTL, RPM_CTL, 1),
-
-	MSM_RPM_MAP(CXO_CLK, CXO_CLK, 1),
-	MSM_RPM_MAP(SYSTEM_FABRIC_CLK, SYSTEM_FABRIC_CLK, 1),
-	MSM_RPM_MAP(DAYTONA_FABRIC_CLK, DAYTONA_FABRIC_CLK, 1),
-	MSM_RPM_MAP(SFPB_CLK, SFPB_CLK, 1),
-	MSM_RPM_MAP(CFPB_CLK, CFPB_CLK, 1),
-	MSM_RPM_MAP(EBI1_CLK, EBI1_CLK, 1),
-
-	MSM_RPM_MAP(SYS_FABRIC_CFG_HALT_0, SYS_FABRIC_CFG_HALT, 2),
-	MSM_RPM_MAP(SYS_FABRIC_CFG_CLKMOD_0, SYS_FABRIC_CFG_CLKMOD, 3),
-	MSM_RPM_MAP(SYS_FABRIC_CFG_IOCTL, SYS_FABRIC_CFG_IOCTL, 1),
-	MSM_RPM_MAP(SYSTEM_FABRIC_ARB_0, SYSTEM_FABRIC_ARB, 27),
-
-	MSM_RPM_MAP(PM8018_S1_0, PM8018_S1, 2),
-	MSM_RPM_MAP(PM8018_S2_0, PM8018_S2, 2),
-	MSM_RPM_MAP(PM8018_S3_0, PM8018_S3, 2),
-	MSM_RPM_MAP(PM8018_S4_0, PM8018_S4, 2),
-	MSM_RPM_MAP(PM8018_S5_0, PM8018_S5, 2),
-	MSM_RPM_MAP(PM8018_L1_0, PM8018_L1, 2),
-	MSM_RPM_MAP(PM8018_L2_0, PM8018_L2, 2),
-	MSM_RPM_MAP(PM8018_L3_0, PM8018_L3, 2),
-	MSM_RPM_MAP(PM8018_L4_0, PM8018_L4, 2),
-	MSM_RPM_MAP(PM8018_L5_0, PM8018_L5, 2),
-	MSM_RPM_MAP(PM8018_L6_0, PM8018_L6, 2),
-	MSM_RPM_MAP(PM8018_L7_0, PM8018_L7, 2),
-	MSM_RPM_MAP(PM8018_L8_0, PM8018_L8, 2),
-	MSM_RPM_MAP(PM8018_L9_0, PM8018_L9, 2),
-	MSM_RPM_MAP(PM8018_L10_0, PM8018_L10, 2),
-	MSM_RPM_MAP(PM8018_L11_0, PM8018_L11, 2),
-	MSM_RPM_MAP(PM8018_L12_0, PM8018_L12, 2),
-	MSM_RPM_MAP(PM8018_L13_0, PM8018_L13, 2),
-	MSM_RPM_MAP(PM8018_L14_0, PM8018_L14, 2),
-	MSM_RPM_MAP(PM8018_LVS1, PM8018_LVS1, 1),
-	MSM_RPM_MAP(NCP_0, NCP, 2),
-	MSM_RPM_MAP(CXO_BUFFERS, CXO_BUFFERS, 1),
-	MSM_RPM_MAP(USB_OTG_SWITCH, USB_OTG_SWITCH, 1),
-	MSM_RPM_MAP(HDMI_SWITCH, HDMI_SWITCH, 1),
-};
-unsigned int rpm_map_data_size = ARRAY_SIZE(rpm_map_data);
-
-static struct msm_rpm_platform_data msm_rpm_data = {
+struct msm_rpm_platform_data msm9615_rpm_data __initdata = {
 	.reg_base_addrs = {
 		[MSM_RPM_PAGE_STATUS] = MSM_RPM_BASE,
 		[MSM_RPM_PAGE_CTRL] = MSM_RPM_BASE + 0x400,
 		[MSM_RPM_PAGE_REQ] = MSM_RPM_BASE + 0x600,
 		[MSM_RPM_PAGE_ACK] = MSM_RPM_BASE + 0xa00,
 	},
-
 	.irq_ack = RPM_APCC_CPU0_GP_HIGH_IRQ,
-	.irq_err = RPM_APCC_CPU0_GP_LOW_IRQ,
-	.irq_vmpm = RPM_APCC_CPU0_GP_MEDIUM_IRQ,
-	.msm_apps_ipc_rpm_reg = MSM_APCS_GCC_BASE + 0x008,
-	.msm_apps_ipc_rpm_val = 4,
+	.ipc_rpm_reg = MSM_APCS_GCC_BASE + 0x008,
+	.ipc_rpm_val = 4,
+	.target_id = {
+		MSM_RPM_MAP(9615, NOTIFICATION_CONFIGURED_0, NOTIFICATION, 4),
+		MSM_RPM_MAP(9615, NOTIFICATION_REGISTERED_0, NOTIFICATION, 4),
+		MSM_RPM_MAP(9615, INVALIDATE_0, INVALIDATE, 8),
+		MSM_RPM_MAP(9615, TRIGGER_TIMED_TO, TRIGGER_TIMED, 1),
+		MSM_RPM_MAP(9615, TRIGGER_TIMED_SCLK_COUNT, TRIGGER_TIMED, 1),
+		MSM_RPM_MAP(9615, RPM_CTL, RPM_CTL, 1),
+		MSM_RPM_MAP(9615, CXO_CLK, CXO_CLK, 1),
+		MSM_RPM_MAP(9615, SYSTEM_FABRIC_CLK, SYSTEM_FABRIC_CLK, 1),
+		MSM_RPM_MAP(9615, DAYTONA_FABRIC_CLK, DAYTONA_FABRIC_CLK, 1),
+		MSM_RPM_MAP(9615, SFPB_CLK, SFPB_CLK, 1),
+		MSM_RPM_MAP(9615, CFPB_CLK, CFPB_CLK, 1),
+		MSM_RPM_MAP(9615, EBI1_CLK, EBI1_CLK, 1),
+		MSM_RPM_MAP(9615, SYS_FABRIC_CFG_HALT_0,
+				SYS_FABRIC_CFG_HALT, 2),
+		MSM_RPM_MAP(9615, SYS_FABRIC_CFG_CLKMOD_0,
+				SYS_FABRIC_CFG_CLKMOD, 3),
+		MSM_RPM_MAP(9615, SYS_FABRIC_CFG_IOCTL,
+				SYS_FABRIC_CFG_IOCTL, 1),
+		MSM_RPM_MAP(9615, SYSTEM_FABRIC_ARB_0,
+				SYSTEM_FABRIC_ARB, 27),
+		MSM_RPM_MAP(9615, PM8018_S1_0, PM8018_S1, 2),
+		MSM_RPM_MAP(9615, PM8018_S2_0, PM8018_S2, 2),
+		MSM_RPM_MAP(9615, PM8018_S3_0, PM8018_S3, 2),
+		MSM_RPM_MAP(9615, PM8018_S4_0, PM8018_S4, 2),
+		MSM_RPM_MAP(9615, PM8018_S5_0, PM8018_S5, 2),
+		MSM_RPM_MAP(9615, PM8018_L1_0, PM8018_L1, 2),
+		MSM_RPM_MAP(9615, PM8018_L2_0, PM8018_L2, 2),
+		MSM_RPM_MAP(9615, PM8018_L3_0, PM8018_L3, 2),
+		MSM_RPM_MAP(9615, PM8018_L4_0, PM8018_L4, 2),
+		MSM_RPM_MAP(9615, PM8018_L5_0, PM8018_L5, 2),
+		MSM_RPM_MAP(9615, PM8018_L6_0, PM8018_L6, 2),
+		MSM_RPM_MAP(9615, PM8018_L7_0, PM8018_L7, 2),
+		MSM_RPM_MAP(9615, PM8018_L8_0, PM8018_L8, 2),
+		MSM_RPM_MAP(9615, PM8018_L9_0, PM8018_L9, 2),
+		MSM_RPM_MAP(9615, PM8018_L10_0, PM8018_L10, 2),
+		MSM_RPM_MAP(9615, PM8018_L11_0, PM8018_L11, 2),
+		MSM_RPM_MAP(9615, PM8018_L12_0, PM8018_L12, 2),
+		MSM_RPM_MAP(9615, PM8018_L13_0, PM8018_L13, 2),
+		MSM_RPM_MAP(9615, PM8018_L14_0, PM8018_L14, 2),
+		MSM_RPM_MAP(9615, PM8018_LVS1, PM8018_LVS1, 1),
+		MSM_RPM_MAP(9615, NCP_0, NCP, 2),
+		MSM_RPM_MAP(9615, CXO_BUFFERS, CXO_BUFFERS, 1),
+		MSM_RPM_MAP(9615, USB_OTG_SWITCH, USB_OTG_SWITCH, 1),
+		MSM_RPM_MAP(9615, HDMI_SWITCH, HDMI_SWITCH, 1),
+	},
+	.target_status = {
+		MSM_RPM_STATUS_ID_MAP(9615, VERSION_MAJOR),
+		MSM_RPM_STATUS_ID_MAP(9615, VERSION_MINOR),
+		MSM_RPM_STATUS_ID_MAP(9615, VERSION_BUILD),
+		MSM_RPM_STATUS_ID_MAP(9615, SUPPORTED_RESOURCES_0),
+		MSM_RPM_STATUS_ID_MAP(9615, SUPPORTED_RESOURCES_1),
+		MSM_RPM_STATUS_ID_MAP(9615, SUPPORTED_RESOURCES_2),
+		MSM_RPM_STATUS_ID_MAP(9615, RESERVED_SUPPORTED_RESOURCES_0),
+		MSM_RPM_STATUS_ID_MAP(9615, SEQUENCE),
+		MSM_RPM_STATUS_ID_MAP(9615, RPM_CTL),
+		MSM_RPM_STATUS_ID_MAP(9615, CXO_CLK),
+		MSM_RPM_STATUS_ID_MAP(9615, SYSTEM_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(9615, DAYTONA_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(9615, SFPB_CLK),
+		MSM_RPM_STATUS_ID_MAP(9615, CFPB_CLK),
+		MSM_RPM_STATUS_ID_MAP(9615, EBI1_CLK),
+		MSM_RPM_STATUS_ID_MAP(9615, SYS_FABRIC_CFG_HALT),
+		MSM_RPM_STATUS_ID_MAP(9615, SYS_FABRIC_CFG_CLKMOD),
+		MSM_RPM_STATUS_ID_MAP(9615, SYS_FABRIC_CFG_IOCTL),
+		MSM_RPM_STATUS_ID_MAP(9615, SYSTEM_FABRIC_ARB),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_S1_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_S1_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_S2_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_S2_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_S3_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_S3_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_S4_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_S4_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_S5_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_S5_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L1_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L1_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L2_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L2_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L3_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L3_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L4_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L4_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L5_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L5_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L6_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L6_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L7_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L7_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L8_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L8_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L9_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L9_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L10_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L10_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L11_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L11_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L12_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L12_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L13_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L13_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L14_0),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_L14_1),
+		MSM_RPM_STATUS_ID_MAP(9615, PM8018_LVS1),
+		MSM_RPM_STATUS_ID_MAP(9615, NCP_0),
+		MSM_RPM_STATUS_ID_MAP(9615, NCP_1),
+		MSM_RPM_STATUS_ID_MAP(9615, CXO_BUFFERS),
+		MSM_RPM_STATUS_ID_MAP(9615, USB_OTG_SWITCH),
+		MSM_RPM_STATUS_ID_MAP(9615, HDMI_SWITCH),
+	},
+	.target_ctrl_id = {
+		MSM_RPM_CTRL_MAP(9615, VERSION_MAJOR),
+		MSM_RPM_CTRL_MAP(9615, VERSION_MINOR),
+		MSM_RPM_CTRL_MAP(9615, VERSION_BUILD),
+		MSM_RPM_CTRL_MAP(9615, REQ_CTX_0),
+		MSM_RPM_CTRL_MAP(9615, REQ_SEL_0),
+		MSM_RPM_CTRL_MAP(9615, ACK_CTX_0),
+		MSM_RPM_CTRL_MAP(9615, ACK_SEL_0),
+	},
+	.sel_invalidate = MSM_RPM_9615_SEL_INVALIDATE,
+	.sel_notification = MSM_RPM_9615_SEL_NOTIFICATION,
+	.sel_last = MSM_RPM_9615_SEL_LAST,
+	.ver = {3, 0, 0},
 };
 
-struct platform_device msm_rpm_device = {
+struct platform_device msm9615_rpm_device = {
 	.name   = "msm_rpm",
 	.id     = -1,
 };
 
-static uint16_t msm_mpm_irqs_m2a[MSM_MPM_NR_MPM_IRQS] = {
+static uint16_t msm_mpm_irqs_m2a[MSM_MPM_NR_MPM_IRQS] __initdata = {
 	[4] = MSM_GPIO_TO_INT(30),
 	[5] = MSM_GPIO_TO_INT(59),
 	[6] = MSM_GPIO_TO_INT(81),
@@ -833,7 +925,7 @@
 	[55] = MSM_GPIO_TO_INT(27),
 };
 
-static uint16_t msm_mpm_bypassed_apps_irqs[] = {
+static uint16_t msm_mpm_bypassed_apps_irqs[] __initdata = {
 	TLMM_MSM_SUMMARY_IRQ,
 	RPM_APCC_CPU0_GP_HIGH_IRQ,
 	RPM_APCC_CPU0_GP_MEDIUM_IRQ,
@@ -848,7 +940,7 @@
 	A2_BAM_IRQ,
 };
 
-struct msm_mpm_device_data msm_mpm_dev_data = {
+struct msm_mpm_device_data msm9615_mpm_dev_data __initdata = {
 	.irqs_m2a = msm_mpm_irqs_m2a,
 	.irqs_m2a_size = ARRAY_SIZE(msm_mpm_irqs_m2a),
 	.bypassed_apps_irqs = msm_mpm_bypassed_apps_irqs,
@@ -911,7 +1003,6 @@
 		true,
 		100, 8000, 100000, 1,
 	},
-
 	{
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE,
 		MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
@@ -938,12 +1029,70 @@
 	},
 };
 
+static struct msm_rpmrs_platform_data msm_rpmrs_data __initdata = {
+	.levels = &msm_rpmrs_levels[0],
+	.num_levels = ARRAY_SIZE(msm_rpmrs_levels),
+	.vdd_mem_levels  = {
+		[MSM_RPMRS_VDD_MEM_RET_LOW]     = 750000,
+		[MSM_RPMRS_VDD_MEM_RET_HIGH]    = 750000,
+		[MSM_RPMRS_VDD_MEM_ACTIVE]      = 1050000,
+		[MSM_RPMRS_VDD_MEM_MAX]         = 1150000,
+	},
+	.vdd_dig_levels = {
+		[MSM_RPMRS_VDD_DIG_RET_LOW]     = 500000,
+		[MSM_RPMRS_VDD_DIG_RET_HIGH]    = 750000,
+		[MSM_RPMRS_VDD_DIG_ACTIVE]      = 950000,
+		[MSM_RPMRS_VDD_DIG_MAX]         = 1150000,
+	},
+	.vdd_mask = 0x7FFFFF,
+	.rpmrs_target_id = {
+		[MSM_RPMRS_ID_PXO_CLK]          = MSM_RPM_ID_CXO_CLK,
+		[MSM_RPMRS_ID_L2_CACHE_CTL]     = MSM_RPM_ID_LAST,
+		[MSM_RPMRS_ID_VDD_DIG_0]        = MSM_RPM_ID_PM8018_S1_0,
+		[MSM_RPMRS_ID_VDD_DIG_1]        = MSM_RPM_ID_PM8018_S1_1,
+		[MSM_RPMRS_ID_VDD_MEM_0]        = MSM_RPM_ID_PM8018_L9_0,
+		[MSM_RPMRS_ID_VDD_MEM_1]        = MSM_RPM_ID_PM8018_L9_1,
+		[MSM_RPMRS_ID_RPM_CTL]          = MSM_RPM_ID_RPM_CTL,
+	},
+};
+
+static struct msm_rpmstats_platform_data msm_rpm_stat_pdata = {
+	.phys_addr_base = 0x0010D204,
+	.phys_size = SZ_8K,
+};
+
+struct platform_device msm9615_rpm_stat_device = {
+	.name = "msm_rpm_stat",
+	.id = -1,
+	.dev = {
+		.platform_data = &msm_rpm_stat_pdata,
+	},
+};
+
+static struct msm_rpm_log_platform_data msm_rpm_log_pdata = {
+	.phys_addr_base = 0x0010AC00,
+	.reg_offsets = {
+		[MSM_RPM_LOG_PAGE_INDICES] = 0x00000080,
+		[MSM_RPM_LOG_PAGE_BUFFER]  = 0x000000A0,
+	},
+	.phys_size = SZ_8K,
+	.log_len = 4096,		  /* log's buffer length in bytes */
+	.log_len_mask = (4096 >> 2) - 1,  /* length mask in units of u32 */
+};
+
+struct platform_device msm9615_rpm_log_device = {
+	.name	= "msm_rpm_log",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &msm_rpm_log_pdata,
+	},
+};
+
 void __init msm9615_device_init(void)
 {
 	msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
-	BUG_ON(msm_rpm_init(&msm_rpm_data));
-	BUG_ON(msm_rpmrs_levels_init(msm_rpmrs_levels,
-			ARRAY_SIZE(msm_rpmrs_levels)));
+	BUG_ON(msm_rpm_init(&msm9615_rpm_data));
+	BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
 }
 
 #define MSM_SHARED_RAM_PHYS 0x40000000
@@ -958,15 +1107,15 @@
 
 void __init msm9615_init_irq(void)
 {
-	msm_mpm_irq_extn_init();
+	struct msm_mpm_device_data *data = NULL;
+
+#ifdef CONFIG_MSM_MPM
+	data = &msm9615_mpm_dev_data;
+#endif
+
+	msm_mpm_irq_extn_init(data);
 	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
 						(void *)MSM_QGIC_CPU_BASE);
-
-	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-	writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
-	writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-	mb();
 }
 
 struct platform_device msm_bus_9615_sys_fabric = {
diff --git a/arch/arm/mach-msm/devices-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 97cb263..31eee43 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -16,12 +16,14 @@
 #include <linux/msm_kgsl.h>
 #include <linux/regulator/machine.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 #include <mach/irqs.h>
 #include <mach/msm_iomap.h>
 #include <mach/board.h>
 #include <mach/dma.h>
 #include <mach/dal_axi.h>
 #include <asm/mach/flash.h>
+#include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/mmc.h>
 #include <mach/rpc_hsusb.h>
@@ -226,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,
 	},
 };
@@ -523,6 +525,73 @@
 	return platform_device_register(pdev);
 }
 
+#ifdef CONFIG_MSM_CAMERA_V4L2
+static struct resource msm_csic0_resources[] = {
+	{
+		.name   = "csic",
+		.start  = 0xA0F00000,
+		.end    = 0xA0F00000 + 0x00100000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "csic",
+		.start  = INT_CSI_IRQ_0,
+		.end    = INT_CSI_IRQ_0,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_csic1_resources[] = {
+	{
+		.name   = "csic",
+		.start  = 0xA1000000,
+		.end    = 0xA1000000 + 0x00100000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "csic",
+		.start  = INT_CSI_IRQ_1,
+		.end    = INT_CSI_IRQ_1,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm7x27a_device_csic0 = {
+	.name           = "msm_csic",
+	.id             = 0,
+	.resource       = msm_csic0_resources,
+	.num_resources  = ARRAY_SIZE(msm_csic0_resources),
+};
+
+struct platform_device msm7x27a_device_csic1 = {
+	.name           = "msm_csic",
+	.id             = 1,
+	.resource       = msm_csic1_resources,
+	.num_resources  = ARRAY_SIZE(msm_csic1_resources),
+};
+
+static struct resource msm_clkctl_resources[] = {
+	{
+		.name   = "clk_ctl",
+		.start  = MSM7XXX_CLK_CTL_PHYS,
+		.end    = MSM7XXX_CLK_CTL_PHYS + MSM7XXX_CLK_CTL_SIZE - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+};
+struct platform_device msm7x27a_device_clkctl = {
+	.name           = "msm_clk_ctl",
+	.id             = 0,
+	.resource       = msm_clkctl_resources,
+	.num_resources  = ARRAY_SIZE(msm_clkctl_resources),
+};
+
+struct platform_device msm7x27a_device_vfe = {
+	.name           = "msm_vfe",
+	.id             = 0,
+};
+
+#endif
+
 #define MDP_BASE		0xAA200000
 #define MIPI_DSI_HW_BASE	0xA1100000
 
@@ -719,15 +788,176 @@
 	.num_resources	= ARRAY_SIZE(gpio_resources),
 };
 
-static int msm7627a_init_gpio(void)
-{
-	platform_device_register(&msm_device_gpio);
-	return 0;
-}
-postcore_initcall(msm7627a_init_gpio);
+struct platform_device *msm_footswitch_devices[] = {
+	FS_PCOM(FS_GFX3D,  "fs_gfx3d"),
+};
+unsigned msm_num_footswitch_devices = ARRAY_SIZE(msm_footswitch_devices);
+
+/* MSM8625 Devices */
+
+static struct resource msm8625_resources_uart1[] = {
+	{
+		.start  = MSM8625_INT_UART1,
+		.end    = MSM8625_INT_UART1,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.start	= MSM7XXX_UART1_PHYS,
+		.end    = MSM7XXX_UART1_PHYS + MSM7XXX_UART1_SIZE - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device msm8625_device_uart1 = {
+	.name		= "msm_serial",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(msm8625_resources_uart1),
+	.resource	= msm8625_resources_uart1,
+};
+
+static struct resource msm8625_dmov_resource[] = {
+	{
+		.start	= MSM8625_INT_ADM_AARM,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= 0xA9700000,
+		.end	= 0xA9700000 + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device msm8625_device_dmov = {
+	.name		= "msm_dmov",
+	.id		= -1,
+	.resource	= msm8625_dmov_resource,
+	.num_resources	= ARRAY_SIZE(msm8625_dmov_resource),
+	.dev		= {
+		.platform_data = &msm_dmov_pdata,
+	},
+};
+
+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 resource msm8625_gpio_resources[] = {
+	{
+		.start	= MSM8625_INT_GPIO_GROUP1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= MSM8625_INT_GPIO_GROUP2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device msm8625_device_gpio = {
+	.name		= "msmgpio",
+	.id		= -1,
+	.resource	= msm8625_gpio_resources,
+	.num_resources	= ARRAY_SIZE(msm8625_gpio_resources),
+};
+
+static struct clk_lookup msm_clock_8625_dummy[] = {
+	CLK_DUMMY("core_clk",		adm_clk.c,	"msm_dmov", 0),
+	CLK_DUMMY("adsp_clk",		adsp_clk.c,	NULL, 0),
+	CLK_DUMMY("ahb_m_clk",		ahb_m_clk.c,	NULL, 0),
+	CLK_DUMMY("ahb_s_clk",		ahb_s_clk.c,	NULL, 0),
+	CLK_DUMMY("cam_m_clk",		cam_m_clk.c,	NULL, 0),
+	CLK_DUMMY("csi_clk",		csi1_clk.c,	NULL, 0),
+	CLK_DUMMY("csi_pclk",		csi1_p_clk.c,	NULL, 0),
+	CLK_DUMMY("csi_vfe_clk",	csi1_vfe_clk.c,	NULL, 0),
+	CLK_DUMMY("dsi_byte_clk",	dsi_byte_clk.c,	NULL, 0),
+	CLK_DUMMY("dsi_clk",		dsi_clk.c,	NULL, 0),
+	CLK_DUMMY("dsi_esc_clk",	dsi_esc_clk.c,	NULL, 0),
+	CLK_DUMMY("dsi_pixel_clk",	dsi_pixel_clk.c, NULL, 0),
+	CLK_DUMMY("dsi_ref_clk",	dsi_ref_clk.c,	NULL, 0),
+	CLK_DUMMY("ebi1_clk",		ebi1_clk.c,	NULL, 0),
+	CLK_DUMMY("ebi2_clk",		ebi2_clk.c,	NULL, 0),
+	CLK_DUMMY("ecodec_clk",		ecodec_clk.c,	NULL, 0),
+	CLK_DUMMY("gp_clk",		gp_clk.c,	NULL, 0),
+	CLK_DUMMY("core_clk",		gsbi1_qup_clk.c, "qup_i2c.0", 0),
+	CLK_DUMMY("core_clk",		gsbi2_qup_clk.c, "qup_i2c.1", 0),
+	CLK_DUMMY("iface_clk",		gsbi1_qup_p_clk.c, "qup_i2c.0", 0),
+	CLK_DUMMY("iface_clk",		gsbi2_qup_p_clk.c, "qup_i2c.1", 0),
+	CLK_DUMMY("icodec_rx_clk",	icodec_rx_clk.c, NULL, 0),
+	CLK_DUMMY("icodec_tx_clk",	icodec_tx_clk.c, NULL, 0),
+	CLK_DUMMY("mem_clk",		imem_clk.c,	NULL, 0),
+	CLK_DUMMY("mddi_clk",		pmdh_clk.c,	NULL, 0),
+	CLK_DUMMY("mdp_clk",		mdp_clk.c,	NULL, 0),
+	CLK_DUMMY("mdp_lcdc_pclk_clk",	mdp_lcdc_pclk_clk.c, NULL, 0),
+	CLK_DUMMY("mdp_lcdc_pad_pclk_clk", mdp_lcdc_pad_pclk_clk.c, NULL, 0),
+	CLK_DUMMY("mdp_vsync_clk",	mdp_vsync_clk.c,	NULL, 0),
+	CLK_DUMMY("mdp_dsi_pclk",	mdp_dsi_p_clk.c,	NULL, 0),
+	CLK_DUMMY("pbus_clk",		pbus_clk.c,	NULL, 0),
+	CLK_DUMMY("pcm_clk",		pcm_clk.c,	NULL, 0),
+	CLK_DUMMY("sdac_clk",		sdac_clk.c,	NULL, 0),
+	CLK_DUMMY("core_clk",		sdc1_clk.c,	"msm_sdcc.1", 0),
+	CLK_DUMMY("iface_clk",		sdc1_p_clk.c,	"msm_sdcc.1", 0),
+	CLK_DUMMY("core_clk",		sdc2_clk.c,	"msm_sdcc.2", 0),
+	CLK_DUMMY("iface_clk",		sdc2_p_clk.c,	"msm_sdcc.2", 0),
+	CLK_DUMMY("core_clk",		sdc3_clk.c,	"msm_sdcc.3", 0),
+	CLK_DUMMY("iface_clk",		sdc3_p_clk.c,	"msm_sdcc.3", 0),
+	CLK_DUMMY("core_clk",		sdc4_clk.c,	"msm_sdcc.4", 0),
+	CLK_DUMMY("iface_clk",		sdc4_p_clk.c,	"msm_sdcc.4", 0),
+	CLK_DUMMY("ref_clk",		tsif_ref_clk.c,	"msm_tsif.0", 0),
+	CLK_DUMMY("iface_clk",		tsif_p_clk.c,	"msm_tsif.0", 0),
+	CLK_DUMMY("core_clk",		uart1_clk.c,	"msm_serial.0", 0),
+	CLK_DUMMY("core_clk",		uart2_clk.c,	"msm_serial.1", 0),
+	CLK_DUMMY("core_clk",		uart1dm_clk.c,	"msm_serial_hs.0", 0),
+	CLK_DUMMY("core_clk",		uart2dm_clk.c,	"msm_serial_hsl.0", 0),
+	CLK_DUMMY("usb_hs_core_clk",	usb_hs_core_clk.c, NULL, 0),
+	CLK_DUMMY("usb_hs2_clk",	usb_hs2_clk.c,	NULL, 0),
+	CLK_DUMMY("usb_hs_clk",		usb_hs_clk.c,	NULL, 0),
+	CLK_DUMMY("usb_hs_pclk",	usb_hs_p_clk.c,	NULL, 0),
+	CLK_DUMMY("usb_phy_clk",	usb_phy_clk.c,	NULL, 0),
+	CLK_DUMMY("vdc_clk",		vdc_clk.c,	NULL, 0),
+	CLK_DUMMY("ebi1_acpu_clk",	ebi_acpu_clk.c,	NULL, 0),
+	CLK_DUMMY("ebi1_lcdc_clk",	ebi_lcdc_clk.c,	NULL, 0),
+	CLK_DUMMY("ebi1_mddi_clk",	ebi_mddi_clk.c,	NULL, 0),
+	CLK_DUMMY("ebi1_usb_clk",	ebi_usb_clk.c,	NULL, 0),
+	CLK_DUMMY("ebi1_vfe_clk",	ebi_vfe_clk.c,	NULL, 0),
+	CLK_DUMMY("mem_clk",		ebi_adm_clk.c,	"msm_dmov", 0),
+};
+
+struct clock_init_data msm8625_dummy_clock_init_data __initdata = {
+	.table = msm_clock_8625_dummy,
+	.size = ARRAY_SIZE(msm_clock_8625_dummy),
+};
 
 int __init msm7x2x_misc_init(void)
 {
+	if (machine_is_msm8625_rumi3()) {
+		msm_clock_init(&msm8625_dummy_clock_init_data);
+		return 0;
+	}
+
 	msm_clock_init(&msm7x27a_clock_init_data);
 	if (cpu_is_msm7x27aa())
 		acpuclk_init(&acpuclk_7x27aa_soc_data);
@@ -748,6 +978,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;
@@ -759,13 +996,33 @@
 void __init msm_common_io_init(void)
 {
 	msm_map_common_io();
-	msm7x27x_cache_init();
 	if (socinfo_init() < 0)
 		pr_err("%s: socinfo_init() failed!\n", __func__);
-
+	msm7x27x_cache_init();
 }
 
-struct platform_device *msm_footswitch_devices[] = {
-	FS_PCOM(FS_GFX3D,  "fs_gfx3d"),
-};
-unsigned msm_num_footswitch_devices = ARRAY_SIZE(msm_footswitch_devices);
+void __init msm8625_init_irq(void)
+{
+	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
+			(void *)MSM_QGIC_CPU_BASE);
+}
+
+void __init msm8625_map_io(void)
+{
+	msm_map_msm8625_io();
+
+	if (socinfo_init() < 0)
+		pr_err("%s: socinfo_init() failed!\n", __func__);
+	msm7x27x_cache_init();
+}
+
+static int msm7627a_init_gpio(void)
+{
+	if (cpu_is_msm8625())
+		platform_device_register(&msm8625_device_gpio);
+	else
+		platform_device_register(&msm_device_gpio);
+	return 0;
+}
+postcore_initcall(msm7627a_init_gpio);
+
diff --git a/arch/arm/mach-msm/devices-msm7x2xa.h b/arch/arm/mach-msm/devices-msm7x2xa.h
index d04dfe0..be6a645 100644
--- a/arch/arm/mach-msm/devices-msm7x2xa.h
+++ b/arch/arm/mach-msm/devices-msm7x2xa.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
@@ -19,4 +19,11 @@
 void __init msm_init_pmic_vibrator(void);
 void __init msm7x25a_kgsl_3d0_init(void);
 int __init msm7x2x_misc_init(void);
+extern struct platform_device msm7x27a_device_vfe;
+extern struct platform_device msm7x27a_device_csic0;
+extern struct platform_device msm7x27a_device_csic1;
+extern struct platform_device msm7x27a_device_clkctl;
+void __init msm8625_init_irq(void);
+void __init msm8625_map_io(void);
+int  ar600x_wlan_power(bool on);
 #endif
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index db656f3..fc732da 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -581,9 +581,67 @@
 	},
 };
 
+static struct resource smd_resource[] = {
+	{
+		.name   = "a9_m2a_0",
+		.start  = INT_A9_M2A_0,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "a9_m2a_5",
+		.start  = INT_A9_M2A_5,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "adsp_a11_smsm",
+		.start  = INT_ADSP_A11,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct smd_subsystem_config smd_config_list[] = {
+	{
+		.irq_config_id = SMD_MODEM,
+		.subsys_name = "modem",
+		.edge = SMD_APPS_MODEM,
+
+		.smd_int.irq_name = "a9_m2a_0",
+		.smd_int.flags = IRQF_TRIGGER_RISING,
+		.smd_int.irq_id = -1,
+		.smd_int.device_name = "smd_dev",
+		.smd_int.dev_id = 0,
+
+		.smd_int.out_bit_pos =  1 << 0,
+		.smd_int.out_base = (void __iomem *)MSM_GCC_BASE,
+		.smd_int.out_offset = 0x8,
+
+		.smsm_int.irq_name = "a9_m2a_5",
+		.smsm_int.flags = IRQF_TRIGGER_RISING,
+		.smsm_int.irq_id = -1,
+		.smsm_int.device_name = "smd_dev",
+		.smsm_int.dev_id = 0,
+
+		.smsm_int.out_bit_pos =  1 << 5,
+		.smsm_int.out_base = (void __iomem *)MSM_GCC_BASE,
+		.smsm_int.out_offset = 0x8,
+
+	}
+};
+
+static struct smd_platform smd_platform_data = {
+	.num_ss_configs = ARRAY_SIZE(smd_config_list),
+	.smd_ss_configs = smd_config_list,
+};
+
 struct platform_device msm_device_smd = {
 	.name	= "msm_smd",
 	.id	= -1,
+	.resource = smd_resource,
+	.num_resources = ARRAY_SIZE(smd_resource),
+	.dev = {
+		.platform_data = &smd_platform_data,
+	}
+
 };
 
 static struct resource msm_dmov_resource[] = {
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 4196462..4670ce8 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -52,6 +52,7 @@
 #include <mach/rpm.h>
 #include <mach/board.h>
 #include <sound/apr_audio.h>
+#include "rpm_log.h"
 #include "rpm_stats.h"
 #include "mpm.h"
 #include "msm_watchdog.h"
@@ -170,11 +171,14 @@
 
 void __init msm8x60_init_irq(void)
 {
-	msm_mpm_irq_extn_init();
-	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE, (void *)MSM_QGIC_CPU_BASE);
+	struct msm_mpm_device_data *data = NULL;
 
-	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-	writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
+#ifdef CONFIG_MSM_MPM
+	data = &msm8660_mpm_dev_data;
+#endif
+
+	msm_mpm_irq_extn_init(data);
+	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE, (void *)MSM_QGIC_CPU_BASE);
 }
 
 #define MSM_LPASS_QDSP6SS_PHYS 0x28800000
@@ -2175,13 +2179,34 @@
 	},
 };
 
+#if defined(CONFIG_MSM_RPM_LOG) || defined(CONFIG_MSM_RPM_LOG_MODULE)
+static struct msm_rpm_log_platform_data msm_rpm_log_pdata = {
+	.phys_addr_base = 0x00106000,
+	.reg_offsets = {
+		[MSM_RPM_LOG_PAGE_INDICES] = 0x00000C80,
+		[MSM_RPM_LOG_PAGE_BUFFER]  = 0x00000CA0,
+	},
+	.phys_size = SZ_8K,
+	.log_len = 4096,		  /* log's buffer length in bytes */
+	.log_len_mask = (4096 >> 2) - 1,  /* length mask in units of u32 */
+};
+
+struct platform_device msm8660_rpm_log_device = {
+	.name	= "msm_rpm_log",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &msm_rpm_log_pdata,
+	},
+};
+#endif
+
 #if defined(CONFIG_MSM_RPM_STATS_LOG)
 static struct msm_rpmstats_platform_data msm_rpm_stat_pdata = {
 	.phys_addr_base = 0x00107E04,
 	.phys_size = SZ_8K,
 };
 
-struct platform_device msm_rpm_stat_device = {
+struct platform_device msm8660_rpm_stat_device = {
 	.name = "msm_rpm_stat",
 	.id = -1,
 	.dev = {
@@ -2191,7 +2216,7 @@
 #endif
 
 #ifdef CONFIG_MSM_MPM
-static uint16_t msm_mpm_irqs_m2a[MSM_MPM_NR_MPM_IRQS] = {
+static uint16_t msm_mpm_irqs_m2a[MSM_MPM_NR_MPM_IRQS]  __initdata = {
 	[1] = MSM_GPIO_TO_INT(61),
 	[4] = MSM_GPIO_TO_INT(87),
 	[5] = MSM_GPIO_TO_INT(88),
@@ -2246,7 +2271,7 @@
 	[59] = MSM_GPIO_TO_INT(129),
 };
 
-static uint16_t msm_mpm_bypassed_apps_irqs[] = {
+static uint16_t msm_mpm_bypassed_apps_irqs[] __initdata = {
 	TLMM_MSM_SUMMARY_IRQ,
 	RPM_SCSS_CPU0_GP_HIGH_IRQ,
 	RPM_SCSS_CPU0_GP_MEDIUM_IRQ,
@@ -2273,7 +2298,7 @@
 	SPS_MTI_31,
 };
 
-struct msm_mpm_device_data msm_mpm_dev_data = {
+struct msm_mpm_device_data msm8660_mpm_dev_data __initdata = {
 	.irqs_m2a = msm_mpm_irqs_m2a,
 	.irqs_m2a_size = ARRAY_SIZE(msm_mpm_irqs_m2a),
 	.bypassed_apps_irqs = msm_mpm_bypassed_apps_irqs,
@@ -2433,104 +2458,265 @@
 };
 unsigned msm_num_footswitch_devices = ARRAY_SIZE(msm_footswitch_devices);
 
-#ifdef CONFIG_MSM_RPM
-struct msm_rpm_map_data rpm_map_data[] __initdata = {
-	MSM_RPM_MAP(TRIGGER_TIMED_TO, TRIGGER_TIMED, 1),
-	MSM_RPM_MAP(TRIGGER_TIMED_SCLK_COUNT, TRIGGER_TIMED, 1),
-	MSM_RPM_MAP(TRIGGER_SET_FROM, TRIGGER_SET, 1),
-	MSM_RPM_MAP(TRIGGER_SET_TO, TRIGGER_SET, 1),
-	MSM_RPM_MAP(TRIGGER_SET_TRIGGER, TRIGGER_SET, 1),
-	MSM_RPM_MAP(TRIGGER_CLEAR_FROM, TRIGGER_CLEAR, 1),
-	MSM_RPM_MAP(TRIGGER_CLEAR_TO, TRIGGER_CLEAR, 1),
-	MSM_RPM_MAP(TRIGGER_CLEAR_TRIGGER, TRIGGER_CLEAR, 1),
+struct msm_rpm_platform_data msm8660_rpm_data __initdata = {
+	.reg_base_addrs = {
+		[MSM_RPM_PAGE_STATUS] = MSM_RPM_BASE,
+		[MSM_RPM_PAGE_CTRL] = MSM_RPM_BASE + 0x400,
+		[MSM_RPM_PAGE_REQ] = MSM_RPM_BASE + 0x600,
+		[MSM_RPM_PAGE_ACK] = MSM_RPM_BASE + 0xa00,
+	},
+	.irq_ack = RPM_SCSS_CPU0_GP_HIGH_IRQ,
+	.ipc_rpm_reg = MSM_GCC_BASE + 0x008,
+	.ipc_rpm_val = 4,
+	.target_id = {
+		MSM_RPM_MAP(8660, NOTIFICATION_CONFIGURED_0, NOTIFICATION, 8),
+		MSM_RPM_MAP(8660, NOTIFICATION_REGISTERED_0, NOTIFICATION, 8),
+		MSM_RPM_MAP(8660, INVALIDATE_0, INVALIDATE, 8),
+		MSM_RPM_MAP(8660, TRIGGER_TIMED_TO, TRIGGER_TIMED, 1),
+		MSM_RPM_MAP(8660, TRIGGER_TIMED_SCLK_COUNT, TRIGGER_TIMED, 1),
+		MSM_RPM_MAP(8660, TRIGGER_SET_FROM, TRIGGER_SET, 1),
+		MSM_RPM_MAP(8660, TRIGGER_SET_TO, TRIGGER_SET, 1),
+		MSM_RPM_MAP(8660, TRIGGER_SET_TRIGGER, TRIGGER_SET, 1),
+		MSM_RPM_MAP(8660, TRIGGER_CLEAR_FROM, TRIGGER_CLEAR, 1),
+		MSM_RPM_MAP(8660, TRIGGER_CLEAR_TO, TRIGGER_CLEAR, 1),
+		MSM_RPM_MAP(8660, TRIGGER_CLEAR_TRIGGER, TRIGGER_CLEAR, 1),
 
-	MSM_RPM_MAP(CXO_CLK, CXO_CLK, 1),
-	MSM_RPM_MAP(PXO_CLK, PXO_CLK, 1),
-	MSM_RPM_MAP(PLL_4, PLL_4, 1),
-	MSM_RPM_MAP(APPS_FABRIC_CLK, APPS_FABRIC_CLK, 1),
-	MSM_RPM_MAP(SYSTEM_FABRIC_CLK, SYSTEM_FABRIC_CLK, 1),
-	MSM_RPM_MAP(MM_FABRIC_CLK, MM_FABRIC_CLK, 1),
-	MSM_RPM_MAP(DAYTONA_FABRIC_CLK, DAYTONA_FABRIC_CLK, 1),
-	MSM_RPM_MAP(SFPB_CLK, SFPB_CLK, 1),
-	MSM_RPM_MAP(CFPB_CLK, CFPB_CLK, 1),
-	MSM_RPM_MAP(MMFPB_CLK, MMFPB_CLK, 1),
-	MSM_RPM_MAP(SMI_CLK, SMI_CLK, 1),
-	MSM_RPM_MAP(EBI1_CLK, EBI1_CLK, 1),
+		MSM_RPM_MAP(8660, CXO_CLK, CXO_CLK, 1),
+		MSM_RPM_MAP(8660, PXO_CLK, PXO_CLK, 1),
+		MSM_RPM_MAP(8660, PLL_4, PLL_4, 1),
+		MSM_RPM_MAP(8660, APPS_FABRIC_CLK, APPS_FABRIC_CLK, 1),
+		MSM_RPM_MAP(8660, SYSTEM_FABRIC_CLK, SYSTEM_FABRIC_CLK, 1),
+		MSM_RPM_MAP(8660, MM_FABRIC_CLK, MM_FABRIC_CLK, 1),
+		MSM_RPM_MAP(8660, DAYTONA_FABRIC_CLK, DAYTONA_FABRIC_CLK, 1),
+		MSM_RPM_MAP(8660, SFPB_CLK, SFPB_CLK, 1),
+		MSM_RPM_MAP(8660, CFPB_CLK, CFPB_CLK, 1),
+		MSM_RPM_MAP(8660, MMFPB_CLK, MMFPB_CLK, 1),
+		MSM_RPM_MAP(8660, SMI_CLK, SMI_CLK, 1),
+		MSM_RPM_MAP(8660, EBI1_CLK, EBI1_CLK, 1),
 
-	MSM_RPM_MAP(APPS_L2_CACHE_CTL, APPS_L2_CACHE_CTL, 1),
+		MSM_RPM_MAP(8660, APPS_L2_CACHE_CTL, APPS_L2_CACHE_CTL, 1),
 
-	MSM_RPM_MAP(APPS_FABRIC_HALT_0, APPS_FABRIC_HALT, 2),
-	MSM_RPM_MAP(APPS_FABRIC_CLOCK_MODE_0, APPS_FABRIC_CLOCK_MODE, 3),
-	MSM_RPM_MAP(APPS_FABRIC_ARB_0, APPS_FABRIC_ARB, 6),
+		MSM_RPM_MAP(8660, APPS_FABRIC_HALT_0, APPS_FABRIC_HALT, 2),
+		MSM_RPM_MAP(8660, APPS_FABRIC_CLOCK_MODE_0,
+				APPS_FABRIC_CLOCK_MODE, 3),
+		MSM_RPM_MAP(8660, APPS_FABRIC_ARB_0, APPS_FABRIC_ARB, 6),
 
-	MSM_RPM_MAP(SYSTEM_FABRIC_HALT_0, SYSTEM_FABRIC_HALT, 2),
-	MSM_RPM_MAP(SYSTEM_FABRIC_CLOCK_MODE_0, SYSTEM_FABRIC_CLOCK_MODE, 3),
-	MSM_RPM_MAP(SYSTEM_FABRIC_ARB_0, SYSTEM_FABRIC_ARB, 22),
+		MSM_RPM_MAP(8660, SYSTEM_FABRIC_HALT_0, SYSTEM_FABRIC_HALT, 2),
+		MSM_RPM_MAP(8660, SYSTEM_FABRIC_CLOCK_MODE_0,
+				SYSTEM_FABRIC_CLOCK_MODE, 3),
+		MSM_RPM_MAP(8660, SYSTEM_FABRIC_ARB_0, SYSTEM_FABRIC_ARB, 22),
 
-	MSM_RPM_MAP(MM_FABRIC_HALT_0, MM_FABRIC_HALT, 2),
-	MSM_RPM_MAP(MM_FABRIC_CLOCK_MODE_0, MM_FABRIC_CLOCK_MODE, 3),
-	MSM_RPM_MAP(MM_FABRIC_ARB_0, MM_FABRIC_ARB, 23),
+		MSM_RPM_MAP(8660, MM_FABRIC_HALT_0, MM_FABRIC_HALT, 2),
+		MSM_RPM_MAP(8660, MM_FABRIC_CLOCK_MODE_0,
+				MM_FABRIC_CLOCK_MODE, 3),
+		MSM_RPM_MAP(8660, MM_FABRIC_ARB_0, MM_FABRIC_ARB, 23),
 
-	MSM_RPM_MAP(SMPS0B_0, SMPS0B, 2),
-	MSM_RPM_MAP(SMPS1B_0, SMPS1B, 2),
-	MSM_RPM_MAP(SMPS2B_0, SMPS2B, 2),
-	MSM_RPM_MAP(SMPS3B_0, SMPS3B, 2),
-	MSM_RPM_MAP(SMPS4B_0, SMPS4B, 2),
-	MSM_RPM_MAP(LDO0B_0, LDO0B, 2),
-	MSM_RPM_MAP(LDO1B_0, LDO1B, 2),
-	MSM_RPM_MAP(LDO2B_0, LDO2B, 2),
-	MSM_RPM_MAP(LDO3B_0, LDO3B, 2),
-	MSM_RPM_MAP(LDO4B_0, LDO4B, 2),
-	MSM_RPM_MAP(LDO5B_0, LDO5B, 2),
-	MSM_RPM_MAP(LDO6B_0, LDO6B, 2),
-	MSM_RPM_MAP(LVS0B, LVS0B, 1),
-	MSM_RPM_MAP(LVS1B, LVS1B, 1),
-	MSM_RPM_MAP(LVS2B, LVS2B, 1),
-	MSM_RPM_MAP(LVS3B, LVS3B, 1),
-	MSM_RPM_MAP(MVS, MVS, 1),
+		MSM_RPM_MAP(8660, SMPS0B_0, SMPS0B, 2),
+		MSM_RPM_MAP(8660, SMPS1B_0, SMPS1B, 2),
+		MSM_RPM_MAP(8660, SMPS2B_0, SMPS2B, 2),
+		MSM_RPM_MAP(8660, SMPS3B_0, SMPS3B, 2),
+		MSM_RPM_MAP(8660, SMPS4B_0, SMPS4B, 2),
+		MSM_RPM_MAP(8660, LDO0B_0, LDO0B, 2),
+		MSM_RPM_MAP(8660, LDO1B_0, LDO1B, 2),
+		MSM_RPM_MAP(8660, LDO2B_0, LDO2B, 2),
+		MSM_RPM_MAP(8660, LDO3B_0, LDO3B, 2),
+		MSM_RPM_MAP(8660, LDO4B_0, LDO4B, 2),
+		MSM_RPM_MAP(8660, LDO5B_0, LDO5B, 2),
+		MSM_RPM_MAP(8660, LDO6B_0, LDO6B, 2),
+		MSM_RPM_MAP(8660, LVS0B, LVS0B, 1),
+		MSM_RPM_MAP(8660, LVS1B, LVS1B, 1),
+		MSM_RPM_MAP(8660, LVS2B, LVS2B, 1),
+		MSM_RPM_MAP(8660, LVS3B, LVS3B, 1),
+		MSM_RPM_MAP(8660, MVS, MVS, 1),
 
-	MSM_RPM_MAP(SMPS0_0, SMPS0, 2),
-	MSM_RPM_MAP(SMPS1_0, SMPS1, 2),
-	MSM_RPM_MAP(SMPS2_0, SMPS2, 2),
-	MSM_RPM_MAP(SMPS3_0, SMPS3, 2),
-	MSM_RPM_MAP(SMPS4_0, SMPS4, 2),
-	MSM_RPM_MAP(LDO0_0, LDO0, 2),
-	MSM_RPM_MAP(LDO1_0, LDO1, 2),
-	MSM_RPM_MAP(LDO2_0, LDO2, 2),
-	MSM_RPM_MAP(LDO3_0, LDO3, 2),
-	MSM_RPM_MAP(LDO4_0, LDO4, 2),
-	MSM_RPM_MAP(LDO5_0, LDO5, 2),
-	MSM_RPM_MAP(LDO6_0, LDO6, 2),
-	MSM_RPM_MAP(LDO7_0, LDO7, 2),
-	MSM_RPM_MAP(LDO8_0, LDO8, 2),
-	MSM_RPM_MAP(LDO9_0, LDO9, 2),
-	MSM_RPM_MAP(LDO10_0, LDO10, 2),
-	MSM_RPM_MAP(LDO11_0, LDO11, 2),
-	MSM_RPM_MAP(LDO12_0, LDO12, 2),
-	MSM_RPM_MAP(LDO13_0, LDO13, 2),
-	MSM_RPM_MAP(LDO14_0, LDO14, 2),
-	MSM_RPM_MAP(LDO15_0, LDO15, 2),
-	MSM_RPM_MAP(LDO16_0, LDO16, 2),
-	MSM_RPM_MAP(LDO17_0, LDO17, 2),
-	MSM_RPM_MAP(LDO18_0, LDO18, 2),
-	MSM_RPM_MAP(LDO19_0, LDO19, 2),
-	MSM_RPM_MAP(LDO20_0, LDO20, 2),
-	MSM_RPM_MAP(LDO21_0, LDO21, 2),
-	MSM_RPM_MAP(LDO22_0, LDO22, 2),
-	MSM_RPM_MAP(LDO23_0, LDO23, 2),
-	MSM_RPM_MAP(LDO24_0, LDO24, 2),
-	MSM_RPM_MAP(LDO25_0, LDO25, 2),
-	MSM_RPM_MAP(LVS0, LVS0, 1),
-	MSM_RPM_MAP(LVS1, LVS1, 1),
-	MSM_RPM_MAP(NCP_0, NCP, 2),
+		MSM_RPM_MAP(8660, SMPS0_0, SMPS0, 2),
+		MSM_RPM_MAP(8660, SMPS1_0, SMPS1, 2),
+		MSM_RPM_MAP(8660, SMPS2_0, SMPS2, 2),
+		MSM_RPM_MAP(8660, SMPS3_0, SMPS3, 2),
+		MSM_RPM_MAP(8660, SMPS4_0, SMPS4, 2),
+		MSM_RPM_MAP(8660, LDO0_0, LDO0, 2),
+		MSM_RPM_MAP(8660, LDO1_0, LDO1, 2),
+		MSM_RPM_MAP(8660, LDO2_0, LDO2, 2),
+		MSM_RPM_MAP(8660, LDO3_0, LDO3, 2),
+		MSM_RPM_MAP(8660, LDO4_0, LDO4, 2),
+		MSM_RPM_MAP(8660, LDO5_0, LDO5, 2),
+		MSM_RPM_MAP(8660, LDO6_0, LDO6, 2),
+		MSM_RPM_MAP(8660, LDO7_0, LDO7, 2),
+		MSM_RPM_MAP(8660, LDO8_0, LDO8, 2),
+		MSM_RPM_MAP(8660, LDO9_0, LDO9, 2),
+		MSM_RPM_MAP(8660, LDO10_0, LDO10, 2),
+		MSM_RPM_MAP(8660, LDO11_0, LDO11, 2),
+		MSM_RPM_MAP(8660, LDO12_0, LDO12, 2),
+		MSM_RPM_MAP(8660, LDO13_0, LDO13, 2),
+		MSM_RPM_MAP(8660, LDO14_0, LDO14, 2),
+		MSM_RPM_MAP(8660, LDO15_0, LDO15, 2),
+		MSM_RPM_MAP(8660, LDO16_0, LDO16, 2),
+		MSM_RPM_MAP(8660, LDO17_0, LDO17, 2),
+		MSM_RPM_MAP(8660, LDO18_0, LDO18, 2),
+		MSM_RPM_MAP(8660, LDO19_0, LDO19, 2),
+		MSM_RPM_MAP(8660, LDO20_0, LDO20, 2),
+		MSM_RPM_MAP(8660, LDO21_0, LDO21, 2),
+		MSM_RPM_MAP(8660, LDO22_0, LDO22, 2),
+		MSM_RPM_MAP(8660, LDO23_0, LDO23, 2),
+		MSM_RPM_MAP(8660, LDO24_0, LDO24, 2),
+		MSM_RPM_MAP(8660, LDO25_0, LDO25, 2),
+		MSM_RPM_MAP(8660, LVS0, LVS0, 1),
+		MSM_RPM_MAP(8660, LVS1, LVS1, 1),
+		MSM_RPM_MAP(8660, NCP_0, NCP, 2),
+		MSM_RPM_MAP(8660, CXO_BUFFERS, CXO_BUFFERS, 1),
+	},
+	.target_status = {
+		MSM_RPM_STATUS_ID_MAP(8660, VERSION_MAJOR),
+		MSM_RPM_STATUS_ID_MAP(8660, VERSION_MINOR),
+		MSM_RPM_STATUS_ID_MAP(8660, VERSION_BUILD),
+		MSM_RPM_STATUS_ID_MAP(8660, SUPPORTED_RESOURCES_0),
+		MSM_RPM_STATUS_ID_MAP(8660, SUPPORTED_RESOURCES_1),
+		MSM_RPM_STATUS_ID_MAP(8660, SUPPORTED_RESOURCES_2),
+		MSM_RPM_STATUS_ID_MAP(8660, SEQUENCE),
 
-	MSM_RPM_MAP(CXO_BUFFERS, CXO_BUFFERS, 1),
+		MSM_RPM_STATUS_ID_MAP(8660, CXO_CLK),
+		MSM_RPM_STATUS_ID_MAP(8660, PXO_CLK),
+		MSM_RPM_STATUS_ID_MAP(8660, PLL_4),
+		MSM_RPM_STATUS_ID_MAP(8660, APPS_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(8660, SYSTEM_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(8660, MM_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(8660, DAYTONA_FABRIC_CLK),
+		MSM_RPM_STATUS_ID_MAP(8660, SFPB_CLK),
+		MSM_RPM_STATUS_ID_MAP(8660, CFPB_CLK),
+		MSM_RPM_STATUS_ID_MAP(8660, MMFPB_CLK),
+		MSM_RPM_STATUS_ID_MAP(8660, SMI_CLK),
+		MSM_RPM_STATUS_ID_MAP(8660, EBI1_CLK),
+
+		MSM_RPM_STATUS_ID_MAP(8660, APPS_L2_CACHE_CTL),
+
+		MSM_RPM_STATUS_ID_MAP(8660, APPS_FABRIC_HALT),
+		MSM_RPM_STATUS_ID_MAP(8660, APPS_FABRIC_CLOCK_MODE),
+		MSM_RPM_STATUS_ID_MAP(8660, APPS_FABRIC_ARB),
+
+		MSM_RPM_STATUS_ID_MAP(8660, SYSTEM_FABRIC_HALT),
+		MSM_RPM_STATUS_ID_MAP(8660, SYSTEM_FABRIC_CLOCK_MODE),
+		MSM_RPM_STATUS_ID_MAP(8660, SYSTEM_FABRIC_ARB),
+
+		MSM_RPM_STATUS_ID_MAP(8660, MM_FABRIC_HALT),
+		MSM_RPM_STATUS_ID_MAP(8660, MM_FABRIC_CLOCK_MODE),
+		MSM_RPM_STATUS_ID_MAP(8660, MM_FABRIC_ARB),
+
+
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS0B_0),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS0B_1),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS1B_0),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS1B_1),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS2B_0),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS2B_1),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS3B_0),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS3B_1),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS4B_0),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS4B_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO0B_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO0B_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO1B_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO1B_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO2B_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO2B_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO3B_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO3B_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO4B_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO4B_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO5B_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO5B_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO6B_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO6B_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LVS0B),
+		MSM_RPM_STATUS_ID_MAP(8660, LVS1B),
+		MSM_RPM_STATUS_ID_MAP(8660, LVS2B),
+		MSM_RPM_STATUS_ID_MAP(8660, LVS3B),
+		MSM_RPM_STATUS_ID_MAP(8660, MVS),
+
+
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS0_0),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS0_1),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS1_0),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS1_1),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS2_0),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS2_1),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS3_0),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS3_1),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS4_0),
+		MSM_RPM_STATUS_ID_MAP(8660, SMPS4_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO0_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO0_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO1_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO1_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO2_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO2_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO3_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO3_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO4_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO4_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO5_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO5_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO6_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO6_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO7_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO7_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO8_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO8_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO9_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO9_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO10_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO10_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO11_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO11_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO12_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO12_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO13_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO13_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO14_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO14_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO15_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO15_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO16_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO16_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO17_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO17_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO18_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO18_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO19_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO19_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO20_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO20_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO21_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO21_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO22_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO22_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO23_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO23_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO24_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO24_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO25_0),
+		MSM_RPM_STATUS_ID_MAP(8660, LDO25_1),
+		MSM_RPM_STATUS_ID_MAP(8660, LVS0),
+		MSM_RPM_STATUS_ID_MAP(8660, LVS1),
+		MSM_RPM_STATUS_ID_MAP(8660, NCP_0),
+		MSM_RPM_STATUS_ID_MAP(8660, NCP_1),
+		MSM_RPM_STATUS_ID_MAP(8660, CXO_BUFFERS),
+	},
+	.target_ctrl_id = {
+		MSM_RPM_CTRL_MAP(8660, VERSION_MAJOR),
+		MSM_RPM_CTRL_MAP(8660, VERSION_MINOR),
+		MSM_RPM_CTRL_MAP(8660, VERSION_BUILD),
+		MSM_RPM_CTRL_MAP(8660, REQ_CTX_0),
+		MSM_RPM_CTRL_MAP(8660, REQ_SEL_0),
+		MSM_RPM_CTRL_MAP(8660, ACK_CTX_0),
+		MSM_RPM_CTRL_MAP(8660, ACK_SEL_0),
+	},
+	.sel_invalidate = MSM_RPM_8660_SEL_INVALIDATE,
+	.sel_notification = MSM_RPM_8660_SEL_NOTIFICATION,
+	.sel_last = MSM_RPM_8660_SEL_LAST,
+	.ver = {2, 0, 0},
 };
-unsigned int rpm_map_data_size = ARRAY_SIZE(rpm_map_data);
 
-struct platform_device msm_rpm_device = {
+struct platform_device msm8660_rpm_device = {
 	.name = "msm_rpm",
 	.id = -1,
 };
-
-#endif
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 5d28fa9..e3c875b 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -41,6 +41,7 @@
 extern struct platform_device msm_device_uart1;
 extern struct platform_device msm_device_uart2;
 extern struct platform_device msm_device_uart3;
+extern struct platform_device msm8625_device_uart1;
 
 extern struct platform_device msm_device_uart_dm1;
 extern struct platform_device msm_device_uart_dm2;
@@ -68,6 +69,7 @@
 
 extern struct platform_device apq8064_device_uart_gsbi1;
 extern struct platform_device apq8064_device_uart_gsbi3;
+extern struct platform_device apq8064_device_uart_gsbi7;
 extern struct platform_device apq8064_device_qup_i2c_gsbi4;
 extern struct platform_device apq8064_device_qup_spi_gsbi5;
 extern struct platform_device apq8064_slim_ctrl;
@@ -101,6 +103,8 @@
 extern struct platform_device apq8064_device_otg;
 extern struct platform_device apq8064_usb_diag_device;
 extern struct platform_device apq8064_device_gadget_peripheral;
+extern struct platform_device apq8064_device_hsusb_host;
+extern struct platform_device apq8064_device_hsic_host;
 
 extern struct platform_device msm_device_i2c;
 
@@ -117,6 +121,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;
@@ -128,6 +134,7 @@
 extern struct platform_device msm8960_device_dmov;
 extern struct platform_device apq8064_device_dmov;
 extern struct platform_device msm9615_device_dmov;
+extern struct platform_device msm8625_device_dmov;
 extern struct platform_device msm_device_dmov_adm0;
 extern struct platform_device msm_device_dmov_adm1;
 
@@ -189,6 +196,7 @@
 extern struct platform_device msm_8960_q6_mss_fw;
 extern struct platform_device msm_8960_q6_mss_sw;
 extern struct platform_device msm_8960_riva;
+extern struct platform_device msm_gss;
 
 extern struct platform_device apq_pcm;
 extern struct platform_device apq_pcm_routing;
@@ -240,8 +248,26 @@
 
 extern struct platform_device led_pdev;
 
-extern struct platform_device msm_rpm_device;
-extern struct platform_device msm_rpm_stat_device;
+extern struct platform_device msm8960_rpm_device;
+extern struct platform_device msm8960_rpm_stat_device;
+extern struct platform_device msm8960_rpm_log_device;
+
+extern struct platform_device msm8930_rpm_device;
+extern struct platform_device msm8930_rpm_stat_device;
+extern struct platform_device msm8930_rpm_log_device;
+
+extern struct platform_device msm8660_rpm_device;
+extern struct platform_device msm8660_rpm_stat_device;
+extern struct platform_device msm8660_rpm_log_device;
+
+extern struct platform_device msm9615_rpm_device;
+extern struct platform_device msm9615_rpm_stat_device;
+extern struct platform_device msm9615_rpm_log_device;
+
+extern struct platform_device apq8064_rpm_device;
+extern struct platform_device apq8064_rpm_stat_device;
+extern struct platform_device apq8064_rpm_log_device;
+
 extern struct platform_device msm_device_rng;
 extern struct platform_device apq8064_device_rng;
 
@@ -270,3 +296,5 @@
 extern struct platform_device msm_bus_8064_mm_fabric;
 extern struct platform_device msm_bus_8064_sys_fpb;
 extern struct platform_device msm_bus_8064_cpss_fpb;
+
+extern struct platform_device mdm_8064_device;
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index 7f63dc8..296c111 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.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
@@ -103,7 +103,8 @@
 					clock->name, clock->rate);
 				for (clock--; clock >= fs->clk_data; clock--) {
 					if (clock->enabled)
-						clk_disable(clock->clk);
+						clk_disable_unprepare(
+								clock->clk);
 					clk_set_rate(clock->clk, clock->rate);
 				}
 				return rc;
@@ -115,7 +116,7 @@
 		 * we don't try to disable them later and crash due to
 		 * unbalanced calls.
 		 */
-		clock->enabled = !clk_enable(clock->clk);
+		clock->enabled = !clk_prepare_enable(clock->clk);
 	}
 
 	return 0;
@@ -128,7 +129,7 @@
 	/* Restore clocks to their orignal states before setup_clocks(). */
 	for (clock = fs->clk_data; clock->clk; clock++) {
 		if (clock->enabled)
-			clk_disable(clock->clk);
+			clk_disable_unprepare(clock->clk);
 		if (clock->rate && clk_set_rate(clock->clk, clock->rate))
 			pr_err("Failed to restore %s rate to %lu Hz.\n",
 				clock->name, clock->rate);
@@ -212,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);
 
@@ -241,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);
@@ -293,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;
 }
@@ -327,7 +335,7 @@
 	}
 
 	/* Disable core clock. */
-	clk_disable(fs->core_clk);
+	clk_disable_unprepare(fs->core_clk);
 
 	/*
 	 * (Re-)Assert resets for all clocks in the clock domain, since
@@ -357,7 +365,10 @@
 	udelay(RESET_DELAY_US);
 
 	/* Re-enable core clock. */
-	clk_enable(fs->core_clk);
+	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);
@@ -386,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);
@@ -396,7 +410,7 @@
 	}
 
 	/* Disable core clock. */
-	clk_disable(fs->core_clk);
+	clk_disable_unprepare(fs->core_clk);
 
 	/*
 	 * Assert resets for all clocks in the clock domain so that
@@ -421,7 +435,7 @@
 	writel_relaxed(regval, fs->gfs_ctl_reg);
 
 	/* Re-enable core clock. */
-	clk_enable(fs->core_clk);
+	clk_prepare_enable(fs->core_clk);
 
 	/* Return clocks to their state before this function. */
 	restore_clocks(fs);
@@ -430,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 8eec807..340f19b 100644
--- a/arch/arm/mach-msm/footswitch-pcom.c
+++ b/arch/arm/mach-msm/footswitch-pcom.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
@@ -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"
 
@@ -92,10 +93,10 @@
 	fs->is_rate_set = !!(clk_get_rate(fs->src_clk));
 	if (!fs->is_rate_set)
 		clk_set_rate(fs->src_clk, fs->src_clk_init_rate);
-	clk_enable(fs->core_clk);
+	clk_prepare_enable(fs->core_clk);
 
 	if (fs->ahb_clk)
-		clk_enable(fs->ahb_clk);
+		clk_prepare_enable(fs->ahb_clk);
 
 	return 0;
 }
@@ -103,8 +104,8 @@
 static void disable_clocks(struct footswitch *fs)
 {
 	if (fs->ahb_clk)
-		clk_disable(fs->ahb_clk);
-	clk_disable(fs->core_clk);
+		clk_disable_unprepare(fs->ahb_clk);
+	clk_disable_unprepare(fs->core_clk);
 }
 
 static int footswitch_is_enabled(struct regulator_dev *rdev)
@@ -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/gpio-v2.c b/arch/arm/mach-msm/gpio-v2.c
index 7ada69a..b716a6c 100644
--- a/arch/arm/mach-msm/gpio-v2.c
+++ b/arch/arm/mach-msm/gpio-v2.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
@@ -20,6 +20,8 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/syscore_ops.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
 
 #include <asm/mach/irq.h>
 
@@ -165,6 +167,7 @@
 	DECLARE_BITMAP(enabled_irqs, NR_MSM_GPIOS);
 	DECLARE_BITMAP(wake_irqs, NR_MSM_GPIOS);
 	DECLARE_BITMAP(dual_edge_irqs, NR_MSM_GPIOS);
+	struct irq_domain domain;
 };
 
 static DEFINE_SPINLOCK(tlmm_lock);
@@ -223,6 +226,21 @@
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct msm_gpio_dev *g_dev = to_msm_gpio_dev(chip);
+	struct irq_domain *domain = &g_dev->domain;
+	return domain->irq_base + (offset - chip->base);
+}
+
+static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq)
+{
+	struct msm_gpio_dev *g_dev = to_msm_gpio_dev(chip);
+	struct irq_domain *domain = &g_dev->domain;
+	return irq - domain->irq_base;
+}
+#else
 static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
 	return MSM_GPIO_TO_INT(offset - chip->base);
@@ -232,6 +250,7 @@
 {
 	return irq - MSM_GPIO_TO_INT(chip->base);
 }
+#endif
 
 static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
 {
@@ -673,6 +692,48 @@
 }
 EXPORT_SYMBOL(msm_gpio_install_direct_irq);
 
+#ifdef CONFIG_OF
+static int msm_gpio_domain_dt_translate(struct irq_domain *d,
+					struct device_node *controller,
+					const u32 *intspec,
+					unsigned int intsize,
+					unsigned long *out_hwirq,
+					unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize != 2)
+		return -EINVAL;
+
+	/* hwirq value */
+	*out_hwirq = intspec[0];
+
+	/* irq flags */
+	*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+
+static struct irq_domain_ops msm_gpio_irq_domain_ops = {
+	.dt_translate = msm_gpio_domain_dt_translate,
+};
+
+int __init msm_gpio_of_init(struct device_node *node,
+			    struct device_node *parent)
+{
+	struct irq_domain *domain = &msm_gpio.domain;
+
+	domain->irq_base = irq_domain_find_free_range(0, NR_MSM_GPIOS);
+	domain->nr_irq = NR_MSM_GPIOS;
+	domain->of_node = of_node_get(node);
+	domain->priv = &msm_gpio;
+	domain->ops = &msm_gpio_irq_domain_ops;
+	irq_domain_add(domain);
+	pr_debug("%s: irq_base = %u\n", __func__, domain->irq_base);
+
+	return 0;
+}
+#endif
+
 MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>");
 MODULE_DESCRIPTION("Driver for Qualcomm MSM TLMMv2 SoC GPIOs");
 MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
index 743e3de..26adec6 100644
--- a/arch/arm/mach-msm/hotplug.c
+++ b/arch/arm/mach-msm/hotplug.c
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 2002 ARM Ltd.
  *  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 as
@@ -13,8 +14,7 @@
 #include <asm/cacheflush.h>
 #include <asm/vfp.h>
 
-#include <mach/pm.h>
-
+#include "pm.h"
 #include "qdss.h"
 #include "spm.h"
 
@@ -68,8 +68,13 @@
 {
 	struct completion *killed =
 		&per_cpu(msm_hotplug_devices, cpu).cpu_killed;
+	int ret;
 
-	return wait_for_completion_timeout(killed, HZ * 5);
+	ret = wait_for_completion_timeout(killed, HZ * 5);
+	if (ret)
+		return ret;
+
+	return msm_pm_wait_cpu_shutdown(cpu);
 }
 
 /*
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 660884c..631d520 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -49,7 +49,9 @@
 #if (NR_CPUS >= 2)
 	mrc	p15, 0, r1, c0, c0, 5	/* MPIDR */
 	ands	r1, r1, #15		/* What CPU am I */
-	addne	r0, r0, #CPU_SAVED_STATE_SIZE
+	mov	r2, #CPU_SAVED_STATE_SIZE
+	mul	r1, r1, r2
+	add	r0, r0, r1
 #endif
 
 	stmia   r0!, {r4-r14}
@@ -149,15 +151,18 @@
 	mov     r1, #'A'
 	str     r1, [r0, #0x00C]
 #endif
-	ldr     r1, =saved_state_end
+	ldr     r1, =saved_state
 	ldr     r2, =msm_pm_collapse_exit
 	adr     r3, msm_pm_collapse_exit
 	add     r1, r1, r3
 	sub     r1, r1, r2
+	add	r1, r1, #CPU_SAVED_STATE_SIZE
 #if (NR_CPUS >= 2)
 	mrc	p15, 0, r2, c0, c0, 5	/* MPIDR */
 	ands	r2, r2, #15		/* What CPU am I */
-	subeq	r1, r1, #CPU_SAVED_STATE_SIZE
+	mov	r3, #CPU_SAVED_STATE_SIZE
+	mul	r2, r2, r3
+	add	r1, r1, r2
 #endif
 
 #ifdef CONFIG_MSM_CPU_AVS
@@ -268,11 +273,7 @@
 	.long	0x0
 
 saved_state:
-#if (NR_CPUS >= 2)
-	.space	CPU_SAVED_STATE_SIZE * 2 /* This code only supports 2 cores */
-#else
-	.space	CPU_SAVED_STATE_SIZE
-#endif
+	.space	CPU_SAVED_STATE_SIZE * NR_CPUS
 saved_state_end:
 
 msm_pm_boot_vector:
diff --git a/arch/arm/mach-msm/idle_stats_device.c b/arch/arm/mach-msm/idle_stats_device.c
index c28cf94..d5a61af 100644
--- a/arch/arm/mach-msm/idle_stats_device.c
+++ b/arch/arm/mach-msm/idle_stats_device.c
@@ -103,17 +103,17 @@
 {
 	hrtimer_cancel(&device->busy_timer);
 	hrtimer_set_expires(&device->busy_timer, us_to_ktime(0));
-	if (device->stats->nr_collected >= MSM_IDLE_STATS_NR_MAX_INTERVALS)
+	if (device->stats->nr_collected >= device->max_samples)
 		return;
 
 	device->stats->pulse_chain[device->stats->nr_collected] = *pulse;
 	device->stats->nr_collected++;
 
-	if (device->stats->nr_collected == MSM_IDLE_STATS_NR_MAX_INTERVALS) {
+	if (device->stats->nr_collected == device->max_samples) {
 		msm_idle_stats_update_event(device,
 			MSM_IDLE_STATS_EVENT_COLLECTION_FULL);
 	} else if (device->stats->nr_collected ==
-				((MSM_IDLE_STATS_NR_MAX_INTERVALS * 3) / 4)) {
+				((device->max_samples * 3) / 4)) {
 		msm_idle_stats_update_event(device,
 			MSM_IDLE_STATS_EVENT_COLLECTION_NEARLY_FULL);
 	}
@@ -140,15 +140,15 @@
 	device->stats->event = 0;
 	device->stats->nr_collected = 0;
 	spin_unlock(&device->lock);
-	if (stats->nr_collected >= MSM_IDLE_STATS_NR_MAX_INTERVALS) {
-		stats->nr_collected = MSM_IDLE_STATS_NR_MAX_INTERVALS;
+	if (stats->nr_collected >= device->max_samples) {
+		stats->nr_collected = device->max_samples;
 	} else {
 	    stats->pulse_chain[stats->nr_collected] = pulse;
 	    stats->nr_collected++;
-	    if (stats->nr_collected == MSM_IDLE_STATS_NR_MAX_INTERVALS)
+	    if (stats->nr_collected == device->max_samples)
 			stats->event |= MSM_IDLE_STATS_EVENT_COLLECTION_FULL;
 	    else if (stats->nr_collected ==
-				 ((MSM_IDLE_STATS_NR_MAX_INTERVALS * 3) / 4))
+				 ((device->max_samples * 3) / 4))
 			stats->event |=
 				MSM_IDLE_STATS_EVENT_COLLECTION_NEARLY_FULL;
 	}
@@ -185,6 +185,9 @@
 	    device->busy_timer_interval = us_to_ktime(stats.next_busy_timer);
 	    if (ktime_to_us(device->idle_start) == 0)
 			start_busy_timer(device, us_to_ktime(stats.busy_timer));
+		if ((stats.max_samples > 0) &&
+			(stats.max_samples <= MSM_IDLE_STATS_NR_MAX_INTERVALS))
+			device->max_samples = stats.max_samples;
 	    spin_unlock(&device->lock);
 	}
 	return ret;
@@ -319,6 +322,7 @@
 	device->stats_vector[1].nr_collected  = 0;
 	device->stats = &device->stats_vector[0];
 	device->busy_timer_interval = us_to_ktime(0);
+	device->max_samples = MSM_IDLE_STATS_NR_MAX_INTERVALS;
 
 	mutex_lock(&device_list_lock);
 	list_add(&device->list, &device_list);
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/board.h b/arch/arm/mach-msm/include/mach/board.h
index 22d5bbc..6eceea7 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -61,6 +61,11 @@
 	struct msm_camera_io_ext ioext;
 	struct msm_camera_io_clk ioclk;
 	uint8_t csid_core;
+	uint8_t is_csiphy;
+	uint8_t is_csic;
+	uint8_t is_csid;
+	uint8_t is_ispif;
+	uint8_t is_vpe;
 	struct msm_bus_scale_pdata *cam_bus_scale_table;
 };
 enum msm_camera_csi_data_format {
@@ -167,26 +172,43 @@
 	BACK_CAMERA_INT_3D,
 };
 
-struct msm8960_privacy_light_cfg {
-	unsigned mpp;
+enum camera_vreg_type {
+	REG_LDO,
+	REG_VS,
 };
 
-struct msm_camera_sensor_platform_info {
-	int mount_angle;
-	int sensor_reset_enable;
-	int sensor_reset;
-	int sensor_pwd;
-	int vcm_pwd;
-	int vcm_enable;
-	int privacy_light;
-	void *privacy_light_info;
+struct camera_vreg_t {
+	char *reg_name;
+	enum camera_vreg_type type;
+	int min_voltage;
+	int max_voltage;
+	int op_mode;
+};
+
+struct msm_gpio_set_tbl {
+	unsigned gpio;
+	unsigned long flags;
+	uint32_t delay;
 };
 
 struct msm_camera_gpio_conf {
 	void *cam_gpiomux_conf_tbl;
 	uint8_t cam_gpiomux_conf_tbl_size;
-	uint16_t *cam_gpio_tbl;
-	uint8_t cam_gpio_tbl_size;
+	struct gpio *cam_gpio_common_tbl;
+	uint8_t cam_gpio_common_tbl_size;
+	struct gpio *cam_gpio_req_tbl;
+	uint8_t cam_gpio_req_tbl_size;
+	struct msm_gpio_set_tbl *cam_gpio_set_tbl;
+	uint8_t cam_gpio_set_tbl_size;
+};
+
+struct msm_camera_sensor_platform_info {
+	int mount_angle;
+	int sensor_reset;
+	struct camera_vreg_t *cam_vreg;
+	int num_vreg;
+	int32_t (*ext_power_ctrl) (int enable);
+	struct msm_camera_gpio_conf *gpio_conf;
 };
 
 struct msm_actuator_info {
@@ -214,7 +236,6 @@
 	struct msm_camera_csi_params csi_params;
 	struct msm_camera_sensor_strobe_flash_data *strobe_flash_data;
 	char *eeprom_data;
-	struct msm_camera_gpio_conf *gpio_conf;
 	enum msm_camera_type camera_type;
 	struct msm_actuator_info *actuator_info;
 };
@@ -298,6 +319,8 @@
 	MDP_REV_40,
 	MDP_REV_41,
 	MDP_REV_42,
+	MDP_REV_43,
+	MDP_REV_44,
 };
 
 struct msm_panel_common_pdata {
@@ -373,6 +396,7 @@
 	int fpga_3d_config_addr;
 	int *gpio;
 	struct mipi_dsi_phy_ctrl *phy_ctrl_settings;
+	char dlane_swap;
 };
 
 struct msm_fb_platform_data {
@@ -443,9 +467,12 @@
 void msm_map_msm7x30_io(void);
 void msm_map_fsm9xxx_io(void);
 void msm_map_copper_io(void);
+void msm_map_msm8625_io(void);
 void msm_init_irq(void);
 void msm_copper_init_irq(void);
 void vic_handle_irq(struct pt_regs *regs);
+void msm_copper_reserve(void);
+void msm_copper_very_early(void);
 
 struct mmc_platform_data;
 int msm_add_sdcc(unsigned int controller,
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 8961c79..06d214f 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -19,6 +19,7 @@
 #include <linux/cdev.h>
 #include <linux/platform_device.h>
 #include <linux/wakelock.h>
+#include <linux/regulator/consumer.h>
 #include "linux/types.h"
 
 #include <mach/board.h>
@@ -74,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,
@@ -84,9 +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 {
@@ -208,6 +213,7 @@
 #define CSI_DECODE_6BIT 0
 #define CSI_DECODE_8BIT 1
 #define CSI_DECODE_10BIT 2
+#define CSI_DECODE_DPCM_10_8_10 5
 
 struct msm_vfe_phy_info {
 	uint32_t sbuf_phy;
@@ -685,7 +691,15 @@
 
 int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info,
 		struct clk **clk_ptr, int num_clk, int enable);
-int msm_sensor_probe_on(struct device *);
-int msm_sensor_probe_off(struct device *);
 int msm_cam_core_reset(void);
+
+int msm_camera_config_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
+		int num_vreg, struct regulator **reg_ptr, int config);
+int msm_camera_enable_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
+		int num_vreg, struct regulator **reg_ptr, int enable);
+
+int msm_camera_config_gpio_table
+	(struct msm_camera_sensor_info *sinfo, int gpio_en);
+int msm_camera_request_gpio_table
+	(struct msm_camera_sensor_info *sinfo, int gpio_en);
 #endif
diff --git a/arch/arm/mach-msm/include/mach/cpuidle.h b/arch/arm/mach-msm/include/mach/cpuidle.h
index b0aa902..37b8d00 100644
--- a/arch/arm/mach-msm/include/mach/cpuidle.h
+++ b/arch/arm/mach-msm/include/mach/cpuidle.h
@@ -15,7 +15,7 @@
 #define __ARCH_ARM_MACH_MSM_CPUIDLE_H
 
 #include <linux/notifier.h>
-#include <mach/pm.h>
+#include "pm.h"
 
 struct msm_cpuidle_state {
 	unsigned int cpu;
diff --git a/arch/arm/mach-msm/include/mach/gpio.h b/arch/arm/mach-msm/include/mach/gpio.h
index fa69b9f..5385f35 100644
--- a/arch/arm/mach-msm/include/mach/gpio.h
+++ b/arch/arm/mach-msm/include/mach/gpio.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  * Author: Mike Lockwood <lockwood@android.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -238,4 +238,9 @@
 }
 #endif
 
+#ifdef CONFIG_OF
+int __init msm_gpio_of_init(struct device_node *node,
+			    struct device_node *parent);
+#endif
+
 #endif /* __ASM_ARCH_MSM_GPIO_H */
diff --git a/arch/arm/mach-msm/include/mach/irqs-7xxx.h b/arch/arm/mach-msm/include/mach/irqs-7xxx.h
index 21ae436..c90b4ee 100644
--- a/arch/arm/mach-msm/include/mach/irqs-7xxx.h
+++ b/arch/arm/mach-msm/include/mach/irqs-7xxx.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  */
 
@@ -79,11 +79,5 @@
 #define INT_CE_IRQ           (32 + 24)
 #endif
 
-/* 7x00A uses 122, but 7x25 has up to 132. */
-#define NR_GPIO_IRQS 133
-#define NR_MSM_IRQS 64
-#define NR_BOARD_IRQS 64
-#define NR_MSM_GPIOS NR_GPIO_IRQS
-
 #define INT_ADSP_A11_SMSM    INT_ADSP_A11
 #endif
diff --git a/arch/arm/mach-msm/include/mach/irqs-8064.h b/arch/arm/mach-msm/include/mach/irqs-8064.h
index 8597111..a5f78f5 100644
--- a/arch/arm/mach-msm/include/mach/irqs-8064.h
+++ b/arch/arm/mach-msm/include/mach/irqs-8064.h
@@ -57,7 +57,7 @@
 #define TLMM_MSM_DIR_CONN_IRQ_8			(GIC_SPI_START + 12)
 #define TLMM_MSM_DIR_CONN_IRQ_9			(GIC_SPI_START + 13)
 #define PM8921_SEC_IRQ_N			(GIC_SPI_START + 14)
-#define PM8018_SEC_IRQ_N			(GIC_SPI_START + 15)
+#define PM8821_SEC_IRQ_N			(GIC_SPI_START + 15)
 #define TLMM_MSM_SUMMARY_IRQ			(GIC_SPI_START + 16)
 #define SPDM_RT_1_IRQ				(GIC_SPI_START + 17)
 #define SPDM_DIAG_IRQ				(GIC_SPI_START + 18)
diff --git a/arch/arm/mach-msm/include/mach/irqs-8625.h b/arch/arm/mach-msm/include/mach/irqs-8625.h
new file mode 100644
index 0000000..3ff73eb
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/irqs-8625.h
@@ -0,0 +1,89 @@
+/* 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 __ASM_ARCH_MSM_IRQS_8625_H
+#define __ASM_ARCH_MSM_IRQS_8625_H
+
+#define GIC_PPI_START		16
+#define GIC_SPI_START		32
+
+/* As per QGIC2 PPI 16 aka 0 is reserved */
+#define MSM8625_INT_A5_PMU_IRQ		(GIC_PPI_START + 1)
+#define MSM8625_INT_DEBUG_TIMER_EXP	(GIC_PPI_START + 2)
+#define MSM8625_INT_GP_TIMER_EXP	(GIC_PPI_START + 3)
+#define MSM8625_INT_COMMRX		(GIC_PPI_START + 4)
+#define MSM8625_INT_COMMTX		(GIC_PPI_START + 5)
+
+/* rest of the PPI's not used
+ */
+
+#define MSM8625_INT_A9_M2A_0		(GIC_SPI_START + 0)
+#define MSM8625_INT_A9_M2A_1		(GIC_SPI_START + 1)
+#define MSM8625_INT_A9_M2A_2		(GIC_SPI_START + 2)
+#define MSM8625_INT_A9_M2A_3		(GIC_SPI_START + 3)
+#define MSM8625_INT_A9_M2A_4		(GIC_SPI_START + 4)
+#define MSM8625_INT_A9_M2A_5		(GIC_SPI_START + 5)
+#define MSM8625_INT_A9_M2A_6		(GIC_SPI_START + 6)
+#define MSM8625_INT_ACSR_MP_CORE_IPC0	(GIC_SPI_START + 7)
+#define MSM8625_INT_ACSR_MP_CORE_IPC1	(GIC_SPI_START + 8)
+#define MSM8625_INT_UART1		(GIC_SPI_START + 9)
+#define MSM8625_INT_UART2		(GIC_SPI_START + 10)
+#define MSM8625_INT_UART3		(GIC_SPI_START + 11)
+#define MSM8625_INT_UART1_RX		(GIC_SPI_START + 12)
+#define MSM8625_INT_UART2_RX		(GIC_SPI_START + 13)
+#define MSM8625_INT_UART3_RX		(GIC_SPI_START + 14)
+#define MSM8625_INT_USB_OTG		(GIC_SPI_START + 15)
+#define MSM8625_INT_DSI_IRQ		(GIC_SPI_START + 16)
+#define MSM8625_INT_CSI_IRQ_1		(GIC_SPI_START + 17)
+#define MSM8625_INT_CSI_IRQ_0		(GIC_SPI_START + 18)
+#define MSM8625_INT_MDP			(GIC_SPI_START + 19)
+#define MSM8625_INT_GRAPHICS		(GIC_SPI_START + 20)
+#define MSM8625_INT_ADM_AARM		(GIC_SPI_START + 21)
+#define MSM8625_INT_ADSP_A11		(GIC_SPI_START + 22)
+#define MSM8625_INT_ADSP_A9_A11		(GIC_SPI_START + 23)
+#define MSM8625_INT_SDC1_0		(GIC_SPI_START + 24)
+#define MSM8625_INT_SDC1_1		(GIC_SPI_START + 25)
+#define MSM8625_INT_SDC2_0		(GIC_SPI_START + 26)
+#define MSM8625_INT_SDC2_1		(GIC_SPI_START + 27)
+#define MSM8625_INT_KEYSENSE		(GIC_SPI_START + 28)
+#define MSM8625_INT_TCHSCRN_SSBI	(GIC_SPI_START + 29)
+#define MSM8625_INT_TCHSCRN1		(GIC_SPI_START + 30)
+#define MSM8625_INT_TCHSCRN2		(GIC_SPI_START + 31)
+
+#define MSM8625_INT_GPIO_GROUP1		(GIC_SPI_START + 32 + 0)
+#define MSM8625_INT_GPIO_GROUP2		(GIC_SPI_START + 32 + 1)
+#define MSM8625_INT_PWB_I2C		(GIC_SPI_START + 32 + 2)
+#define MSM8625_INT_SOFTRESET		(GIC_SPI_START + 32 + 3)
+#define MSM8625_INT_NAND_WR_ER_DONE	(GIC_SPI_START + 32 + 4)
+#define MSM8625_INT_NAND_OP_DONE	(GIC_SPI_START + 32 + 5)
+#define MSM8625_INT_PBUS_ARM11		(GIC_SPI_START + 32 + 6)
+#define MSM8625_INT_AXI_MPU_SMI		(GIC_SPI_START + 32 + 7)
+#define MSM8625_INT_AXI_MPU_EBI1	(GIC_SPI_START + 32 + 8)
+#define MSM8625_INT_AD_HSSD		(GIC_SPI_START + 32 + 9)
+#define MSM8625_INT_NOTUSED		(GIC_SPI_START + 32 + 10)
+#define MSM8625_INT_ARM11_DMA		(GIC_SPI_START + 32 + 11)
+#define MSM8625_INT_TSIF_IRQ		(GIC_SPI_START + 32 + 12)
+#define MSM8625_INT_UART1DM_IRQ		(GIC_SPI_START + 32 + 13)
+#define MSM8625_INT_UART1DM_RX		(GIC_SPI_START + 32 + 14)
+#define MSM8625_INT_USB_HS		(GIC_SPI_START + 32 + 15)
+#define MSM8625_INT_SDC3_0		(GIC_SPI_START + 32 + 16)
+#define MSM8625_INT_SDC3_1		(GIC_SPI_START + 32 + 17)
+#define MSM8625_INT_SDC4_0		(GIC_SPI_START + 32 + 18)
+#define MSM8625_INT_SDC4_1		(GIC_SPI_START + 32 + 19)
+#define MSM8625_INT_UART2DM_IRQ		(GIC_SPI_START + 32 + 20)
+#define MSM8625_INT_UART2DM_RX		(GIC_SPI_START + 32 + 21)
+#define MSM8625_INT_L2CC_EM		(GIC_SPI_START + 32 + 22)
+#define MSM8625_INT_L2CC_INTR		(GIC_SPI_START + 32 + 23)
+#define MSM8625_INT_CE_IRQ		(GIC_SPI_START + 32 + 24)
+
+#define MSM8625_INT_ADSP_A11_SMSM	MSM8625_INT_ADSP_A11
+#endif
diff --git a/arch/arm/mach-msm/include/mach/irqs-9615.h b/arch/arm/mach-msm/include/mach/irqs-9615.h
index 5fba24e..cd8f2a3 100644
--- a/arch/arm/mach-msm/include/mach/irqs-9615.h
+++ b/arch/arm/mach-msm/include/mach/irqs-9615.h
@@ -179,6 +179,7 @@
 #define TLMM_MSM_DIR_CONN_IRQ_21		(GIC_SPI_START + 224)
 #define MSM_SPARE0_IRQ				(GIC_SPI_START + 225)
 #define PMIC_SEC_IRQ_N				(GIC_SPI_START + 226)
+#define USB_HSIC_BAM_IRQ			(GIC_SPI_START + 231)
 #define USB_HSIC_IRQ				(GIC_SPI_START + 232)
 
 #define NR_MSM_IRQS 288
diff --git a/arch/arm/mach-msm/include/mach/irqs-copper.h b/arch/arm/mach-msm/include/mach/irqs-copper.h
index 24da0a4..821eaeb 100644
--- a/arch/arm/mach-msm/include/mach/irqs-copper.h
+++ b/arch/arm/mach-msm/include/mach/irqs-copper.h
@@ -34,7 +34,7 @@
 #define TLMM_MSM_SUMMARY_IRQ		(GIC_SPI_START + 16)
 #define SPS_BAM_DMA_IRQ			(GIC_SPI_START + 105)
 
-#define NR_MSM_IRQS 256
+#define NR_MSM_IRQS 1020 /* Should be 256 - but higher due to bug in sim */
 #define NR_GPIO_IRQS 156
 #define NR_BOARD_IRQS 100
 #define NR_TLMM_MSM_DIR_CONN_IRQ 8
diff --git a/arch/arm/mach-msm/include/mach/irqs.h b/arch/arm/mach-msm/include/mach/irqs.h
index 8c1e4ff..954b673 100644
--- a/arch/arm/mach-msm/include/mach/irqs.h
+++ b/arch/arm/mach-msm/include/mach/irqs.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
@@ -19,6 +19,8 @@
 
 #define MSM_IRQ_BIT(irq)     (1 << ((irq) & 31))
 
+#include "irqs-8625.h"
+
 #if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064) || \
 	defined(CONFIG_ARCH_MSM8930)
 
@@ -63,6 +65,11 @@
 #elif defined(CONFIG_ARCH_MSM7X01A) || defined(CONFIG_ARCH_MSM7X25) \
 	|| defined(CONFIG_ARCH_MSM7X27)
 #include "irqs-7xxx.h"
+
+#define NR_GPIO_IRQS 133
+#define NR_MSM_IRQS 256
+#define NR_BOARD_IRQS 256
+#define NR_MSM_GPIOS NR_GPIO_IRQS
 #elif defined(CONFIG_ARCH_FSM9XXX)
 #include "irqs-fsm9xxx.h"
 #include "sirc.h"
diff --git a/arch/arm/mach-msm/include/mach/mdm2.h b/arch/arm/mach-msm/include/mach/mdm2.h
index acfa38a..78ca88f 100644
--- a/arch/arm/mach-msm/include/mach/mdm2.h
+++ b/arch/arm/mach-msm/include/mach/mdm2.h
@@ -15,6 +15,8 @@
 
 struct mdm_platform_data {
 	char *mdm_version;
+	int ramdump_delay_ms;
+	struct platform_device *peripheral_platform_device;
 };
 
 #endif
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 d545a5f..88bc3c6 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2010, 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
@@ -35,58 +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_QGIC_DIST_BASE    MSM_VIC_BASE
+#define MSM7XXX_GPIO1_PHYS        0xA9200000
+#define MSM7XXX_GPIO1_SIZE        SZ_4K
 
-#define MSM_GPIO1_BASE        IOMEM(0xFA003000)
-#define MSM_GPIO1_PHYS        0xA9200000
-#define MSM_GPIO1_SIZE        SZ_4K
+#define MSM7XXX_GPIO2_PHYS        0xA9300000
+#define MSM7XXX_GPIO2_SIZE        SZ_4K
 
-#define MSM_GPIO2_BASE        IOMEM(0xFA004000)
-#define MSM_GPIO2_PHYS        0xA9300000
-#define MSM_GPIO2_SIZE        SZ_4K
+#define MSM7XXX_CLK_CTL_PHYS      0xA8600000
+#define MSM7XXX_CLK_CTL_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_L2CC_PHYS         0xC0400000
+#define MSM7XXX_L2CC_SIZE         SZ_4K
 
-#define MSM_L2CC_BASE         IOMEM(0xFA006000)
-#define MSM_L2CC_PHYS         0xC0400000
-#define MSM_L2CC_SIZE         SZ_4K
+#define MSM7XXX_UART1_PHYS        0xA9A00000
+#define MSM7XXX_UART1_SIZE        SZ_4K
 
-#define MSM_SHARED_RAM_BASE   IOMEM(0xFA100000)
-#define MSM_SHARED_RAM_SIZE   SZ_1M
+#define MSM7XXX_UART2_PHYS        0xA9B00000
+#define MSM7XXX_UART2_SIZE        SZ_4K
 
-#define MSM_UART1_PHYS        0xA9A00000
-#define MSM_UART1_SIZE        SZ_4K
+#define MSM7XXX_UART3_PHYS        0xA9C00000
+#define MSM7XXX_UART3_SIZE        SZ_4K
 
-#define MSM_UART2_PHYS        0xA9B00000
-#define MSM_UART2_SIZE        SZ_4K
+#define MSM7XXX_MDC_PHYS	  0xAA500000
+#define MSM7XXX_MDC_SIZE          SZ_1M
 
-#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 15b2856..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
@@ -97,5 +97,10 @@
 
 #define APQ8064_SAW_L2_PHYS		0x02012000
 #define APQ8064_SAW_L2_SIZE		SZ_4K
+#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..bb2b019 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,22 @@
 #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
+#define MSM8625_SECONDARY_PHYS		0x0FE00000
+
+#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 +108,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 +123,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..ac45cbd
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_rtb.h
@@ -0,0 +1,69 @@
+/*
+ * 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_LOGBUF,
+	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);
+
+#define ETB_WAYPOINT  do { \
+				BRANCH_TO_NEXT_ISTR; \
+				nop(); \
+				BRANCH_TO_NEXT_ISTR; \
+				nop(); \
+			} while (0)
+
+#define BRANCH_TO_NEXT_ISTR  asm volatile("b .+4\n" : : : "memory")
+/*
+ * both the mb and the isb are needed to ensure enough waypoints for
+ * etb tracing
+ */
+#define LOG_BARRIER	do { \
+				mb(); \
+				isb();\
+			 } while (0)
+#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; }
+
+#define ETB_WAYPOINT
+#define BRANCH_TO_NEXT_ISTR
+/*
+ * Due to a GCC bug, we need to have a nop here in order to prevent an extra
+ * read from being generated after the write.
+ */
+#define LOG_BARRIER		nop()
+#endif
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h
index af47425..4be6d9ea 100644
--- a/arch/arm/mach-msm/include/mach/msm_smd.h
+++ b/arch/arm/mach-msm/include/mach/msm_smd.h
@@ -1,7 +1,7 @@
 /* linux/include/asm-arm/arch-msm/msm_smd.h
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -18,6 +18,9 @@
 #ifndef __ASM_ARCH_MSM_SMD_H
 #define __ASM_ARCH_MSM_SMD_H
 
+#include <linux/io.h>
+#include <mach/msm_smsm.h>
+
 typedef struct smd_channel smd_channel_t;
 
 #define SMD_MAX_CH_NAME_LEN 20 /* includes null char at end */
@@ -28,6 +31,24 @@
 #define SMD_EVENT_STATUS 4
 #define SMD_EVENT_REOPEN_READY 5
 
+/*
+ * SMD Processor ID's.
+ *
+ * For all processors that have both SMSM and SMD clients,
+ * the SMSM Processor ID and the SMD Processor ID will
+ * be the same.  In cases where a processor only supports
+ * SMD, the entry will only exist in this enum.
+ */
+enum {
+	SMD_APPS = SMSM_APPS,
+	SMD_MODEM = SMSM_MODEM,
+	SMD_Q6 = SMSM_Q6,
+	SMD_WCNSS = SMSM_WCNSS,
+	SMD_DSPS = SMSM_DSPS,
+	SMD_MODEM_Q6_FW,
+	NUM_SMD_SUBSYSTEMS,
+};
+
 enum {
 	SMD_APPS_MODEM = 0,
 	SMD_APPS_QDSP,
@@ -49,6 +70,59 @@
 
 };
 
+/*
+ * SMD IRQ Configuration
+ *
+ * Used to initialize IRQ configurations from platform data
+ *
+ * @irq_name: irq_name to query platform data
+ * @irq_id: initialized to -1 in platform data, stores actual irq id on
+ *		successful registration
+ * @out_base: if not null then settings used for outgoing interrupt
+ *		initialied from platform data
+ */
+
+struct smd_irq_config {
+	/* incoming interrupt config */
+	const char *irq_name;
+	unsigned long flags;
+	int irq_id;
+	const char *device_name;
+	const void *dev_id;
+
+	/* outgoing interrupt config */
+	uint32_t out_bit_pos;
+	void __iomem *out_base;
+	uint32_t out_offset;
+};
+
+/*
+ * SMD subsystem configurations
+ *
+ * SMD subsystems configurations for platform data. This contains the
+ * M2A and A2M interrupt configurations for both SMD and SMSM per
+ * subsystem.
+ *
+ * @subsys_name: name of subsystem passed to PIL
+ * @irq_config_id: unique id for each subsystem
+ * @edge: maps to actual remote subsystem edge
+ *
+ */
+struct smd_subsystem_config {
+	unsigned irq_config_id;
+	const char *subsys_name;
+	int edge;
+
+	struct smd_irq_config smd_int;
+	struct smd_irq_config smsm_int;
+
+};
+
+struct smd_platform {
+	uint32_t num_ss_configs;
+	struct smd_subsystem_config *smd_ss_configs;
+};
+
 #ifdef CONFIG_MSM_SMD
 /* warning: notify() may be called before open returns */
 int smd_open(const char *name, smd_channel_t **ch, void *priv,
diff --git a/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h b/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
index 68a3c44..d50fe2b 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010, 2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -41,6 +41,7 @@
 	unsigned used;		/* Input usage actual DSP produced PCM size  */
 	unsigned addr;
 };
+struct audio;
 
 #ifdef CONFIG_HAS_EARLYSUSPEND
 struct audio_suspend_ctl {
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
index 16751fe..a55dee6 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -28,9 +28,15 @@
 	uint32_t		cal_paddr;
 };
 
+struct acdb_atomic_cal_block {
+	atomic_t		cal_size;
+	atomic_t		cal_kvaddr;
+	atomic_t		cal_paddr;
+};
+
 struct acdb_cal_data {
-	uint32_t		num_cal_blocks;
-	struct acdb_cal_block	*cal_blocks;
+	uint32_t			num_cal_blocks;
+	struct acdb_atomic_cal_block	*cal_blocks;
 };
 
 uint32_t get_voice_rx_topology(void);
@@ -44,6 +50,7 @@
 void get_all_vocstrm_cal(struct acdb_cal_block *cal_block);
 void get_all_vocvol_cal(struct acdb_cal_block *cal_block);
 void get_anc_cal(struct acdb_cal_block *cal_block);
+void get_afe_cal(int32_t path, struct acdb_cal_block *cal_block);
 void get_audproc_cal(int32_t path, struct acdb_cal_block *cal_block);
 void get_audstrm_cal(int32_t path, struct acdb_cal_block *cal_block);
 void get_audvol_cal(int32_t path, struct acdb_cal_block *cal_block);
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/qpnp-int.h b/arch/arm/mach-msm/include/mach/qpnp-int.h
new file mode 100644
index 0000000..a79d2fc
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/qpnp-int.h
@@ -0,0 +1,83 @@
+/* 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 QPNPINT_H
+#define QPNPINT_H
+
+#include <linux/spmi.h>
+
+struct qpnp_irq_spec {
+	uint8_t slave; /* 0-15 */
+	uint8_t per; /* 0-255 */
+	uint8_t irq; /* 0-7 */
+};
+
+struct qpnp_local_int {
+	 /* mask - Invoke PMIC Arbiter local mask handler */
+	int (*mask)(struct spmi_controller *spmi_ctrl,
+		    struct qpnp_irq_spec *spec,
+		    uint32_t priv_d);
+	 /* unmask - Invoke PMIC Arbiter local unmask handler */
+	int (*unmask)(struct spmi_controller *spmi_ctrl,
+		      struct qpnp_irq_spec *spec,
+		      uint32_t priv_d);
+	/* register_priv_data - Return per irq priv data */
+	int (*register_priv_data)(struct spmi_controller *spmi_ctrl,
+				  struct qpnp_irq_spec *spec,
+				  uint32_t *priv_d);
+};
+
+#ifdef CONFIG_MSM_QPNP_INT
+/**
+ * qpnpint_of_init() - Device Tree irq initialization
+ *
+ * Standard Device Tree init routine to be called from
+ * of_irq_init().
+ */
+int __init qpnpint_of_init(struct device_node *node,
+			   struct device_node *parent);
+
+/**
+ * qpnpint_register_controller() - Register local interrupt callbacks
+ *
+ * Used by the PMIC Arbiter driver or equivalent to register
+ * callbacks for interrupt events.
+ */
+int qpnpint_register_controller(unsigned int busno,
+				struct qpnp_local_int *li_cb);
+
+/**
+ * qpnpint_handle_irq - Main interrupt handling routine
+ *
+ * Pass a PMIC Arbiter interrupt to Linux.
+ */
+int qpnpint_handle_irq(struct spmi_controller *spmi_ctrl,
+		       struct qpnp_irq_spec *spec);
+#else
+static inline int __init qpnpint_of_init(struct device_node *node,
+				  struct device_node *parent)
+{
+	return -ENXIO;
+}
+static inline int qpnpint_register_controller(unsigned int busno,
+				struct qpnp_local_int *li_cb)
+{
+	return -ENXIO;
+}
+
+static inline int qpnpint_handle_irq(struct spmi_controller *spmi_ctrl,
+		       struct qpnp_irq_spec *spec)
+{
+	return -ENXIO;
+}
+#endif /* CONFIG_MSM_QPNP_INT */
+#endif /* QPNPINT_H */
diff --git a/arch/arm/mach-msm/include/mach/rpm-8064.h b/arch/arm/mach-msm/include/mach/rpm-8064.h
new file mode 100644
index 0000000..c4c6b0a
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/rpm-8064.h
@@ -0,0 +1,432 @@
+/* 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 __ARCH_ARM_MACH_MSM_RPM_8064_H
+#define __ARCH_ARM_MACH_MSM_RPM_8064_H
+
+/* RPM control message RAM enums */
+enum {
+	MSM_RPM_8064_CTRL_VERSION_MAJOR,
+	MSM_RPM_8064_CTRL_VERSION_MINOR,
+	MSM_RPM_8064_CTRL_VERSION_BUILD,
+
+	MSM_RPM_8064_CTRL_REQ_CTX_0,
+	MSM_RPM_8064_CTRL_REQ_CTX_7 = MSM_RPM_8064_CTRL_REQ_CTX_0 + 7,
+	MSM_RPM_8064_CTRL_REQ_SEL_0,
+	MSM_RPM_8064_CTRL_REQ_SEL_3 = MSM_RPM_8064_CTRL_REQ_SEL_0 + 3,
+	MSM_RPM_8064_CTRL_ACK_CTX_0,
+	MSM_RPM_8064_CTRL_ACK_CTX_7 = MSM_RPM_8064_CTRL_ACK_CTX_0 + 7,
+	MSM_RPM_8064_CTRL_ACK_SEL_0,
+	MSM_RPM_8064_CTRL_ACK_SEL_7 = MSM_RPM_8064_CTRL_ACK_SEL_0 + 7,
+};
+
+/* RPM resource select enums defined for RPM core
+   NOT IN SEQUENTIAL ORDER */
+enum {
+	MSM_RPM_8064_SEL_NOTIFICATION					= 0,
+	MSM_RPM_8064_SEL_INVALIDATE					= 1,
+	MSM_RPM_8064_SEL_TRIGGER_TIMED					= 2,
+	MSM_RPM_8064_SEL_RPM_CTL					= 3,
+
+	MSM_RPM_8064_SEL_CXO_CLK					= 5,
+	MSM_RPM_8064_SEL_PXO_CLK					= 6,
+	MSM_RPM_8064_SEL_QDSS_CLK					= 7,
+	MSM_RPM_8064_SEL_APPS_FABRIC_CLK				= 8,
+	MSM_RPM_8064_SEL_SYSTEM_FABRIC_CLK				= 9,
+	MSM_RPM_8064_SEL_MM_FABRIC_CLK					= 10,
+	MSM_RPM_8064_SEL_DAYTONA_FABRIC_CLK				= 11,
+	MSM_RPM_8064_SEL_SFPB_CLK					= 12,
+	MSM_RPM_8064_SEL_CFPB_CLK					= 13,
+	MSM_RPM_8064_SEL_MMFPB_CLK					= 14,
+	MSM_RPM_8064_SEL_EBI1_CLK					= 16,
+
+	MSM_RPM_8064_SEL_APPS_FABRIC_CFG_HALT				= 18,
+	MSM_RPM_8064_SEL_APPS_FABRIC_CFG_CLKMOD				= 19,
+	MSM_RPM_8064_SEL_APPS_FABRIC_CFG_IOCTL				= 20,
+	MSM_RPM_8064_SEL_APPS_FABRIC_ARB				= 21,
+
+	MSM_RPM_8064_SEL_SYS_FABRIC_CFG_HALT				= 22,
+	MSM_RPM_8064_SEL_SYS_FABRIC_CFG_CLKMOD				= 23,
+	MSM_RPM_8064_SEL_SYS_FABRIC_CFG_IOCTL				= 24,
+	MSM_RPM_8064_SEL_SYSTEM_FABRIC_ARB				= 25,
+
+	MSM_RPM_8064_SEL_MMSS_FABRIC_CFG_HALT				= 26,
+	MSM_RPM_8064_SEL_MMSS_FABRIC_CFG_CLKMOD				= 27,
+	MSM_RPM_8064_SEL_MMSS_FABRIC_CFG_IOCTL				= 28,
+	MSM_RPM_8064_SEL_MM_FABRIC_ARB					= 29,
+
+	MSM_RPM_8064_SEL_PM8921_S1					= 30,
+	MSM_RPM_8064_SEL_PM8921_S2					= 31,
+	MSM_RPM_8064_SEL_PM8921_S3					= 32,
+	MSM_RPM_8064_SEL_PM8921_S4					= 33,
+	MSM_RPM_8064_SEL_PM8921_S5					= 34,
+	MSM_RPM_8064_SEL_PM8921_S6					= 35,
+	MSM_RPM_8064_SEL_PM8921_S7					= 36,
+	MSM_RPM_8064_SEL_PM8921_S8					= 37,
+	MSM_RPM_8064_SEL_PM8921_L1					= 38,
+	MSM_RPM_8064_SEL_PM8921_L2					= 39,
+	MSM_RPM_8064_SEL_PM8921_L3					= 40,
+	MSM_RPM_8064_SEL_PM8921_L4					= 41,
+	MSM_RPM_8064_SEL_PM8921_L5					= 42,
+	MSM_RPM_8064_SEL_PM8921_L6					= 43,
+	MSM_RPM_8064_SEL_PM8921_L7					= 44,
+	MSM_RPM_8064_SEL_PM8921_L8					= 45,
+	MSM_RPM_8064_SEL_PM8921_L9					= 46,
+	MSM_RPM_8064_SEL_PM8921_L10					= 47,
+	MSM_RPM_8064_SEL_PM8921_L11					= 48,
+	MSM_RPM_8064_SEL_PM8921_L12					= 49,
+	MSM_RPM_8064_SEL_PM8921_L13					= 50,
+	MSM_RPM_8064_SEL_PM8921_L14					= 51,
+	MSM_RPM_8064_SEL_PM8921_L15					= 52,
+	MSM_RPM_8064_SEL_PM8921_L16					= 53,
+	MSM_RPM_8064_SEL_PM8921_L17					= 54,
+	MSM_RPM_8064_SEL_PM8921_L18					= 55,
+	MSM_RPM_8064_SEL_PM8921_L19					= 56,
+	MSM_RPM_8064_SEL_PM8921_L20					= 57,
+	MSM_RPM_8064_SEL_PM8921_L21					= 58,
+	MSM_RPM_8064_SEL_PM8921_L22					= 59,
+	MSM_RPM_8064_SEL_PM8921_L23					= 60,
+	MSM_RPM_8064_SEL_PM8921_L24					= 61,
+	MSM_RPM_8064_SEL_PM8921_L25					= 62,
+	MSM_RPM_8064_SEL_PM8921_L26					= 63,
+	MSM_RPM_8064_SEL_PM8921_L27					= 64,
+	MSM_RPM_8064_SEL_PM8921_L28					= 65,
+	MSM_RPM_8064_SEL_PM8921_L29					= 66,
+	MSM_RPM_8064_SEL_PM8921_CLK1					= 67,
+	MSM_RPM_8064_SEL_PM8921_CLK2					= 68,
+	MSM_RPM_8064_SEL_PM8921_LVS1					= 69,
+	MSM_RPM_8064_SEL_PM8921_LVS2					= 70,
+	MSM_RPM_8064_SEL_PM8921_LVS3					= 71,
+	MSM_RPM_8064_SEL_PM8921_LVS4					= 72,
+	MSM_RPM_8064_SEL_PM8921_LVS5					= 73,
+	MSM_RPM_8064_SEL_PM8921_LVS6					= 74,
+	MSM_RPM_8064_SEL_PM8921_LVS7					= 75,
+	MSM_RPM_8064_SEL_PM8821_S1					= 76,
+	MSM_RPM_8064_SEL_PM8821_S2					= 77,
+	MSM_RPM_8064_SEL_PM8821_L1					= 78,
+
+	MSM_RPM_8064_SEL_NCP						= 80,
+	MSM_RPM_8064_SEL_CXO_BUFFERS					= 81,
+	MSM_RPM_8064_SEL_USB_OTG_SWITCH					= 82,
+	MSM_RPM_8064_SEL_HDMI_SWITCH					= 83,
+	MSM_RPM_8064_SEL_DDR_DMM					= 84,
+
+	MSM_RPM_8064_SEL_LAST = MSM_RPM_8064_SEL_DDR_DMM,
+};
+
+/* RPM resource (4 byte) word ID enum */
+enum {
+	MSM_RPM_8064_ID_NOTIFICATION_CONFIGURED_0			= 0,
+	MSM_RPM_8064_ID_NOTIFICATION_CONFIGURED_3 =
+		MSM_RPM_8064_ID_NOTIFICATION_CONFIGURED_0 + 3,
+
+	MSM_RPM_8064_ID_NOTIFICATION_REGISTERED_0			= 4,
+	MSM_RPM_8064_ID_NOTIFICATION_REGISTERED_3 =
+		MSM_RPM_8064_ID_NOTIFICATION_REGISTERED_0 + 3,
+
+	MSM_RPM_8064_ID_INVALIDATE_0					= 8,
+	MSM_RPM_8064_ID_INVALIDATE_7 =
+		MSM_RPM_8064_ID_INVALIDATE_0 + 7,
+
+	MSM_RPM_8064_ID_TRIGGER_TIMED_TO				= 16,
+	MSM_RPM_8064_ID_TRIGGER_TIMED_SCLK_COUNT			= 17,
+
+	MSM_RPM_8064_ID_RPM_CTL						= 18,
+
+	/* TRIGGER_CLEAR/SET deprecated in these 24 RESERVED bytes */
+	MSM_RPM_8064_ID_RESERVED_0					= 19,
+	MSM_RPM_8064_ID_RESERVED_5 =
+		MSM_RPM_8064_ID_RESERVED_0 + 5,
+
+	MSM_RPM_8064_ID_CXO_CLK						= 25,
+	MSM_RPM_8064_ID_PXO_CLK						= 26,
+	MSM_RPM_8064_ID_APPS_FABRIC_CLK					= 27,
+	MSM_RPM_8064_ID_SYSTEM_FABRIC_CLK				= 28,
+	MSM_RPM_8064_ID_MM_FABRIC_CLK					= 29,
+	MSM_RPM_8064_ID_DAYTONA_FABRIC_CLK				= 30,
+	MSM_RPM_8064_ID_SFPB_CLK					= 31,
+	MSM_RPM_8064_ID_CFPB_CLK					= 32,
+	MSM_RPM_8064_ID_MMFPB_CLK					= 33,
+	MSM_RPM_8064_ID_EBI1_CLK					= 34,
+
+	MSM_RPM_8064_ID_APPS_FABRIC_CFG_HALT_0				= 35,
+	MSM_RPM_8064_ID_APPS_FABRIC_CFG_HALT_1				= 36,
+	MSM_RPM_8064_ID_APPS_FABRIC_CFG_CLKMOD_0			= 37,
+	MSM_RPM_8064_ID_APPS_FABRIC_CFG_CLKMOD_1			= 38,
+	MSM_RPM_8064_ID_APPS_FABRIC_CFG_CLKMOD_2			= 39,
+	MSM_RPM_8064_ID_APPS_FABRIC_CFG_IOCTL				= 40,
+	MSM_RPM_8064_ID_APPS_FABRIC_ARB_0				= 41,
+	MSM_RPM_8064_ID_APPS_FABRIC_ARB_11 =
+		MSM_RPM_8064_ID_APPS_FABRIC_ARB_0 + 11,
+
+	MSM_RPM_8064_ID_SYS_FABRIC_CFG_HALT_0				= 53,
+	MSM_RPM_8064_ID_SYS_FABRIC_CFG_HALT_1				= 54,
+	MSM_RPM_8064_ID_SYS_FABRIC_CFG_CLKMOD_0				= 55,
+	MSM_RPM_8064_ID_SYS_FABRIC_CFG_CLKMOD_1				= 56,
+	MSM_RPM_8064_ID_SYS_FABRIC_CFG_CLKMOD_2				= 57,
+	MSM_RPM_8064_ID_SYS_FABRIC_CFG_IOCTL				= 58,
+	MSM_RPM_8064_ID_SYSTEM_FABRIC_ARB_0				= 59,
+	MSM_RPM_8064_ID_SYSTEM_FABRIC_ARB_29 =
+		MSM_RPM_8064_ID_SYSTEM_FABRIC_ARB_0 + 29,
+
+	MSM_RPM_8064_ID_MMSS_FABRIC_CFG_HALT_0				= 89,
+	MSM_RPM_8064_ID_MMSS_FABRIC_CFG_HALT_1				= 90,
+	MSM_RPM_8064_ID_MMSS_FABRIC_CFG_CLKMOD_0			= 91,
+	MSM_RPM_8064_ID_MMSS_FABRIC_CFG_CLKMOD_1			= 92,
+	MSM_RPM_8064_ID_MMSS_FABRIC_CFG_CLKMOD_2			= 93,
+	MSM_RPM_8064_ID_MMSS_FABRIC_CFG_IOCTL				= 94,
+	MSM_RPM_8064_ID_MM_FABRIC_ARB_0					= 95,
+	MSM_RPM_8064_ID_MM_FABRIC_ARB_20 =
+		MSM_RPM_8064_ID_MM_FABRIC_ARB_0 + 20,
+
+	MSM_RPM_8064_ID_PM8921_S1_0					= 116,
+	MSM_RPM_8064_ID_PM8921_S1_1					= 117,
+	MSM_RPM_8064_ID_PM8921_S2_0					= 118,
+	MSM_RPM_8064_ID_PM8921_S2_1					= 119,
+	MSM_RPM_8064_ID_PM8921_S3_0					= 120,
+	MSM_RPM_8064_ID_PM8921_S3_1					= 121,
+	MSM_RPM_8064_ID_PM8921_S4_0					= 122,
+	MSM_RPM_8064_ID_PM8921_S4_1					= 123,
+	MSM_RPM_8064_ID_PM8921_S5_0					= 124,
+	MSM_RPM_8064_ID_PM8921_S5_1					= 125,
+	MSM_RPM_8064_ID_PM8921_S6_0					= 126,
+	MSM_RPM_8064_ID_PM8921_S6_1					= 127,
+	MSM_RPM_8064_ID_PM8921_S7_0					= 128,
+	MSM_RPM_8064_ID_PM8921_S7_1					= 129,
+	MSM_RPM_8064_ID_PM8921_S8_0					= 130,
+	MSM_RPM_8064_ID_PM8921_S8_1					= 131,
+	MSM_RPM_8064_ID_PM8921_L1_0					= 132,
+	MSM_RPM_8064_ID_PM8921_L1_1					= 133,
+	MSM_RPM_8064_ID_PM8921_L2_0					= 134,
+	MSM_RPM_8064_ID_PM8921_L2_1					= 135,
+	MSM_RPM_8064_ID_PM8921_L3_0					= 136,
+	MSM_RPM_8064_ID_PM8921_L3_1					= 137,
+	MSM_RPM_8064_ID_PM8921_L4_0					= 138,
+	MSM_RPM_8064_ID_PM8921_L4_1					= 139,
+	MSM_RPM_8064_ID_PM8921_L5_0					= 140,
+	MSM_RPM_8064_ID_PM8921_L5_1					= 141,
+	MSM_RPM_8064_ID_PM8921_L6_0					= 142,
+	MSM_RPM_8064_ID_PM8921_L6_1					= 143,
+	MSM_RPM_8064_ID_PM8921_L7_0					= 144,
+	MSM_RPM_8064_ID_PM8921_L7_1					= 145,
+	MSM_RPM_8064_ID_PM8921_L8_0					= 146,
+	MSM_RPM_8064_ID_PM8921_L8_1					= 147,
+	MSM_RPM_8064_ID_PM8921_L9_0					= 148,
+	MSM_RPM_8064_ID_PM8921_L9_1					= 149,
+	MSM_RPM_8064_ID_PM8921_L10_0					= 150,
+	MSM_RPM_8064_ID_PM8921_L10_1					= 151,
+	MSM_RPM_8064_ID_PM8921_L11_0					= 152,
+	MSM_RPM_8064_ID_PM8921_L11_1					= 153,
+	MSM_RPM_8064_ID_PM8921_L12_0					= 154,
+	MSM_RPM_8064_ID_PM8921_L12_1					= 155,
+	MSM_RPM_8064_ID_PM8921_L13_0					= 156,
+	MSM_RPM_8064_ID_PM8921_L13_1					= 157,
+	MSM_RPM_8064_ID_PM8921_L14_0					= 158,
+	MSM_RPM_8064_ID_PM8921_L14_1					= 159,
+	MSM_RPM_8064_ID_PM8921_L15_0					= 160,
+	MSM_RPM_8064_ID_PM8921_L15_1					= 161,
+	MSM_RPM_8064_ID_PM8921_L16_0					= 162,
+	MSM_RPM_8064_ID_PM8921_L16_1					= 163,
+	MSM_RPM_8064_ID_PM8921_L17_0					= 164,
+	MSM_RPM_8064_ID_PM8921_L17_1					= 165,
+	MSM_RPM_8064_ID_PM8921_L18_0					= 166,
+	MSM_RPM_8064_ID_PM8921_L18_1					= 167,
+	MSM_RPM_8064_ID_PM8921_L19_0					= 168,
+	MSM_RPM_8064_ID_PM8921_L19_1					= 169,
+	MSM_RPM_8064_ID_PM8921_L20_0					= 170,
+	MSM_RPM_8064_ID_PM8921_L20_1					= 171,
+	MSM_RPM_8064_ID_PM8921_L21_0					= 172,
+	MSM_RPM_8064_ID_PM8921_L21_1					= 173,
+	MSM_RPM_8064_ID_PM8921_L22_0					= 174,
+	MSM_RPM_8064_ID_PM8921_L22_1					= 175,
+	MSM_RPM_8064_ID_PM8921_L23_0					= 176,
+	MSM_RPM_8064_ID_PM8921_L23_1					= 177,
+	MSM_RPM_8064_ID_PM8921_L24_0					= 178,
+	MSM_RPM_8064_ID_PM8921_L24_1					= 179,
+	MSM_RPM_8064_ID_PM8921_L25_0					= 180,
+	MSM_RPM_8064_ID_PM8921_L25_1					= 181,
+	MSM_RPM_8064_ID_PM8921_L26_0					= 182,
+	MSM_RPM_8064_ID_PM8921_L26_1					= 183,
+	MSM_RPM_8064_ID_PM8921_L27_0					= 184,
+	MSM_RPM_8064_ID_PM8921_L27_1					= 185,
+	MSM_RPM_8064_ID_PM8921_L28_0					= 186,
+	MSM_RPM_8064_ID_PM8921_L28_1					= 187,
+	MSM_RPM_8064_ID_PM8921_L29_0					= 188,
+	MSM_RPM_8064_ID_PM8921_L29_1					= 189,
+	MSM_RPM_8064_ID_PM8921_CLK1_0					= 190,
+	MSM_RPM_8064_ID_PM8921_CLK1_1					= 191,
+	MSM_RPM_8064_ID_PM8921_CLK2_0					= 192,
+	MSM_RPM_8064_ID_PM8921_CLK2_1					= 193,
+	MSM_RPM_8064_ID_PM8921_LVS1					= 194,
+	MSM_RPM_8064_ID_PM8921_LVS2					= 195,
+	MSM_RPM_8064_ID_PM8921_LVS3					= 196,
+	MSM_RPM_8064_ID_PM8921_LVS4					= 197,
+	MSM_RPM_8064_ID_PM8921_LVS5					= 198,
+	MSM_RPM_8064_ID_PM8921_LVS6					= 199,
+	MSM_RPM_8064_ID_PM8921_LVS7					= 200,
+	MSM_RPM_8064_ID_PM8821_S1_0					= 201,
+	MSM_RPM_8064_ID_PM8821_S1_1					= 202,
+	MSM_RPM_8064_ID_PM8821_S2_0					= 203,
+	MSM_RPM_8064_ID_PM8821_S2_1					= 204,
+	MSM_RPM_8064_ID_PM8821_L1_0					= 205,
+	MSM_RPM_8064_ID_PM8821_L1_1					= 206,
+	MSM_RPM_8064_ID_NCP_0						= 207,
+	MSM_RPM_8064_ID_NCP_1						= 208,
+	MSM_RPM_8064_ID_CXO_BUFFERS					= 209,
+	MSM_RPM_8064_ID_USB_OTG_SWITCH					= 210,
+	MSM_RPM_8064_ID_HDMI_SWITCH					= 211,
+	MSM_RPM_8064_ID_DDR_DMM_0					= 212,
+	MSM_RPM_8064_ID_DDR_DMM_1					= 213,
+	MSM_RPM_8064_ID_QDSS_CLK					= 214,
+
+	MSM_RPM_8064_ID_LAST = MSM_RPM_8064_ID_QDSS_CLK,
+};
+
+
+/* RPM status ID enum */
+enum {
+	MSM_RPM_8064_STATUS_ID_VERSION_MAJOR				= 0,
+	MSM_RPM_8064_STATUS_ID_VERSION_MINOR				= 1,
+	MSM_RPM_8064_STATUS_ID_VERSION_BUILD				= 2,
+	MSM_RPM_8064_STATUS_ID_SUPPORTED_RESOURCES_0			= 3,
+	MSM_RPM_8064_STATUS_ID_SUPPORTED_RESOURCES_1			= 4,
+	MSM_RPM_8064_STATUS_ID_SUPPORTED_RESOURCES_2			= 5,
+	MSM_RPM_8064_STATUS_ID_RESERVED_SUPPORTED_RESOURCES_0		= 6,
+	MSM_RPM_8064_STATUS_ID_SEQUENCE					= 7,
+	MSM_RPM_8064_STATUS_ID_RPM_CTL					= 8,
+	MSM_RPM_8064_STATUS_ID_CXO_CLK					= 9,
+	MSM_RPM_8064_STATUS_ID_PXO_CLK					= 10,
+	MSM_RPM_8064_STATUS_ID_APPS_FABRIC_CLK				= 11,
+	MSM_RPM_8064_STATUS_ID_SYSTEM_FABRIC_CLK			= 12,
+	MSM_RPM_8064_STATUS_ID_MM_FABRIC_CLK				= 13,
+	MSM_RPM_8064_STATUS_ID_DAYTONA_FABRIC_CLK			= 14,
+	MSM_RPM_8064_STATUS_ID_SFPB_CLK					= 15,
+	MSM_RPM_8064_STATUS_ID_CFPB_CLK					= 16,
+	MSM_RPM_8064_STATUS_ID_MMFPB_CLK				= 17,
+	MSM_RPM_8064_STATUS_ID_EBI1_CLK					= 18,
+	MSM_RPM_8064_STATUS_ID_APPS_FABRIC_CFG_HALT			= 19,
+	MSM_RPM_8064_STATUS_ID_APPS_FABRIC_CFG_CLKMOD			= 20,
+	MSM_RPM_8064_STATUS_ID_APPS_FABRIC_CFG_IOCTL			= 21,
+	MSM_RPM_8064_STATUS_ID_APPS_FABRIC_ARB				= 22,
+	MSM_RPM_8064_STATUS_ID_SYS_FABRIC_CFG_HALT			= 23,
+	MSM_RPM_8064_STATUS_ID_SYS_FABRIC_CFG_CLKMOD			= 24,
+	MSM_RPM_8064_STATUS_ID_SYS_FABRIC_CFG_IOCTL			= 25,
+	MSM_RPM_8064_STATUS_ID_SYSTEM_FABRIC_ARB			= 26,
+	MSM_RPM_8064_STATUS_ID_MMSS_FABRIC_CFG_HALT			= 27,
+	MSM_RPM_8064_STATUS_ID_MMSS_FABRIC_CFG_CLKMOD			= 28,
+	MSM_RPM_8064_STATUS_ID_MMSS_FABRIC_CFG_IOCTL			= 29,
+	MSM_RPM_8064_STATUS_ID_MM_FABRIC_ARB				= 30,
+	MSM_RPM_8064_STATUS_ID_PM8921_S1_0				= 31,
+	MSM_RPM_8064_STATUS_ID_PM8921_S1_1				= 32,
+	MSM_RPM_8064_STATUS_ID_PM8921_S2_0				= 33,
+	MSM_RPM_8064_STATUS_ID_PM8921_S2_1				= 34,
+	MSM_RPM_8064_STATUS_ID_PM8921_S3_0				= 35,
+	MSM_RPM_8064_STATUS_ID_PM8921_S3_1				= 36,
+	MSM_RPM_8064_STATUS_ID_PM8921_S4_0				= 37,
+	MSM_RPM_8064_STATUS_ID_PM8921_S4_1				= 38,
+	MSM_RPM_8064_STATUS_ID_PM8921_S5_0				= 39,
+	MSM_RPM_8064_STATUS_ID_PM8921_S5_1				= 40,
+	MSM_RPM_8064_STATUS_ID_PM8921_S6_0				= 41,
+	MSM_RPM_8064_STATUS_ID_PM8921_S6_1				= 42,
+	MSM_RPM_8064_STATUS_ID_PM8921_S7_0				= 43,
+	MSM_RPM_8064_STATUS_ID_PM8921_S7_1				= 44,
+	MSM_RPM_8064_STATUS_ID_PM8921_S8_0				= 45,
+	MSM_RPM_8064_STATUS_ID_PM8921_S8_1				= 46,
+	MSM_RPM_8064_STATUS_ID_PM8921_L1_0				= 47,
+	MSM_RPM_8064_STATUS_ID_PM8921_L1_1				= 48,
+	MSM_RPM_8064_STATUS_ID_PM8921_L2_0				= 49,
+	MSM_RPM_8064_STATUS_ID_PM8921_L2_1				= 50,
+	MSM_RPM_8064_STATUS_ID_PM8921_L3_0				= 51,
+	MSM_RPM_8064_STATUS_ID_PM8921_L3_1				= 52,
+	MSM_RPM_8064_STATUS_ID_PM8921_L4_0				= 53,
+	MSM_RPM_8064_STATUS_ID_PM8921_L4_1				= 54,
+	MSM_RPM_8064_STATUS_ID_PM8921_L5_0				= 55,
+	MSM_RPM_8064_STATUS_ID_PM8921_L5_1				= 56,
+	MSM_RPM_8064_STATUS_ID_PM8921_L6_0				= 57,
+	MSM_RPM_8064_STATUS_ID_PM8921_L6_1				= 58,
+	MSM_RPM_8064_STATUS_ID_PM8921_L7_0				= 59,
+	MSM_RPM_8064_STATUS_ID_PM8921_L7_1				= 60,
+	MSM_RPM_8064_STATUS_ID_PM8921_L8_0				= 61,
+	MSM_RPM_8064_STATUS_ID_PM8921_L8_1				= 62,
+	MSM_RPM_8064_STATUS_ID_PM8921_L9_0				= 63,
+	MSM_RPM_8064_STATUS_ID_PM8921_L9_1				= 64,
+	MSM_RPM_8064_STATUS_ID_PM8921_L10_0				= 65,
+	MSM_RPM_8064_STATUS_ID_PM8921_L10_1				= 66,
+	MSM_RPM_8064_STATUS_ID_PM8921_L11_0				= 67,
+	MSM_RPM_8064_STATUS_ID_PM8921_L11_1				= 68,
+	MSM_RPM_8064_STATUS_ID_PM8921_L12_0				= 69,
+	MSM_RPM_8064_STATUS_ID_PM8921_L12_1				= 70,
+	MSM_RPM_8064_STATUS_ID_PM8921_L13_0				= 71,
+	MSM_RPM_8064_STATUS_ID_PM8921_L13_1				= 72,
+	MSM_RPM_8064_STATUS_ID_PM8921_L14_0				= 73,
+	MSM_RPM_8064_STATUS_ID_PM8921_L14_1				= 74,
+	MSM_RPM_8064_STATUS_ID_PM8921_L15_0				= 75,
+	MSM_RPM_8064_STATUS_ID_PM8921_L15_1				= 76,
+	MSM_RPM_8064_STATUS_ID_PM8921_L16_0				= 77,
+	MSM_RPM_8064_STATUS_ID_PM8921_L16_1				= 78,
+	MSM_RPM_8064_STATUS_ID_PM8921_L17_0				= 79,
+	MSM_RPM_8064_STATUS_ID_PM8921_L17_1				= 80,
+	MSM_RPM_8064_STATUS_ID_PM8921_L18_0				= 81,
+	MSM_RPM_8064_STATUS_ID_PM8921_L18_1				= 82,
+	MSM_RPM_8064_STATUS_ID_PM8921_L19_0				= 83,
+	MSM_RPM_8064_STATUS_ID_PM8921_L19_1				= 84,
+	MSM_RPM_8064_STATUS_ID_PM8921_L20_0				= 85,
+	MSM_RPM_8064_STATUS_ID_PM8921_L20_1				= 86,
+	MSM_RPM_8064_STATUS_ID_PM8921_L21_0				= 87,
+	MSM_RPM_8064_STATUS_ID_PM8921_L21_1				= 88,
+	MSM_RPM_8064_STATUS_ID_PM8921_L22_0				= 89,
+	MSM_RPM_8064_STATUS_ID_PM8921_L22_1				= 90,
+	MSM_RPM_8064_STATUS_ID_PM8921_L23_0				= 91,
+	MSM_RPM_8064_STATUS_ID_PM8921_L23_1				= 92,
+	MSM_RPM_8064_STATUS_ID_PM8921_L24_0				= 93,
+	MSM_RPM_8064_STATUS_ID_PM8921_L24_1				= 94,
+	MSM_RPM_8064_STATUS_ID_PM8921_L25_0				= 95,
+	MSM_RPM_8064_STATUS_ID_PM8921_L25_1				= 96,
+	MSM_RPM_8064_STATUS_ID_PM8921_L26_0				= 97,
+	MSM_RPM_8064_STATUS_ID_PM8921_L26_1				= 98,
+	MSM_RPM_8064_STATUS_ID_PM8921_L27_0				= 99,
+	MSM_RPM_8064_STATUS_ID_PM8921_L27_1				= 100,
+	MSM_RPM_8064_STATUS_ID_PM8921_L28_0				= 101,
+	MSM_RPM_8064_STATUS_ID_PM8921_L28_1				= 102,
+	MSM_RPM_8064_STATUS_ID_PM8921_L29_0				= 103,
+	MSM_RPM_8064_STATUS_ID_PM8921_L29_1				= 104,
+	MSM_RPM_8064_STATUS_ID_PM8921_CLK1_0				= 105,
+	MSM_RPM_8064_STATUS_ID_PM8921_CLK1_1				= 106,
+	MSM_RPM_8064_STATUS_ID_PM8921_CLK2_0				= 107,
+	MSM_RPM_8064_STATUS_ID_PM8921_CLK2_1				= 108,
+	MSM_RPM_8064_STATUS_ID_PM8921_LVS1				= 109,
+	MSM_RPM_8064_STATUS_ID_PM8921_LVS2				= 110,
+	MSM_RPM_8064_STATUS_ID_PM8921_LVS3				= 111,
+	MSM_RPM_8064_STATUS_ID_PM8921_LVS4				= 112,
+	MSM_RPM_8064_STATUS_ID_PM8921_LVS5				= 113,
+	MSM_RPM_8064_STATUS_ID_PM8921_LVS6				= 114,
+	MSM_RPM_8064_STATUS_ID_PM8921_LVS7				= 115,
+	MSM_RPM_8064_STATUS_ID_PM8821_S1_0				= 116,
+	MSM_RPM_8064_STATUS_ID_PM8821_S1_1				= 117,
+	MSM_RPM_8064_STATUS_ID_PM8821_S2_0				= 118,
+	MSM_RPM_8064_STATUS_ID_PM8821_S2_1				= 119,
+	MSM_RPM_8064_STATUS_ID_PM8821_L1_0				= 120,
+	MSM_RPM_8064_STATUS_ID_PM8821_L1_1				= 121,
+	MSM_RPM_8064_STATUS_ID_NCP_0					= 122,
+	MSM_RPM_8064_STATUS_ID_NCP_1					= 123,
+	MSM_RPM_8064_STATUS_ID_CXO_BUFFERS				= 124,
+	MSM_RPM_8064_STATUS_ID_USB_OTG_SWITCH				= 125,
+	MSM_RPM_8064_STATUS_ID_HDMI_SWITCH				= 126,
+	MSM_RPM_8064_STATUS_ID_DDR_DMM_0				= 127,
+	MSM_RPM_8064_STATUS_ID_DDR_DMM_1				= 128,
+	MSM_RPM_8064_STATUS_ID_EBI1_CH0_RANGE				= 129,
+	MSM_RPM_8064_STATUS_ID_EBI1_CH1_RANGE				= 130,
+
+	MSM_RPM_8064_STATUS_ID_LAST = MSM_RPM_8064_STATUS_ID_EBI1_CH1_RANGE,
+};
+
+#endif /* __ARCH_ARM_MACH_MSM_RPM_8064_H */
diff --git a/arch/arm/mach-msm/include/mach/rpm-8660.h b/arch/arm/mach-msm/include/mach/rpm-8660.h
index 23ffc5d..5e3b404 100644
--- a/arch/arm/mach-msm/include/mach/rpm-8660.h
+++ b/arch/arm/mach-msm/include/mach/rpm-8660.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,469 +13,443 @@
 #ifndef __ARCH_ARM_MACH_MSM_RPM_8660_H
 #define __ARCH_ARM_MACH_MSM_RPM_8660_H
 
-#define RPM_MAJOR_VER	2
-#define RPM_MINOR_VER	0
-#define RPM_BUILD_VER	0
-
-
 /* RPM control message RAM enums */
 enum {
-	MSM_RPM_CTRL_VERSION_MAJOR,
-	MSM_RPM_CTRL_VERSION_MINOR,
-	MSM_RPM_CTRL_VERSION_BUILD,
+	MSM_RPM_8660_CTRL_VERSION_MAJOR,
+	MSM_RPM_8660_CTRL_VERSION_MINOR,
+	MSM_RPM_8660_CTRL_VERSION_BUILD,
 
-	MSM_RPM_CTRL_REQ_CTX_0,
-	MSM_RPM_CTRL_REQ_CTX_7 = MSM_RPM_CTRL_REQ_CTX_0 + 7,
-	MSM_RPM_CTRL_REQ_SEL_0,
-	MSM_RPM_CTRL_REQ_SEL_7 = MSM_RPM_CTRL_REQ_SEL_0 + 7,
-	MSM_RPM_CTRL_ACK_CTX_0,
-	MSM_RPM_CTRL_ACK_CTX_7 = MSM_RPM_CTRL_ACK_CTX_0 + 7,
-	MSM_RPM_CTRL_ACK_SEL_0,
-	MSM_RPM_CTRL_ACK_SEL_7 = MSM_RPM_CTRL_ACK_SEL_0 + 7,
+	MSM_RPM_8660_CTRL_REQ_CTX_0,
+	MSM_RPM_8660_CTRL_REQ_CTX_7 = MSM_RPM_8660_CTRL_REQ_CTX_0 + 7,
+	MSM_RPM_8660_CTRL_REQ_SEL_0,
+	MSM_RPM_8660_CTRL_REQ_SEL_7 = MSM_RPM_8660_CTRL_REQ_SEL_0 + 7,
+	MSM_RPM_8660_CTRL_ACK_CTX_0,
+	MSM_RPM_8660_CTRL_ACK_CTX_7 = MSM_RPM_8660_CTRL_ACK_CTX_0 + 7,
+	MSM_RPM_8660_CTRL_ACK_SEL_0,
+	MSM_RPM_8660_CTRL_ACK_SEL_7 = MSM_RPM_8660_CTRL_ACK_SEL_0 + 7,
 };
 
 enum {
-	MSM_RPM_SEL_NOTIFICATION,
-	MSM_RPM_SEL_INVALIDATE,
-	MSM_RPM_SEL_TRIGGER_TIMED,
-	MSM_RPM_SEL_TRIGGER_SET,
-	MSM_RPM_SEL_TRIGGER_CLEAR,
+	MSM_RPM_8660_SEL_NOTIFICATION,
+	MSM_RPM_8660_SEL_INVALIDATE,
+	MSM_RPM_8660_SEL_TRIGGER_TIMED,
+	MSM_RPM_8660_SEL_TRIGGER_SET,
+	MSM_RPM_8660_SEL_TRIGGER_CLEAR,
 
-	MSM_RPM_SEL_CXO_CLK,
-	MSM_RPM_SEL_PXO_CLK,
-	MSM_RPM_SEL_PLL_4,
-	MSM_RPM_SEL_APPS_FABRIC_CLK,
-	MSM_RPM_SEL_SYSTEM_FABRIC_CLK,
-	MSM_RPM_SEL_MM_FABRIC_CLK,
-	MSM_RPM_SEL_DAYTONA_FABRIC_CLK,
-	MSM_RPM_SEL_SFPB_CLK,
-	MSM_RPM_SEL_CFPB_CLK,
-	MSM_RPM_SEL_MMFPB_CLK,
-	MSM_RPM_SEL_SMI_CLK,
-	MSM_RPM_SEL_EBI1_CLK,
+	MSM_RPM_8660_SEL_CXO_CLK,
+	MSM_RPM_8660_SEL_PXO_CLK,
+	MSM_RPM_8660_SEL_PLL_4,
+	MSM_RPM_8660_SEL_APPS_FABRIC_CLK,
+	MSM_RPM_8660_SEL_SYSTEM_FABRIC_CLK,
+	MSM_RPM_8660_SEL_MM_FABRIC_CLK,
+	MSM_RPM_8660_SEL_DAYTONA_FABRIC_CLK,
+	MSM_RPM_8660_SEL_SFPB_CLK,
+	MSM_RPM_8660_SEL_CFPB_CLK,
+	MSM_RPM_8660_SEL_MMFPB_CLK,
+	MSM_RPM_8660_SEL_SMI_CLK,
+	MSM_RPM_8660_SEL_EBI1_CLK,
 
-	MSM_RPM_SEL_APPS_L2_CACHE_CTL,
+	MSM_RPM_8660_SEL_APPS_L2_CACHE_CTL,
 
-	MSM_RPM_SEL_APPS_FABRIC_HALT,
-	MSM_RPM_SEL_APPS_FABRIC_CLOCK_MODE,
-	MSM_RPM_SEL_APPS_FABRIC_IOCTL,
-	MSM_RPM_SEL_APPS_FABRIC_ARB,
+	MSM_RPM_8660_SEL_APPS_FABRIC_HALT,
+	MSM_RPM_8660_SEL_APPS_FABRIC_CLOCK_MODE,
+	MSM_RPM_8660_SEL_APPS_FABRIC_IOCTL,
+	MSM_RPM_8660_SEL_APPS_FABRIC_ARB,
 
-	MSM_RPM_SEL_SYSTEM_FABRIC_HALT,
-	MSM_RPM_SEL_SYSTEM_FABRIC_CLOCK_MODE,
-	MSM_RPM_SEL_SYSTEM_FABRIC_IOCTL,
-	MSM_RPM_SEL_SYSTEM_FABRIC_ARB,
+	MSM_RPM_8660_SEL_SYSTEM_FABRIC_HALT,
+	MSM_RPM_8660_SEL_SYSTEM_FABRIC_CLOCK_MODE,
+	MSM_RPM_8660_SEL_SYSTEM_FABRIC_IOCTL,
+	MSM_RPM_8660_SEL_SYSTEM_FABRIC_ARB,
 
-	MSM_RPM_SEL_MM_FABRIC_HALT,
-	MSM_RPM_SEL_MM_FABRIC_CLOCK_MODE,
-	MSM_RPM_SEL_MM_FABRIC_IOCTL,
-	MSM_RPM_SEL_MM_FABRIC_ARB,
+	MSM_RPM_8660_SEL_MM_FABRIC_HALT,
+	MSM_RPM_8660_SEL_MM_FABRIC_CLOCK_MODE,
+	MSM_RPM_8660_SEL_MM_FABRIC_IOCTL,
+	MSM_RPM_8660_SEL_MM_FABRIC_ARB,
 
-	MSM_RPM_SEL_SMPS0B,
-	MSM_RPM_SEL_SMPS1B,
-	MSM_RPM_SEL_SMPS2B,
-	MSM_RPM_SEL_SMPS3B,
-	MSM_RPM_SEL_SMPS4B,
-	MSM_RPM_SEL_LDO0B,
-	MSM_RPM_SEL_LDO1B,
-	MSM_RPM_SEL_LDO2B,
-	MSM_RPM_SEL_LDO3B,
-	MSM_RPM_SEL_LDO4B,
-	MSM_RPM_SEL_LDO5B,
-	MSM_RPM_SEL_LDO6B,
-	MSM_RPM_SEL_LVS0B,
-	MSM_RPM_SEL_LVS1B,
-	MSM_RPM_SEL_LVS2B,
-	MSM_RPM_SEL_LVS3B,
-	MSM_RPM_SEL_MVS,
+	MSM_RPM_8660_SEL_SMPS0B,
+	MSM_RPM_8660_SEL_SMPS1B,
+	MSM_RPM_8660_SEL_SMPS2B,
+	MSM_RPM_8660_SEL_SMPS3B,
+	MSM_RPM_8660_SEL_SMPS4B,
+	MSM_RPM_8660_SEL_LDO0B,
+	MSM_RPM_8660_SEL_LDO1B,
+	MSM_RPM_8660_SEL_LDO2B,
+	MSM_RPM_8660_SEL_LDO3B,
+	MSM_RPM_8660_SEL_LDO4B,
+	MSM_RPM_8660_SEL_LDO5B,
+	MSM_RPM_8660_SEL_LDO6B,
+	MSM_RPM_8660_SEL_LVS0B,
+	MSM_RPM_8660_SEL_LVS1B,
+	MSM_RPM_8660_SEL_LVS2B,
+	MSM_RPM_8660_SEL_LVS3B,
+	MSM_RPM_8660_SEL_MVS,
 
-	MSM_RPM_SEL_SMPS0,
-	MSM_RPM_SEL_SMPS1,
-	MSM_RPM_SEL_SMPS2,
-	MSM_RPM_SEL_SMPS3,
-	MSM_RPM_SEL_SMPS4,
+	MSM_RPM_8660_SEL_SMPS0,
+	MSM_RPM_8660_SEL_SMPS1,
+	MSM_RPM_8660_SEL_SMPS2,
+	MSM_RPM_8660_SEL_SMPS3,
+	MSM_RPM_8660_SEL_SMPS4,
 
-	MSM_RPM_SEL_LDO0,
-	MSM_RPM_SEL_LDO1,
-	MSM_RPM_SEL_LDO2,
-	MSM_RPM_SEL_LDO3,
-	MSM_RPM_SEL_LDO4,
-	MSM_RPM_SEL_LDO5,
-	MSM_RPM_SEL_LDO6,
-	MSM_RPM_SEL_LDO7,
-	MSM_RPM_SEL_LDO8,
-	MSM_RPM_SEL_LDO9,
-	MSM_RPM_SEL_LDO10,
-	MSM_RPM_SEL_LDO11,
-	MSM_RPM_SEL_LDO12,
-	MSM_RPM_SEL_LDO13,
-	MSM_RPM_SEL_LDO14,
-	MSM_RPM_SEL_LDO15,
-	MSM_RPM_SEL_LDO16,
-	MSM_RPM_SEL_LDO17,
-	MSM_RPM_SEL_LDO18,
-	MSM_RPM_SEL_LDO19,
-	MSM_RPM_SEL_LDO20,
-	MSM_RPM_SEL_LDO21,
-	MSM_RPM_SEL_LDO22,
-	MSM_RPM_SEL_LDO23,
-	MSM_RPM_SEL_LDO24,
-	MSM_RPM_SEL_LDO25,
-	MSM_RPM_SEL_LVS0,
-	MSM_RPM_SEL_LVS1,
-	MSM_RPM_SEL_NCP,
+	MSM_RPM_8660_SEL_LDO0,
+	MSM_RPM_8660_SEL_LDO1,
+	MSM_RPM_8660_SEL_LDO2,
+	MSM_RPM_8660_SEL_LDO3,
+	MSM_RPM_8660_SEL_LDO4,
+	MSM_RPM_8660_SEL_LDO5,
+	MSM_RPM_8660_SEL_LDO6,
+	MSM_RPM_8660_SEL_LDO7,
+	MSM_RPM_8660_SEL_LDO8,
+	MSM_RPM_8660_SEL_LDO9,
+	MSM_RPM_8660_SEL_LDO10,
+	MSM_RPM_8660_SEL_LDO11,
+	MSM_RPM_8660_SEL_LDO12,
+	MSM_RPM_8660_SEL_LDO13,
+	MSM_RPM_8660_SEL_LDO14,
+	MSM_RPM_8660_SEL_LDO15,
+	MSM_RPM_8660_SEL_LDO16,
+	MSM_RPM_8660_SEL_LDO17,
+	MSM_RPM_8660_SEL_LDO18,
+	MSM_RPM_8660_SEL_LDO19,
+	MSM_RPM_8660_SEL_LDO20,
+	MSM_RPM_8660_SEL_LDO21,
+	MSM_RPM_8660_SEL_LDO22,
+	MSM_RPM_8660_SEL_LDO23,
+	MSM_RPM_8660_SEL_LDO24,
+	MSM_RPM_8660_SEL_LDO25,
+	MSM_RPM_8660_SEL_LVS0,
+	MSM_RPM_8660_SEL_LVS1,
+	MSM_RPM_8660_SEL_NCP,
 
-	MSM_RPM_SEL_CXO_BUFFERS,
+	MSM_RPM_8660_SEL_CXO_BUFFERS,
 
-	MSM_RPM_SEL_LAST = MSM_RPM_SEL_CXO_BUFFERS,
+	MSM_RPM_8660_SEL_LAST = MSM_RPM_8660_SEL_CXO_BUFFERS,
 };
 
 
 enum {
-	MSM_RPM_ID_NOTIFICATION_CONFIGURED_0,
-	MSM_RPM_ID_NOTIFICATION_CONFIGURED_7 =
-		MSM_RPM_ID_NOTIFICATION_CONFIGURED_0 + 7,
+	MSM_RPM_8660_ID_NOTIFICATION_CONFIGURED_0,
+	MSM_RPM_8660_ID_NOTIFICATION_CONFIGURED_7 =
+		MSM_RPM_8660_ID_NOTIFICATION_CONFIGURED_0 + 7,
 
-	MSM_RPM_ID_NOTIFICATION_REGISTERED_0,
-	MSM_RPM_ID_NOTIFICATION_REGISTERED_7 =
-		MSM_RPM_ID_NOTIFICATION_REGISTERED_0 + 7,
+	MSM_RPM_8660_ID_NOTIFICATION_REGISTERED_0,
+	MSM_RPM_8660_ID_NOTIFICATION_REGISTERED_7 =
+		MSM_RPM_8660_ID_NOTIFICATION_REGISTERED_0 + 7,
 
-	MSM_RPM_ID_INVALIDATE_0,
-	MSM_RPM_ID_INVALIDATE_7 = MSM_RPM_ID_INVALIDATE_0 + 7,
+	MSM_RPM_8660_ID_INVALIDATE_0,
+	MSM_RPM_8660_ID_INVALIDATE_7 =
+		MSM_RPM_8660_ID_INVALIDATE_0 + 7,
 
-	MSM_RPM_ID_TRIGGER_TIMED_TO,
-	MSM_RPM_ID_TRIGGER_TIMED_SCLK_COUNT,
+	MSM_RPM_8660_ID_TRIGGER_TIMED_TO,
+	MSM_RPM_8660_ID_TRIGGER_TIMED_SCLK_COUNT,
 
-	MSM_RPM_ID_TRIGGER_SET_FROM,
-	MSM_RPM_ID_TRIGGER_SET_TO,
-	MSM_RPM_ID_TRIGGER_SET_TRIGGER,
+	MSM_RPM_8660_ID_TRIGGER_SET_FROM,
+	MSM_RPM_8660_ID_TRIGGER_SET_TO,
+	MSM_RPM_8660_ID_TRIGGER_SET_TRIGGER,
 
-	MSM_RPM_ID_TRIGGER_CLEAR_FROM,
-	MSM_RPM_ID_TRIGGER_CLEAR_TO,
-	MSM_RPM_ID_TRIGGER_CLEAR_TRIGGER,
+	MSM_RPM_8660_ID_TRIGGER_CLEAR_FROM,
+	MSM_RPM_8660_ID_TRIGGER_CLEAR_TO,
+	MSM_RPM_8660_ID_TRIGGER_CLEAR_TRIGGER,
 
-	MSM_RPM_ID_CXO_CLK,
-	MSM_RPM_ID_PXO_CLK,
-	MSM_RPM_ID_PLL_4,
-	MSM_RPM_ID_APPS_FABRIC_CLK,
-	MSM_RPM_ID_SYSTEM_FABRIC_CLK,
-	MSM_RPM_ID_MM_FABRIC_CLK,
-	MSM_RPM_ID_DAYTONA_FABRIC_CLK,
-	MSM_RPM_ID_SFPB_CLK,
-	MSM_RPM_ID_CFPB_CLK,
-	MSM_RPM_ID_MMFPB_CLK,
-	MSM_RPM_ID_SMI_CLK,
-	MSM_RPM_ID_EBI1_CLK,
+	MSM_RPM_8660_ID_CXO_CLK,
+	MSM_RPM_8660_ID_PXO_CLK,
+	MSM_RPM_8660_ID_PLL_4,
+	MSM_RPM_8660_ID_APPS_FABRIC_CLK,
+	MSM_RPM_8660_ID_SYSTEM_FABRIC_CLK,
+	MSM_RPM_8660_ID_MM_FABRIC_CLK,
+	MSM_RPM_8660_ID_DAYTONA_FABRIC_CLK,
+	MSM_RPM_8660_ID_SFPB_CLK,
+	MSM_RPM_8660_ID_CFPB_CLK,
+	MSM_RPM_8660_ID_MMFPB_CLK,
+	MSM_RPM_8660_ID_SMI_CLK,
+	MSM_RPM_8660_ID_EBI1_CLK,
 
-	MSM_RPM_ID_APPS_L2_CACHE_CTL,
+	MSM_RPM_8660_ID_APPS_L2_CACHE_CTL,
 
-	MSM_RPM_ID_APPS_FABRIC_HALT_0,
-	MSM_RPM_ID_APPS_FABRIC_HALT_1,
-	MSM_RPM_ID_APPS_FABRIC_CLOCK_MODE_0,
-	MSM_RPM_ID_APPS_FABRIC_CLOCK_MODE_1,
-	MSM_RPM_ID_APPS_FABRIC_CLOCK_MODE_2,
-	MSM_RPM_ID_APPS_FABRIC_RESERVED_A,
-	MSM_RPM_ID_APPS_FABRIC_ARB_0,
-	MSM_RPM_ID_APPS_FABRIC_ARB_5 = MSM_RPM_ID_APPS_FABRIC_ARB_0 + 5,
-	MSM_RPM_ID_APPS_FABRIC_RESERVED_B_0,
-	MSM_RPM_ID_APPS_FABRIC_RESERVED_B_5 =
-		MSM_RPM_ID_APPS_FABRIC_RESERVED_B_0 + 5,
+	MSM_RPM_8660_ID_APPS_FABRIC_HALT_0,
+	MSM_RPM_8660_ID_APPS_FABRIC_HALT_1,
+	MSM_RPM_8660_ID_APPS_FABRIC_CLOCK_MODE_0,
+	MSM_RPM_8660_ID_APPS_FABRIC_CLOCK_MODE_1,
+	MSM_RPM_8660_ID_APPS_FABRIC_CLOCK_MODE_2,
+	MSM_RPM_8660_ID_APPS_FABRIC_RESERVED_A,
+	MSM_RPM_8660_ID_APPS_FABRIC_ARB_0,
+	MSM_RPM_8660_ID_APPS_FABRIC_ARB_5 =
+		MSM_RPM_8660_ID_APPS_FABRIC_ARB_0 + 5,
+	MSM_RPM_8660_ID_APPS_FABRIC_RESERVED_B_0,
+	MSM_RPM_8660_ID_APPS_FABRIC_RESERVED_B_5 =
+		MSM_RPM_8660_ID_APPS_FABRIC_RESERVED_B_0 + 5,
 
-	MSM_RPM_ID_SYSTEM_FABRIC_HALT_0,
-	MSM_RPM_ID_SYSTEM_FABRIC_HALT_1,
-	MSM_RPM_ID_SYSTEM_FABRIC_CLOCK_MODE_0,
-	MSM_RPM_ID_SYSTEM_FABRIC_CLOCK_MODE_1,
-	MSM_RPM_ID_SYSTEM_FABRIC_CLOCK_MODE_2,
-	MSM_RPM_ID_SYSTEM_FABRIC_RESERVED_A,
-	MSM_RPM_ID_SYSTEM_FABRIC_ARB_0,
-	MSM_RPM_ID_SYSTEM_FABRIC_ARB_21 = MSM_RPM_ID_SYSTEM_FABRIC_ARB_0 + 21,
-	MSM_RPM_ID_SYSTEM_FABRIC_RESERVED_B_0,
-	MSM_RPM_ID_SYSTEM_FABRIC_RESERVED_B_13 =
-		MSM_RPM_ID_SYSTEM_FABRIC_RESERVED_B_0 + 13,
+	MSM_RPM_8660_ID_SYSTEM_FABRIC_HALT_0,
+	MSM_RPM_8660_ID_SYSTEM_FABRIC_HALT_1,
+	MSM_RPM_8660_ID_SYSTEM_FABRIC_CLOCK_MODE_0,
+	MSM_RPM_8660_ID_SYSTEM_FABRIC_CLOCK_MODE_1,
+	MSM_RPM_8660_ID_SYSTEM_FABRIC_CLOCK_MODE_2,
+	MSM_RPM_8660_ID_SYSTEM_FABRIC_RESERVED_A,
+	MSM_RPM_8660_ID_SYSTEM_FABRIC_ARB_0,
+	MSM_RPM_8660_ID_SYSTEM_FABRIC_ARB_21 =
+		MSM_RPM_8660_ID_SYSTEM_FABRIC_ARB_0 + 21,
+	MSM_RPM_8660_ID_SYSTEM_FABRIC_RESERVED_B_0,
+	MSM_RPM_8660_ID_SYSTEM_FABRIC_RESERVED_B_13 =
+		MSM_RPM_8660_ID_SYSTEM_FABRIC_RESERVED_B_0 + 13,
 
-	MSM_RPM_ID_MM_FABRIC_HALT_0,
-	MSM_RPM_ID_MM_FABRIC_HALT_1,
-	MSM_RPM_ID_MM_FABRIC_CLOCK_MODE_0,
-	MSM_RPM_ID_MM_FABRIC_CLOCK_MODE_1,
-	MSM_RPM_ID_MM_FABRIC_CLOCK_MODE_2,
-	MSM_RPM_ID_MM_FABRIC_RESERVED_A,
-	MSM_RPM_ID_MM_FABRIC_ARB_0,
-	MSM_RPM_ID_MM_FABRIC_ARB_22 = MSM_RPM_ID_MM_FABRIC_ARB_0 + 22,
+	MSM_RPM_8660_ID_MM_FABRIC_HALT_0,
+	MSM_RPM_8660_ID_MM_FABRIC_HALT_1,
+	MSM_RPM_8660_ID_MM_FABRIC_CLOCK_MODE_0,
+	MSM_RPM_8660_ID_MM_FABRIC_CLOCK_MODE_1,
+	MSM_RPM_8660_ID_MM_FABRIC_CLOCK_MODE_2,
+	MSM_RPM_8660_ID_MM_FABRIC_RESERVED_A,
+	MSM_RPM_8660_ID_MM_FABRIC_ARB_0,
+	MSM_RPM_8660_ID_MM_FABRIC_ARB_22 =
+		MSM_RPM_8660_ID_MM_FABRIC_ARB_0 + 22,
 
 	/* pmic 8901 */
-	MSM_RPM_ID_SMPS0B_0,
-	MSM_RPM_ID_SMPS0B_1,
-	MSM_RPM_ID_SMPS1B_0,
-	MSM_RPM_ID_SMPS1B_1,
-	MSM_RPM_ID_SMPS2B_0,
-	MSM_RPM_ID_SMPS2B_1,
-	MSM_RPM_ID_SMPS3B_0,
-	MSM_RPM_ID_SMPS3B_1,
-	MSM_RPM_ID_SMPS4B_0,
-	MSM_RPM_ID_SMPS4B_1,
-	MSM_RPM_ID_LDO0B_0,
-	MSM_RPM_ID_LDO0B_1,
-	MSM_RPM_ID_LDO1B_0,
-	MSM_RPM_ID_LDO1B_1,
-	MSM_RPM_ID_LDO2B_0,
-	MSM_RPM_ID_LDO2B_1,
-	MSM_RPM_ID_LDO3B_0,
-	MSM_RPM_ID_LDO3B_1,
-	MSM_RPM_ID_LDO4B_0,
-	MSM_RPM_ID_LDO4B_1,
-	MSM_RPM_ID_LDO5B_0,
-	MSM_RPM_ID_LDO5B_1,
-	MSM_RPM_ID_LDO6B_0,
-	MSM_RPM_ID_LDO6B_1,
-	MSM_RPM_ID_LVS0B,
-	MSM_RPM_ID_LVS1B,
-	MSM_RPM_ID_LVS2B,
-	MSM_RPM_ID_LVS3B,
-	MSM_RPM_ID_MVS,
+	MSM_RPM_8660_ID_SMPS0B_0,
+	MSM_RPM_8660_ID_SMPS0B_1,
+	MSM_RPM_8660_ID_SMPS1B_0,
+	MSM_RPM_8660_ID_SMPS1B_1,
+	MSM_RPM_8660_ID_SMPS2B_0,
+	MSM_RPM_8660_ID_SMPS2B_1,
+	MSM_RPM_8660_ID_SMPS3B_0,
+	MSM_RPM_8660_ID_SMPS3B_1,
+	MSM_RPM_8660_ID_SMPS4B_0,
+	MSM_RPM_8660_ID_SMPS4B_1,
+	MSM_RPM_8660_ID_LDO0B_0,
+	MSM_RPM_8660_ID_LDO0B_1,
+	MSM_RPM_8660_ID_LDO1B_0,
+	MSM_RPM_8660_ID_LDO1B_1,
+	MSM_RPM_8660_ID_LDO2B_0,
+	MSM_RPM_8660_ID_LDO2B_1,
+	MSM_RPM_8660_ID_LDO3B_0,
+	MSM_RPM_8660_ID_LDO3B_1,
+	MSM_RPM_8660_ID_LDO4B_0,
+	MSM_RPM_8660_ID_LDO4B_1,
+	MSM_RPM_8660_ID_LDO5B_0,
+	MSM_RPM_8660_ID_LDO5B_1,
+	MSM_RPM_8660_ID_LDO6B_0,
+	MSM_RPM_8660_ID_LDO6B_1,
+	MSM_RPM_8660_ID_LVS0B,
+	MSM_RPM_8660_ID_LVS1B,
+	MSM_RPM_8660_ID_LVS2B,
+	MSM_RPM_8660_ID_LVS3B,
+	MSM_RPM_8660_ID_MVS,
 
 	/* pmic 8058 */
-	MSM_RPM_ID_SMPS0_0,
-	MSM_RPM_ID_SMPS0_1,
-	MSM_RPM_ID_SMPS1_0,
-	MSM_RPM_ID_SMPS1_1,
-	MSM_RPM_ID_SMPS2_0,
-	MSM_RPM_ID_SMPS2_1,
-	MSM_RPM_ID_SMPS3_0,
-	MSM_RPM_ID_SMPS3_1,
-	MSM_RPM_ID_SMPS4_0,
-	MSM_RPM_ID_SMPS4_1,
-	MSM_RPM_ID_LDO0_0,
-	MSM_RPM_ID_LDO0_1,
-	MSM_RPM_ID_LDO1_0,
-	MSM_RPM_ID_LDO1_1,
-	MSM_RPM_ID_LDO2_0,
-	MSM_RPM_ID_LDO2_1,
-	MSM_RPM_ID_LDO3_0,
-	MSM_RPM_ID_LDO3_1,
-	MSM_RPM_ID_LDO4_0,
-	MSM_RPM_ID_LDO4_1,
-	MSM_RPM_ID_LDO5_0,
-	MSM_RPM_ID_LDO5_1,
-	MSM_RPM_ID_LDO6_0,
-	MSM_RPM_ID_LDO6_1,
-	MSM_RPM_ID_LDO7_0,
-	MSM_RPM_ID_LDO7_1,
-	MSM_RPM_ID_LDO8_0,
-	MSM_RPM_ID_LDO8_1,
-	MSM_RPM_ID_LDO9_0,
-	MSM_RPM_ID_LDO9_1,
-	MSM_RPM_ID_LDO10_0,
-	MSM_RPM_ID_LDO10_1,
-	MSM_RPM_ID_LDO11_0,
-	MSM_RPM_ID_LDO11_1,
-	MSM_RPM_ID_LDO12_0,
-	MSM_RPM_ID_LDO12_1,
-	MSM_RPM_ID_LDO13_0,
-	MSM_RPM_ID_LDO13_1,
-	MSM_RPM_ID_LDO14_0,
-	MSM_RPM_ID_LDO14_1,
-	MSM_RPM_ID_LDO15_0,
-	MSM_RPM_ID_LDO15_1,
-	MSM_RPM_ID_LDO16_0,
-	MSM_RPM_ID_LDO16_1,
-	MSM_RPM_ID_LDO17_0,
-	MSM_RPM_ID_LDO17_1,
-	MSM_RPM_ID_LDO18_0,
-	MSM_RPM_ID_LDO18_1,
-	MSM_RPM_ID_LDO19_0,
-	MSM_RPM_ID_LDO19_1,
-	MSM_RPM_ID_LDO20_0,
-	MSM_RPM_ID_LDO20_1,
-	MSM_RPM_ID_LDO21_0,
-	MSM_RPM_ID_LDO21_1,
-	MSM_RPM_ID_LDO22_0,
-	MSM_RPM_ID_LDO22_1,
-	MSM_RPM_ID_LDO23_0,
-	MSM_RPM_ID_LDO23_1,
-	MSM_RPM_ID_LDO24_0,
-	MSM_RPM_ID_LDO24_1,
-	MSM_RPM_ID_LDO25_0,
-	MSM_RPM_ID_LDO25_1,
-	MSM_RPM_ID_LVS0,
-	MSM_RPM_ID_LVS1,
-	MSM_RPM_ID_NCP_0,
-	MSM_RPM_ID_NCP_1,
+	MSM_RPM_8660_ID_SMPS0_0,
+	MSM_RPM_8660_ID_SMPS0_1,
+	MSM_RPM_8660_ID_SMPS1_0,
+	MSM_RPM_8660_ID_SMPS1_1,
+	MSM_RPM_8660_ID_SMPS2_0,
+	MSM_RPM_8660_ID_SMPS2_1,
+	MSM_RPM_8660_ID_SMPS3_0,
+	MSM_RPM_8660_ID_SMPS3_1,
+	MSM_RPM_8660_ID_SMPS4_0,
+	MSM_RPM_8660_ID_SMPS4_1,
+	MSM_RPM_8660_ID_LDO0_0,
+	MSM_RPM_8660_ID_LDO0_1,
+	MSM_RPM_8660_ID_LDO1_0,
+	MSM_RPM_8660_ID_LDO1_1,
+	MSM_RPM_8660_ID_LDO2_0,
+	MSM_RPM_8660_ID_LDO2_1,
+	MSM_RPM_8660_ID_LDO3_0,
+	MSM_RPM_8660_ID_LDO3_1,
+	MSM_RPM_8660_ID_LDO4_0,
+	MSM_RPM_8660_ID_LDO4_1,
+	MSM_RPM_8660_ID_LDO5_0,
+	MSM_RPM_8660_ID_LDO5_1,
+	MSM_RPM_8660_ID_LDO6_0,
+	MSM_RPM_8660_ID_LDO6_1,
+	MSM_RPM_8660_ID_LDO7_0,
+	MSM_RPM_8660_ID_LDO7_1,
+	MSM_RPM_8660_ID_LDO8_0,
+	MSM_RPM_8660_ID_LDO8_1,
+	MSM_RPM_8660_ID_LDO9_0,
+	MSM_RPM_8660_ID_LDO9_1,
+	MSM_RPM_8660_ID_LDO10_0,
+	MSM_RPM_8660_ID_LDO10_1,
+	MSM_RPM_8660_ID_LDO11_0,
+	MSM_RPM_8660_ID_LDO11_1,
+	MSM_RPM_8660_ID_LDO12_0,
+	MSM_RPM_8660_ID_LDO12_1,
+	MSM_RPM_8660_ID_LDO13_0,
+	MSM_RPM_8660_ID_LDO13_1,
+	MSM_RPM_8660_ID_LDO14_0,
+	MSM_RPM_8660_ID_LDO14_1,
+	MSM_RPM_8660_ID_LDO15_0,
+	MSM_RPM_8660_ID_LDO15_1,
+	MSM_RPM_8660_ID_LDO16_0,
+	MSM_RPM_8660_ID_LDO16_1,
+	MSM_RPM_8660_ID_LDO17_0,
+	MSM_RPM_8660_ID_LDO17_1,
+	MSM_RPM_8660_ID_LDO18_0,
+	MSM_RPM_8660_ID_LDO18_1,
+	MSM_RPM_8660_ID_LDO19_0,
+	MSM_RPM_8660_ID_LDO19_1,
+	MSM_RPM_8660_ID_LDO20_0,
+	MSM_RPM_8660_ID_LDO20_1,
+	MSM_RPM_8660_ID_LDO21_0,
+	MSM_RPM_8660_ID_LDO21_1,
+	MSM_RPM_8660_ID_LDO22_0,
+	MSM_RPM_8660_ID_LDO22_1,
+	MSM_RPM_8660_ID_LDO23_0,
+	MSM_RPM_8660_ID_LDO23_1,
+	MSM_RPM_8660_ID_LDO24_0,
+	MSM_RPM_8660_ID_LDO24_1,
+	MSM_RPM_8660_ID_LDO25_0,
+	MSM_RPM_8660_ID_LDO25_1,
+	MSM_RPM_8660_ID_LVS0,
+	MSM_RPM_8660_ID_LVS1,
+	MSM_RPM_8660_ID_NCP_0,
+	MSM_RPM_8660_ID_NCP_1,
 
-	MSM_RPM_ID_CXO_BUFFERS,
+	MSM_RPM_8660_ID_CXO_BUFFERS,
 
-	MSM_RPM_ID_LAST = MSM_RPM_ID_CXO_BUFFERS
-};
-
-/* RPM resources RPM_ID aliases */
-enum {
-	MSM_RPMRS_ID_RPM_CTL = MSM_RPM_ID_TRIGGER_SET_FROM,
-	MSM_RPMRS_ID_PXO_CLK = MSM_RPM_ID_PXO_CLK,
-	MSM_RPMRS_ID_APPS_L2_CACHE_CTL = MSM_RPM_ID_APPS_L2_CACHE_CTL,
-	MSM_RPMRS_ID_VDD_MEM_0 = MSM_RPM_ID_SMPS0_0,
-	MSM_RPMRS_ID_VDD_MEM_1 = MSM_RPM_ID_SMPS0_1,
-	MSM_RPMRS_ID_VDD_DIG_0 = MSM_RPM_ID_SMPS1_0,
-	MSM_RPMRS_ID_VDD_DIG_1 = MSM_RPM_ID_SMPS1_1
-};
-
-/* VDD values are in millivolts */
-#define MSM_RPMRS_VDD_MASK  0xfff
-enum {
-	MSM_RPMRS_VDD_MEM_RET_LOW = 500,
-	MSM_RPMRS_VDD_MEM_RET_HIGH = 750,
-	MSM_RPMRS_VDD_MEM_ACTIVE = 1000,
-	MSM_RPMRS_VDD_MEM_MAX = 1250,
+	MSM_RPM_8660_ID_LAST = MSM_RPM_8660_ID_CXO_BUFFERS
 };
 
 enum {
-	MSM_RPMRS_VDD_DIG_RET_LOW = 500,
-	MSM_RPMRS_VDD_DIG_RET_HIGH = 750,
-	MSM_RPMRS_VDD_DIG_ACTIVE = 1000,
-	MSM_RPMRS_VDD_DIG_MAX = 1250,
-};
+	MSM_RPM_8660_STATUS_ID_VERSION_MAJOR,
+	MSM_RPM_8660_STATUS_ID_VERSION_MINOR,
+	MSM_RPM_8660_STATUS_ID_VERSION_BUILD,
+	MSM_RPM_8660_STATUS_ID_SUPPORTED_RESOURCES_0,
+	MSM_RPM_8660_STATUS_ID_SUPPORTED_RESOURCES_1,
+	MSM_RPM_8660_STATUS_ID_SUPPORTED_RESOURCES_2,
+	MSM_RPM_8660_STATUS_ID_RESERVED_0,
+	MSM_RPM_8660_STATUS_ID_RESERVED_4 =
+		MSM_RPM_8660_STATUS_ID_RESERVED_0 + 4,
+	MSM_RPM_8660_STATUS_ID_SEQUENCE,
 
-enum {
-	MSM_RPM_STATUS_ID_VERSION_MAJOR,
-	MSM_RPM_STATUS_ID_VERSION_MINOR,
-	MSM_RPM_STATUS_ID_VERSION_BUILD,
-	MSM_RPM_STATUS_ID_SUPPORTED_RESOURCES_0,
-	MSM_RPM_STATUS_ID_SUPPORTED_RESOURCES_1,
-	MSM_RPM_STATUS_ID_SUPPORTED_RESOURCES_2,
-	MSM_RPM_STATUS_ID_RESERVED_0,
-	MSM_RPM_STATUS_ID_RESERVED_4 = MSM_RPM_STATUS_ID_RESERVED_0 + 4,
-	MSM_RPM_STATUS_ID_SEQUENCE,
+	MSM_RPM_8660_STATUS_ID_CXO_CLK,
+	MSM_RPM_8660_STATUS_ID_PXO_CLK,
+	MSM_RPM_8660_STATUS_ID_PLL_4,
+	MSM_RPM_8660_STATUS_ID_APPS_FABRIC_CLK,
+	MSM_RPM_8660_STATUS_ID_SYSTEM_FABRIC_CLK,
+	MSM_RPM_8660_STATUS_ID_MM_FABRIC_CLK,
+	MSM_RPM_8660_STATUS_ID_DAYTONA_FABRIC_CLK,
+	MSM_RPM_8660_STATUS_ID_SFPB_CLK,
+	MSM_RPM_8660_STATUS_ID_CFPB_CLK,
+	MSM_RPM_8660_STATUS_ID_MMFPB_CLK,
+	MSM_RPM_8660_STATUS_ID_SMI_CLK,
+	MSM_RPM_8660_STATUS_ID_EBI1_CLK,
 
-	MSM_RPM_STATUS_ID_CXO_CLK,
-	MSM_RPM_STATUS_ID_PXO_CLK,
-	MSM_RPM_STATUS_ID_PLL_4,
-	MSM_RPM_STATUS_ID_APPS_FABRIC_CLK,
-	MSM_RPM_STATUS_ID_SYSTEM_FABRIC_CLK,
-	MSM_RPM_STATUS_ID_MM_FABRIC_CLK,
-	MSM_RPM_STATUS_ID_DAYTONA_FABRIC_CLK,
-	MSM_RPM_STATUS_ID_SFPB_CLK,
-	MSM_RPM_STATUS_ID_CFPB_CLK,
-	MSM_RPM_STATUS_ID_MMFPB_CLK,
-	MSM_RPM_STATUS_ID_SMI_CLK,
-	MSM_RPM_STATUS_ID_EBI1_CLK,
+	MSM_RPM_8660_STATUS_ID_APPS_L2_CACHE_CTL,
 
-	MSM_RPM_STATUS_ID_APPS_L2_CACHE_CTL,
+	MSM_RPM_8660_STATUS_ID_APPS_FABRIC_HALT,
+	MSM_RPM_8660_STATUS_ID_APPS_FABRIC_CLOCK_MODE,
+	MSM_RPM_8660_STATUS_ID_APPS_FABRIC_RESERVED,
+	MSM_RPM_8660_STATUS_ID_APPS_FABRIC_ARB,
 
-	MSM_RPM_STATUS_ID_APPS_FABRIC_HALT,
-	MSM_RPM_STATUS_ID_APPS_FABRIC_CLOCK_MODE,
-	MSM_RPM_STATUS_ID_APPS_FABRIC_RESERVED,
-	MSM_RPM_STATUS_ID_APPS_FABRIC_ARB,
+	MSM_RPM_8660_STATUS_ID_SYSTEM_FABRIC_HALT,
+	MSM_RPM_8660_STATUS_ID_SYSTEM_FABRIC_CLOCK_MODE,
+	MSM_RPM_8660_STATUS_ID_SYSTEM_FABRIC_RESERVED,
+	MSM_RPM_8660_STATUS_ID_SYSTEM_FABRIC_ARB,
 
-	MSM_RPM_STATUS_ID_SYSTEM_FABRIC_HALT,
-	MSM_RPM_STATUS_ID_SYSTEM_FABRIC_CLOCK_MODE,
-	MSM_RPM_STATUS_ID_SYSTEM_FABRIC_RESERVED,
-	MSM_RPM_STATUS_ID_SYSTEM_FABRIC_ARB,
-
-	MSM_RPM_STATUS_ID_MM_FABRIC_HALT,
-	MSM_RPM_STATUS_ID_MM_FABRIC_CLOCK_MODE,
-	MSM_RPM_STATUS_ID_MM_FABRIC_RESERVED,
-	MSM_RPM_STATUS_ID_MM_FABRIC_ARB,
+	MSM_RPM_8660_STATUS_ID_MM_FABRIC_HALT,
+	MSM_RPM_8660_STATUS_ID_MM_FABRIC_CLOCK_MODE,
+	MSM_RPM_8660_STATUS_ID_MM_FABRIC_RESERVED,
+	MSM_RPM_8660_STATUS_ID_MM_FABRIC_ARB,
 
 	/* pmic 8901 */
-	MSM_RPM_STATUS_ID_SMPS0B_0,
-	MSM_RPM_STATUS_ID_SMPS0B_1,
-	MSM_RPM_STATUS_ID_SMPS1B_0,
-	MSM_RPM_STATUS_ID_SMPS1B_1,
-	MSM_RPM_STATUS_ID_SMPS2B_0,
-	MSM_RPM_STATUS_ID_SMPS2B_1,
-	MSM_RPM_STATUS_ID_SMPS3B_0,
-	MSM_RPM_STATUS_ID_SMPS3B_1,
-	MSM_RPM_STATUS_ID_SMPS4B_0,
-	MSM_RPM_STATUS_ID_SMPS4B_1,
-	MSM_RPM_STATUS_ID_LDO0B_0,
-	MSM_RPM_STATUS_ID_LDO0B_1,
-	MSM_RPM_STATUS_ID_LDO1B_0,
-	MSM_RPM_STATUS_ID_LDO1B_1,
-	MSM_RPM_STATUS_ID_LDO2B_0,
-	MSM_RPM_STATUS_ID_LDO2B_1,
-	MSM_RPM_STATUS_ID_LDO3B_0,
-	MSM_RPM_STATUS_ID_LDO3B_1,
-	MSM_RPM_STATUS_ID_LDO4B_0,
-	MSM_RPM_STATUS_ID_LDO4B_1,
-	MSM_RPM_STATUS_ID_LDO5B_0,
-	MSM_RPM_STATUS_ID_LDO5B_1,
-	MSM_RPM_STATUS_ID_LDO6B_0,
-	MSM_RPM_STATUS_ID_LDO6B_1,
-	MSM_RPM_STATUS_ID_LVS0B,
-	MSM_RPM_STATUS_ID_LVS1B,
-	MSM_RPM_STATUS_ID_LVS2B,
-	MSM_RPM_STATUS_ID_LVS3B,
-	MSM_RPM_STATUS_ID_MVS,
+	MSM_RPM_8660_STATUS_ID_SMPS0B_0,
+	MSM_RPM_8660_STATUS_ID_SMPS0B_1,
+	MSM_RPM_8660_STATUS_ID_SMPS1B_0,
+	MSM_RPM_8660_STATUS_ID_SMPS1B_1,
+	MSM_RPM_8660_STATUS_ID_SMPS2B_0,
+	MSM_RPM_8660_STATUS_ID_SMPS2B_1,
+	MSM_RPM_8660_STATUS_ID_SMPS3B_0,
+	MSM_RPM_8660_STATUS_ID_SMPS3B_1,
+	MSM_RPM_8660_STATUS_ID_SMPS4B_0,
+	MSM_RPM_8660_STATUS_ID_SMPS4B_1,
+	MSM_RPM_8660_STATUS_ID_LDO0B_0,
+	MSM_RPM_8660_STATUS_ID_LDO0B_1,
+	MSM_RPM_8660_STATUS_ID_LDO1B_0,
+	MSM_RPM_8660_STATUS_ID_LDO1B_1,
+	MSM_RPM_8660_STATUS_ID_LDO2B_0,
+	MSM_RPM_8660_STATUS_ID_LDO2B_1,
+	MSM_RPM_8660_STATUS_ID_LDO3B_0,
+	MSM_RPM_8660_STATUS_ID_LDO3B_1,
+	MSM_RPM_8660_STATUS_ID_LDO4B_0,
+	MSM_RPM_8660_STATUS_ID_LDO4B_1,
+	MSM_RPM_8660_STATUS_ID_LDO5B_0,
+	MSM_RPM_8660_STATUS_ID_LDO5B_1,
+	MSM_RPM_8660_STATUS_ID_LDO6B_0,
+	MSM_RPM_8660_STATUS_ID_LDO6B_1,
+	MSM_RPM_8660_STATUS_ID_LVS0B,
+	MSM_RPM_8660_STATUS_ID_LVS1B,
+	MSM_RPM_8660_STATUS_ID_LVS2B,
+	MSM_RPM_8660_STATUS_ID_LVS3B,
+	MSM_RPM_8660_STATUS_ID_MVS,
 
 	/* pmic 8058 */
-	MSM_RPM_STATUS_ID_SMPS0_0,
-	MSM_RPM_STATUS_ID_SMPS0_1,
-	MSM_RPM_STATUS_ID_SMPS1_0,
-	MSM_RPM_STATUS_ID_SMPS1_1,
-	MSM_RPM_STATUS_ID_SMPS2_0,
-	MSM_RPM_STATUS_ID_SMPS2_1,
-	MSM_RPM_STATUS_ID_SMPS3_0,
-	MSM_RPM_STATUS_ID_SMPS3_1,
-	MSM_RPM_STATUS_ID_SMPS4_0,
-	MSM_RPM_STATUS_ID_SMPS4_1,
-	MSM_RPM_STATUS_ID_LDO0_0,
-	MSM_RPM_STATUS_ID_LDO0_1,
-	MSM_RPM_STATUS_ID_LDO1_0,
-	MSM_RPM_STATUS_ID_LDO1_1,
-	MSM_RPM_STATUS_ID_LDO2_0,
-	MSM_RPM_STATUS_ID_LDO2_1,
-	MSM_RPM_STATUS_ID_LDO3_0,
-	MSM_RPM_STATUS_ID_LDO3_1,
-	MSM_RPM_STATUS_ID_LDO4_0,
-	MSM_RPM_STATUS_ID_LDO4_1,
-	MSM_RPM_STATUS_ID_LDO5_0,
-	MSM_RPM_STATUS_ID_LDO5_1,
-	MSM_RPM_STATUS_ID_LDO6_0,
-	MSM_RPM_STATUS_ID_LDO6_1,
-	MSM_RPM_STATUS_ID_LDO7_0,
-	MSM_RPM_STATUS_ID_LDO7_1,
-	MSM_RPM_STATUS_ID_LDO8_0,
-	MSM_RPM_STATUS_ID_LDO8_1,
-	MSM_RPM_STATUS_ID_LDO9_0,
-	MSM_RPM_STATUS_ID_LDO9_1,
-	MSM_RPM_STATUS_ID_LDO10_0,
-	MSM_RPM_STATUS_ID_LDO10_1,
-	MSM_RPM_STATUS_ID_LDO11_0,
-	MSM_RPM_STATUS_ID_LDO11_1,
-	MSM_RPM_STATUS_ID_LDO12_0,
-	MSM_RPM_STATUS_ID_LDO12_1,
-	MSM_RPM_STATUS_ID_LDO13_0,
-	MSM_RPM_STATUS_ID_LDO13_1,
-	MSM_RPM_STATUS_ID_LDO14_0,
-	MSM_RPM_STATUS_ID_LDO14_1,
-	MSM_RPM_STATUS_ID_LDO15_0,
-	MSM_RPM_STATUS_ID_LDO15_1,
-	MSM_RPM_STATUS_ID_LDO16_0,
-	MSM_RPM_STATUS_ID_LDO16_1,
-	MSM_RPM_STATUS_ID_LDO17_0,
-	MSM_RPM_STATUS_ID_LDO17_1,
-	MSM_RPM_STATUS_ID_LDO18_0,
-	MSM_RPM_STATUS_ID_LDO18_1,
-	MSM_RPM_STATUS_ID_LDO19_0,
-	MSM_RPM_STATUS_ID_LDO19_1,
-	MSM_RPM_STATUS_ID_LDO20_0,
-	MSM_RPM_STATUS_ID_LDO20_1,
-	MSM_RPM_STATUS_ID_LDO21_0,
-	MSM_RPM_STATUS_ID_LDO21_1,
-	MSM_RPM_STATUS_ID_LDO22_0,
-	MSM_RPM_STATUS_ID_LDO22_1,
-	MSM_RPM_STATUS_ID_LDO23_0,
-	MSM_RPM_STATUS_ID_LDO23_1,
-	MSM_RPM_STATUS_ID_LDO24_0,
-	MSM_RPM_STATUS_ID_LDO24_1,
-	MSM_RPM_STATUS_ID_LDO25_0,
-	MSM_RPM_STATUS_ID_LDO25_1,
-	MSM_RPM_STATUS_ID_LVS0,
-	MSM_RPM_STATUS_ID_LVS1,
-	MSM_RPM_STATUS_ID_NCP_0,
-	MSM_RPM_STATUS_ID_NCP_1,
+	MSM_RPM_8660_STATUS_ID_SMPS0_0,
+	MSM_RPM_8660_STATUS_ID_SMPS0_1,
+	MSM_RPM_8660_STATUS_ID_SMPS1_0,
+	MSM_RPM_8660_STATUS_ID_SMPS1_1,
+	MSM_RPM_8660_STATUS_ID_SMPS2_0,
+	MSM_RPM_8660_STATUS_ID_SMPS2_1,
+	MSM_RPM_8660_STATUS_ID_SMPS3_0,
+	MSM_RPM_8660_STATUS_ID_SMPS3_1,
+	MSM_RPM_8660_STATUS_ID_SMPS4_0,
+	MSM_RPM_8660_STATUS_ID_SMPS4_1,
+	MSM_RPM_8660_STATUS_ID_LDO0_0,
+	MSM_RPM_8660_STATUS_ID_LDO0_1,
+	MSM_RPM_8660_STATUS_ID_LDO1_0,
+	MSM_RPM_8660_STATUS_ID_LDO1_1,
+	MSM_RPM_8660_STATUS_ID_LDO2_0,
+	MSM_RPM_8660_STATUS_ID_LDO2_1,
+	MSM_RPM_8660_STATUS_ID_LDO3_0,
+	MSM_RPM_8660_STATUS_ID_LDO3_1,
+	MSM_RPM_8660_STATUS_ID_LDO4_0,
+	MSM_RPM_8660_STATUS_ID_LDO4_1,
+	MSM_RPM_8660_STATUS_ID_LDO5_0,
+	MSM_RPM_8660_STATUS_ID_LDO5_1,
+	MSM_RPM_8660_STATUS_ID_LDO6_0,
+	MSM_RPM_8660_STATUS_ID_LDO6_1,
+	MSM_RPM_8660_STATUS_ID_LDO7_0,
+	MSM_RPM_8660_STATUS_ID_LDO7_1,
+	MSM_RPM_8660_STATUS_ID_LDO8_0,
+	MSM_RPM_8660_STATUS_ID_LDO8_1,
+	MSM_RPM_8660_STATUS_ID_LDO9_0,
+	MSM_RPM_8660_STATUS_ID_LDO9_1,
+	MSM_RPM_8660_STATUS_ID_LDO10_0,
+	MSM_RPM_8660_STATUS_ID_LDO10_1,
+	MSM_RPM_8660_STATUS_ID_LDO11_0,
+	MSM_RPM_8660_STATUS_ID_LDO11_1,
+	MSM_RPM_8660_STATUS_ID_LDO12_0,
+	MSM_RPM_8660_STATUS_ID_LDO12_1,
+	MSM_RPM_8660_STATUS_ID_LDO13_0,
+	MSM_RPM_8660_STATUS_ID_LDO13_1,
+	MSM_RPM_8660_STATUS_ID_LDO14_0,
+	MSM_RPM_8660_STATUS_ID_LDO14_1,
+	MSM_RPM_8660_STATUS_ID_LDO15_0,
+	MSM_RPM_8660_STATUS_ID_LDO15_1,
+	MSM_RPM_8660_STATUS_ID_LDO16_0,
+	MSM_RPM_8660_STATUS_ID_LDO16_1,
+	MSM_RPM_8660_STATUS_ID_LDO17_0,
+	MSM_RPM_8660_STATUS_ID_LDO17_1,
+	MSM_RPM_8660_STATUS_ID_LDO18_0,
+	MSM_RPM_8660_STATUS_ID_LDO18_1,
+	MSM_RPM_8660_STATUS_ID_LDO19_0,
+	MSM_RPM_8660_STATUS_ID_LDO19_1,
+	MSM_RPM_8660_STATUS_ID_LDO20_0,
+	MSM_RPM_8660_STATUS_ID_LDO20_1,
+	MSM_RPM_8660_STATUS_ID_LDO21_0,
+	MSM_RPM_8660_STATUS_ID_LDO21_1,
+	MSM_RPM_8660_STATUS_ID_LDO22_0,
+	MSM_RPM_8660_STATUS_ID_LDO22_1,
+	MSM_RPM_8660_STATUS_ID_LDO23_0,
+	MSM_RPM_8660_STATUS_ID_LDO23_1,
+	MSM_RPM_8660_STATUS_ID_LDO24_0,
+	MSM_RPM_8660_STATUS_ID_LDO24_1,
+	MSM_RPM_8660_STATUS_ID_LDO25_0,
+	MSM_RPM_8660_STATUS_ID_LDO25_1,
+	MSM_RPM_8660_STATUS_ID_LVS0,
+	MSM_RPM_8660_STATUS_ID_LVS1,
+	MSM_RPM_8660_STATUS_ID_NCP_0,
+	MSM_RPM_8660_STATUS_ID_NCP_1,
 
-	MSM_RPM_STATUS_ID_CXO_BUFFERS,
+	MSM_RPM_8660_STATUS_ID_CXO_BUFFERS,
 
-	MSM_RPM_STATUS_ID_LAST = MSM_RPM_STATUS_ID_CXO_BUFFERS
+	MSM_RPM_8660_STATUS_ID_LAST =
+		MSM_RPM_8660_STATUS_ID_CXO_BUFFERS
 };
 
 #endif /* __ARCH_ARM_MACH_MSM_RPM_8660_H */
diff --git a/arch/arm/mach-msm/include/mach/rpm-8930.h b/arch/arm/mach-msm/include/mach/rpm-8930.h
new file mode 100644
index 0000000..04218b2
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/rpm-8930.h
@@ -0,0 +1,355 @@
+/* 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 __ARCH_ARM_MACH_MSM_RPM_8930_H
+#define __ARCH_ARM_MACH_MSM_RPM_8930_H
+
+/* RPM control message RAM enums */
+enum {
+	MSM_RPM_8930_CTRL_VERSION_MAJOR,
+	MSM_RPM_8930_CTRL_VERSION_MINOR,
+	MSM_RPM_8930_CTRL_VERSION_BUILD,
+
+	MSM_RPM_8930_CTRL_REQ_CTX_0,
+	MSM_RPM_8930_CTRL_REQ_CTX_7 = MSM_RPM_8930_CTRL_REQ_CTX_0 + 7,
+	MSM_RPM_8930_CTRL_REQ_SEL_0,
+	MSM_RPM_8930_CTRL_REQ_SEL_3 = MSM_RPM_8930_CTRL_REQ_SEL_0 + 3,
+	MSM_RPM_8930_CTRL_ACK_CTX_0,
+	MSM_RPM_8930_CTRL_ACK_CTX_7 = MSM_RPM_8930_CTRL_ACK_CTX_0 + 7,
+	MSM_RPM_8930_CTRL_ACK_SEL_0,
+	MSM_RPM_8930_CTRL_ACK_SEL_7 = MSM_RPM_8930_CTRL_ACK_SEL_0 + 7,
+};
+
+/* RPM resource select enums defined for RPM core
+   NOT IN SEQUENTIAL ORDER */
+enum {
+	MSM_RPM_8930_SEL_NOTIFICATION				= 0,
+	MSM_RPM_8930_SEL_INVALIDATE				= 1,
+	MSM_RPM_8930_SEL_TRIGGER_TIMED_0			= 2,
+	MSM_RPM_8930_SEL_RPM_CTL				= 3,
+	MSM_RPM_8930_SEL_CXO_CLK				= 5,
+	MSM_RPM_8930_SEL_PXO_CLK				= 6,
+	MSM_RPM_8930_SEL_QDSS_CLK				= 7,
+	MSM_RPM_8930_SEL_APPS_FABRIC_CLK			= 8,
+	MSM_RPM_8930_SEL_SYSTEM_FABRIC_CLK			= 9,
+	MSM_RPM_8930_SEL_MM_FABRIC_CLK				= 10,
+	MSM_RPM_8930_SEL_DAYTONA_FABRIC_CLK			= 11,
+	MSM_RPM_8930_SEL_SFPB_CLK				= 12,
+	MSM_RPM_8930_SEL_CFPB_CLK				= 13,
+	MSM_RPM_8930_SEL_MMFPB_CLK				= 14,
+	MSM_RPM_8930_SEL_EBI1_CLK				= 16,
+	MSM_RPM_8930_SEL_APPS_FABRIC_CFG_HALT			= 18,
+	MSM_RPM_8930_SEL_APPS_FABRIC_CFG_CLKMOD			= 19,
+	MSM_RPM_8930_SEL_APPS_FABRIC_CFG_IOCTL			= 20,
+	MSM_RPM_8930_SEL_APPS_FABRIC_ARB			= 21,
+	MSM_RPM_8930_SEL_SYS_FABRIC_CFG_HALT			= 22,
+	MSM_RPM_8930_SEL_SYS_FABRIC_CFG_CLKMOD			= 23,
+	MSM_RPM_8930_SEL_SYS_FABRIC_CFG_IOCTL			= 24,
+	MSM_RPM_8930_SEL_SYSTEM_FABRIC_ARB			= 25,
+	MSM_RPM_8930_SEL_MMSS_FABRIC_CFG_HALT			= 26,
+	MSM_RPM_8930_SEL_MMSS_FABRIC_CFG_CLKMOD			= 27,
+	MSM_RPM_8930_SEL_MMSS_FABRIC_CFG_IOCTL			= 28,
+	MSM_RPM_8930_SEL_MM_FABRIC_ARB				= 29,
+	MSM_RPM_8930_SEL_PM8038_S1				= 30,
+	MSM_RPM_8930_SEL_PM8038_S2				= 31,
+	MSM_RPM_8930_SEL_PM8038_S3				= 32,
+	MSM_RPM_8930_SEL_PM8038_S4				= 33,
+	MSM_RPM_8930_SEL_PM8038_S5				= 34,
+	MSM_RPM_8930_SEL_PM8038_S6				= 35,
+	MSM_RPM_8930_SEL_PM8038_L1				= 36,
+	MSM_RPM_8930_SEL_PM8038_L2				= 37,
+	MSM_RPM_8930_SEL_PM8038_L3				= 38,
+	MSM_RPM_8930_SEL_PM8038_L4				= 39,
+	MSM_RPM_8930_SEL_PM8038_L5				= 40,
+	MSM_RPM_8930_SEL_PM8038_L6				= 41,
+	MSM_RPM_8930_SEL_PM8038_L7				= 42,
+	MSM_RPM_8930_SEL_PM8038_L8				= 43,
+	MSM_RPM_8930_SEL_PM8038_L9				= 44,
+	MSM_RPM_8930_SEL_PM8038_L10				= 45,
+	MSM_RPM_8930_SEL_PM8038_L11				= 46,
+	MSM_RPM_8930_SEL_PM8038_L12				= 47,
+	MSM_RPM_8930_SEL_PM8038_L13				= 48,
+	MSM_RPM_8930_SEL_PM8038_L14				= 49,
+	MSM_RPM_8930_SEL_PM8038_L15				= 50,
+	MSM_RPM_8930_SEL_PM8038_L16				= 51,
+	MSM_RPM_8930_SEL_PM8038_L17				= 52,
+	MSM_RPM_8930_SEL_PM8038_L18				= 53,
+	MSM_RPM_8930_SEL_PM8038_L19				= 54,
+	MSM_RPM_8930_SEL_PM8038_L20				= 55,
+	MSM_RPM_8930_SEL_PM8038_L21				= 56,
+	MSM_RPM_8930_SEL_PM8038_L22				= 57,
+	MSM_RPM_8930_SEL_PM8038_L23				= 58,
+	MSM_RPM_8930_SEL_PM8038_L24				= 59,
+	MSM_RPM_8930_SEL_PM8038_L25				= 60,
+	MSM_RPM_8930_SEL_PM8038_L26				= 61,
+	MSM_RPM_8930_SEL_PM8038_L27				= 62,
+	MSM_RPM_8930_SEL_PM8038_CLK1				= 63,
+	MSM_RPM_8930_SEL_PM8038_CLK2				= 64,
+	MSM_RPM_8930_SEL_PM8038_LVS1				= 65,
+	MSM_RPM_8930_SEL_PM8038_LVS2				= 66,
+	MSM_RPM_8930_SEL_NCP					= 80,
+	MSM_RPM_8930_SEL_CXO_BUFFERS				= 81,
+	MSM_RPM_8930_SEL_USB_OTG_SWITCH				= 82,
+	MSM_RPM_8930_SEL_HDMI_SWITCH				= 83,
+	MSM_RPM_8930_SEL_LAST = MSM_RPM_8930_SEL_HDMI_SWITCH,
+};
+
+/* RPM resource (4 byte) word ID enum */
+enum {
+	MSM_RPM_8930_ID_NOTIFICATION_CONFIGURED_0		= 0,
+	MSM_RPM_8930_ID_NOTIFICATION_CONFIGURED_3 =
+		MSM_RPM_8930_ID_NOTIFICATION_CONFIGURED_0 + 3,
+
+	MSM_RPM_8930_ID_NOTIFICATION_REGISTERED_0		= 4,
+	MSM_RPM_8930_ID_NOTIFICATION_REGISTERED_3 =
+		MSM_RPM_8930_ID_NOTIFICATION_REGISTERED_0 + 3,
+
+	MSM_RPM_8930_ID_INVALIDATE_0				= 8,
+	MSM_RPM_8930_ID_INVALIDATE_7 =
+		MSM_RPM_8930_ID_INVALIDATE_0 + 7,
+
+	MSM_RPM_8930_ID_TRIGGER_TIMED_TO_			= 16,
+	MSM_RPM_8930_ID_TRIGGER_TIMED_SCLK_COUNT		= 17,
+	MSM_RPM_8930_ID_RPM_CTL					= 18,
+	MSM_RPM_8930_ID_RESERVED_0				= 19,
+	MSM_RPM_8930_ID_RESERVED_5 =
+		MSM_RPM_8930_ID_RESERVED_0 + 5,
+	MSM_RPM_8930_ID_CXO_CLK					= 25,
+	MSM_RPM_8930_ID_PXO_CLK					= 26,
+	MSM_RPM_8930_ID_APPS_FABRIC_CLK				= 27,
+	MSM_RPM_8930_ID_SYSTEM_FABRIC_CLK			= 28,
+	MSM_RPM_8930_ID_MM_FABRIC_CLK				= 29,
+	MSM_RPM_8930_ID_DAYTONA_FABRIC_CLK			= 30,
+	MSM_RPM_8930_ID_SFPB_CLK				= 31,
+	MSM_RPM_8930_ID_CFPB_CLK				= 32,
+	MSM_RPM_8930_ID_MMFPB_CLK				= 33,
+	MSM_RPM_8930_ID_EBI1_CLK				= 34,
+	MSM_RPM_8930_ID_APPS_FABRIC_CFG_HALT_0			= 35,
+	MSM_RPM_8930_ID_APPS_FABRIC_CFG_HALT_1			= 36,
+	MSM_RPM_8930_ID_APPS_FABRIC_CFG_CLKMOD_0		= 37,
+	MSM_RPM_8930_ID_APPS_FABRIC_CFG_CLKMOD_1		= 38,
+	MSM_RPM_8930_ID_APPS_FABRIC_CFG_CLKMOD_2		= 39,
+	MSM_RPM_8930_ID_APPS_FABRIC_CFG_IOCTL			= 40,
+	MSM_RPM_8930_ID_APPS_FABRIC_ARB_0			= 41,
+	MSM_RPM_8930_ID_APPS_FABRIC_ARB_11 =
+		MSM_RPM_8930_ID_APPS_FABRIC_ARB_0 + 11,
+	MSM_RPM_8930_ID_SYS_FABRIC_CFG_HALT_0			= 53,
+	MSM_RPM_8930_ID_SYS_FABRIC_CFG_HALT_1			= 54,
+	MSM_RPM_8930_ID_SYS_FABRIC_CFG_CLKMOD_0			= 55,
+	MSM_RPM_8930_ID_SYS_FABRIC_CFG_CLKMOD_1			= 56,
+	MSM_RPM_8930_ID_SYS_FABRIC_CFG_CLKMOD_2			= 57,
+	MSM_RPM_8930_ID_SYS_FABRIC_CFG_IOCTL			= 58,
+	MSM_RPM_8930_ID_SYSTEM_FABRIC_ARB_0			= 59,
+	MSM_RPM_8930_ID_SYSTEM_FABRIC_ARB_28 =
+		MSM_RPM_8930_ID_SYSTEM_FABRIC_ARB_0 + 28,
+	MSM_RPM_8930_ID_MMSS_FABRIC_CFG_HALT_0			= 88,
+	MSM_RPM_8930_ID_MMSS_FABRIC_CFG_HALT_1			= 89,
+	MSM_RPM_8930_ID_MMSS_FABRIC_CFG_CLKMOD_0		= 90,
+	MSM_RPM_8930_ID_MMSS_FABRIC_CFG_CLKMOD_1		= 91,
+	MSM_RPM_8930_ID_MMSS_FABRIC_CFG_CLKMOD_2		= 92,
+	MSM_RPM_8930_ID_MMSS_FABRIC_CFG_IOCTL			= 93,
+	MSM_RPM_8930_ID_MM_FABRIC_ARB_0				= 94,
+	MSM_RPM_8930_ID_MM_FABRIC_ARB_22 =
+		MSM_RPM_8930_ID_MM_FABRIC_ARB_0	+ 22,
+
+	MSM_RPM_8930_ID_PM8038_S1_0				= 117,
+	MSM_RPM_8930_ID_PM8038_S1_1				= 118,
+	MSM_RPM_8930_ID_PM8038_S2_0				= 119,
+	MSM_RPM_8930_ID_PM8038_S2_1				= 120,
+	MSM_RPM_8930_ID_PM8038_S3_0				= 121,
+	MSM_RPM_8930_ID_PM8038_S3_1				= 122,
+	MSM_RPM_8930_ID_PM8038_S4_0				= 123,
+	MSM_RPM_8930_ID_PM8038_S4_1				= 124,
+	MSM_RPM_8930_ID_PM8038_S5_0				= 125,
+	MSM_RPM_8930_ID_PM8038_S5_1				= 126,
+	MSM_RPM_8930_ID_PM8038_S6_0				= 127,
+	MSM_RPM_8930_ID_PM8038_S6_1				= 128,
+	MSM_RPM_8930_ID_PM8038_L1_0				= 129,
+	MSM_RPM_8930_ID_PM8038_L1_1				= 130,
+	MSM_RPM_8930_ID_PM8038_L2_0				= 131,
+	MSM_RPM_8930_ID_PM8038_L2_1				= 132,
+	MSM_RPM_8930_ID_PM8038_L3_0				= 133,
+	MSM_RPM_8930_ID_PM8038_L3_1				= 134,
+	MSM_RPM_8930_ID_PM8038_L4_0				= 135,
+	MSM_RPM_8930_ID_PM8038_L4_1				= 136,
+	MSM_RPM_8930_ID_PM8038_L5_0				= 137,
+	MSM_RPM_8930_ID_PM8038_L5_1				= 138,
+	MSM_RPM_8930_ID_PM8038_L6_0				= 139,
+	MSM_RPM_8930_ID_PM8038_L6_1				= 140,
+	MSM_RPM_8930_ID_PM8038_L7_0				= 141,
+	MSM_RPM_8930_ID_PM8038_L7_1				= 142,
+	MSM_RPM_8930_ID_PM8038_L8_0				= 143,
+	MSM_RPM_8930_ID_PM8038_L8_1				= 144,
+	MSM_RPM_8930_ID_PM8038_L9_0				= 145,
+	MSM_RPM_8930_ID_PM8038_L9_1				= 146,
+	MSM_RPM_8930_ID_PM8038_L10_0				= 147,
+	MSM_RPM_8930_ID_PM8038_L10_1				= 148,
+	MSM_RPM_8930_ID_PM8038_L11_0				= 149,
+	MSM_RPM_8930_ID_PM8038_L11_1				= 150,
+	MSM_RPM_8930_ID_PM8038_L12_0				= 151,
+	MSM_RPM_8930_ID_PM8038_L12_1				= 152,
+	MSM_RPM_8930_ID_PM8038_L13_0				= 153,
+	MSM_RPM_8930_ID_PM8038_L13_1				= 154,
+	MSM_RPM_8930_ID_PM8038_L14_0				= 155,
+	MSM_RPM_8930_ID_PM8038_L14_1				= 156,
+	MSM_RPM_8930_ID_PM8038_L15_0				= 157,
+	MSM_RPM_8930_ID_PM8038_L15_1				= 158,
+	MSM_RPM_8930_ID_PM8038_L16_0				= 159,
+	MSM_RPM_8930_ID_PM8038_L16_1				= 160,
+	MSM_RPM_8930_ID_PM8038_L17_0				= 161,
+	MSM_RPM_8930_ID_PM8038_L17_1				= 162,
+	MSM_RPM_8930_ID_PM8038_L18_0				= 163,
+	MSM_RPM_8930_ID_PM8038_L18_1				= 164,
+	MSM_RPM_8930_ID_PM8038_L19_0				= 165,
+	MSM_RPM_8930_ID_PM8038_L19_1				= 166,
+	MSM_RPM_8930_ID_PM8038_L20_0				= 167,
+	MSM_RPM_8930_ID_PM8038_L20_1				= 168,
+	MSM_RPM_8930_ID_PM8038_L21_0				= 169,
+	MSM_RPM_8930_ID_PM8038_L21_1				= 170,
+	MSM_RPM_8930_ID_PM8038_L22_0				= 171,
+	MSM_RPM_8930_ID_PM8038_L22_1				= 172,
+	MSM_RPM_8930_ID_PM8038_L23_0				= 173,
+	MSM_RPM_8930_ID_PM8038_L23_1				= 174,
+	MSM_RPM_8930_ID_PM8038_L24_0				= 175,
+	MSM_RPM_8930_ID_PM8038_L24_1				= 176,
+	MSM_RPM_8930_ID_PM8038_L25_0				= 177,
+	MSM_RPM_8930_ID_PM8038_L25_1				= 178,
+	MSM_RPM_8930_ID_PM8038_L26_0				= 179,
+	MSM_RPM_8930_ID_PM8038_L26_1				= 180,
+	MSM_RPM_8930_ID_PM8038_L27_0				= 181,
+	MSM_RPM_8930_ID_PM8038_L27_1				= 182,
+	MSM_RPM_8930_ID_PM8038_CLK1_0				= 183,
+	MSM_RPM_8930_ID_PM8038_CLK1_1				= 184,
+	MSM_RPM_8930_ID_PM8038_CLK2_0				= 185,
+	MSM_RPM_8930_ID_PM8038_CLK2_1				= 186,
+	MSM_RPM_8930_ID_PM8038_LVS1				= 187,
+	MSM_RPM_8930_ID_PM8038_LVS2				= 188,
+	MSM_RPM_8930_ID_NCP_0					= 189,
+	MSM_RPM_8930_ID_NCP_1					= 190,
+	MSM_RPM_8930_ID_CXO_BUFFERS				= 191,
+	MSM_RPM_8930_ID_USB_OTG_SWITCH				= 192,
+	MSM_RPM_8930_ID_HDMI_SWITCH				= 193,
+	MSM_RPM_8930_ID_QDSS_CLK				= 194,
+	MSM_RPM_8930_ID_LAST = MSM_RPM_8930_ID_QDSS_CLK,
+};
+
+/* RPM status ID enum */
+enum {
+	MSM_RPM_8930_STATUS_ID_VERSION_MAJOR			= 0,
+	MSM_RPM_8930_STATUS_ID_VERSION_MINOR			= 1,
+	MSM_RPM_8930_STATUS_ID_VERSION_BUILD			= 2,
+	MSM_RPM_8930_STATUS_ID_SUPPORTED_RESOURCES_0		= 3,
+	MSM_RPM_8930_STATUS_ID_SUPPORTED_RESOURCES_1		= 4,
+	MSM_RPM_8930_STATUS_ID_SUPPORTED_RESOURCES_2		= 5,
+	MSM_RPM_8930_STATUS_ID_RESERVED_SUPPORTED_RESOURCES_0	= 6,
+	MSM_RPM_8930_STATUS_ID_SEQUENCE				= 7,
+	MSM_RPM_8930_STATUS_ID_RPM_CTL				= 8,
+	MSM_RPM_8930_STATUS_ID_CXO_CLK				= 9,
+	MSM_RPM_8930_STATUS_ID_PXO_CLK				= 10,
+	MSM_RPM_8930_STATUS_ID_APPS_FABRIC_CLK			= 11,
+	MSM_RPM_8930_STATUS_ID_SYSTEM_FABRIC_CLK		= 12,
+	MSM_RPM_8930_STATUS_ID_MM_FABRIC_CLK			= 13,
+	MSM_RPM_8930_STATUS_ID_DAYTONA_FABRIC_CLK		= 14,
+	MSM_RPM_8930_STATUS_ID_SFPB_CLK				= 15,
+	MSM_RPM_8930_STATUS_ID_CFPB_CLK				= 16,
+	MSM_RPM_8930_STATUS_ID_MMFPB_CLK			= 17,
+	MSM_RPM_8930_STATUS_ID_EBI1_CLK				= 18,
+	MSM_RPM_8930_STATUS_ID_APPS_FABRIC_CFG_HALT		= 19,
+	MSM_RPM_8930_STATUS_ID_APPS_FABRIC_CFG_CLKMOD		= 20,
+	MSM_RPM_8930_STATUS_ID_APPS_FABRIC_CFG_IOCTL		= 21,
+	MSM_RPM_8930_STATUS_ID_APPS_FABRIC_ARB			= 22,
+	MSM_RPM_8930_STATUS_ID_SYS_FABRIC_CFG_HALT		= 23,
+	MSM_RPM_8930_STATUS_ID_SYS_FABRIC_CFG_CLKMOD		= 24,
+	MSM_RPM_8930_STATUS_ID_SYS_FABRIC_CFG_IOCTL		= 25,
+	MSM_RPM_8930_STATUS_ID_SYSTEM_FABRIC_ARB		= 26,
+	MSM_RPM_8930_STATUS_ID_MMSS_FABRIC_CFG_HALT		= 27,
+	MSM_RPM_8930_STATUS_ID_MMSS_FABRIC_CFG_CLKMOD		= 28,
+	MSM_RPM_8930_STATUS_ID_MMSS_FABRIC_CFG_IOCTL		= 29,
+	MSM_RPM_8930_STATUS_ID_MM_FABRIC_ARB			= 30,
+	MSM_RPM_8930_STATUS_ID_PM8038_S1_0			= 31,
+	MSM_RPM_8930_STATUS_ID_PM8038_S1_1			= 32,
+	MSM_RPM_8930_STATUS_ID_PM8038_S2_0			= 33,
+	MSM_RPM_8930_STATUS_ID_PM8038_S2_1			= 34,
+	MSM_RPM_8930_STATUS_ID_PM8038_S3_0			= 35,
+	MSM_RPM_8930_STATUS_ID_PM8038_S3_1			= 36,
+	MSM_RPM_8930_STATUS_ID_PM8038_S4_0			= 37,
+	MSM_RPM_8930_STATUS_ID_PM8038_S4_1			= 38,
+	MSM_RPM_8930_STATUS_ID_PM8038_L1_0			= 43,
+	MSM_RPM_8930_STATUS_ID_PM8038_L1_1			= 44,
+	MSM_RPM_8930_STATUS_ID_PM8038_L2_0			= 45,
+	MSM_RPM_8930_STATUS_ID_PM8038_L2_1			= 46,
+	MSM_RPM_8930_STATUS_ID_PM8038_L3_0			= 47,
+	MSM_RPM_8930_STATUS_ID_PM8038_L3_1			= 48,
+	MSM_RPM_8930_STATUS_ID_PM8038_L4_0			= 49,
+	MSM_RPM_8930_STATUS_ID_PM8038_L4_1			= 50,
+	MSM_RPM_8930_STATUS_ID_PM8038_L5_0			= 51,
+	MSM_RPM_8930_STATUS_ID_PM8038_L5_1			= 52,
+	MSM_RPM_8930_STATUS_ID_PM8038_L6_0			= 53,
+	MSM_RPM_8930_STATUS_ID_PM8038_L6_1			= 54,
+	MSM_RPM_8930_STATUS_ID_PM8038_L7_0			= 55,
+	MSM_RPM_8930_STATUS_ID_PM8038_L7_1			= 56,
+	MSM_RPM_8930_STATUS_ID_PM8038_L8_0			= 57,
+	MSM_RPM_8930_STATUS_ID_PM8038_L8_1			= 58,
+	MSM_RPM_8930_STATUS_ID_PM8038_L9_0			= 59,
+	MSM_RPM_8930_STATUS_ID_PM8038_L9_1			= 60,
+	MSM_RPM_8930_STATUS_ID_PM8038_L10_0			= 61,
+	MSM_RPM_8930_STATUS_ID_PM8038_L10_1			= 62,
+	MSM_RPM_8930_STATUS_ID_PM8038_L11_0			= 63,
+	MSM_RPM_8930_STATUS_ID_PM8038_L11_1			= 64,
+	MSM_RPM_8930_STATUS_ID_PM8038_L12_0			= 65,
+	MSM_RPM_8930_STATUS_ID_PM8038_L12_1			= 66,
+	MSM_RPM_8930_STATUS_ID_PM8038_L13_0			= 67,
+	MSM_RPM_8930_STATUS_ID_PM8038_L13_1			= 68,
+	MSM_RPM_8930_STATUS_ID_PM8038_L14_0			= 69,
+	MSM_RPM_8930_STATUS_ID_PM8038_L14_1			= 70,
+	MSM_RPM_8930_STATUS_ID_PM8038_L15_0			= 71,
+	MSM_RPM_8930_STATUS_ID_PM8038_L15_1			= 72,
+	MSM_RPM_8930_STATUS_ID_PM8038_L16_0			= 73,
+	MSM_RPM_8930_STATUS_ID_PM8038_L16_1			= 74,
+	MSM_RPM_8930_STATUS_ID_PM8038_L17_0			= 75,
+	MSM_RPM_8930_STATUS_ID_PM8038_L17_1			= 76,
+	MSM_RPM_8930_STATUS_ID_PM8038_L18_0			= 77,
+	MSM_RPM_8930_STATUS_ID_PM8038_L18_1			= 78,
+	MSM_RPM_8930_STATUS_ID_PM8038_L19_0			= 79,
+	MSM_RPM_8930_STATUS_ID_PM8038_L19_1			= 80,
+	MSM_RPM_8930_STATUS_ID_PM8038_L20_0			= 81,
+	MSM_RPM_8930_STATUS_ID_PM8038_L20_1			= 82,
+	MSM_RPM_8930_STATUS_ID_PM8038_L21_0			= 83,
+	MSM_RPM_8930_STATUS_ID_PM8038_L21_1			= 84,
+	MSM_RPM_8930_STATUS_ID_PM8038_L22_0			= 85,
+	MSM_RPM_8930_STATUS_ID_PM8038_L22_1			= 86,
+	MSM_RPM_8930_STATUS_ID_PM8038_L23_0			= 87,
+	MSM_RPM_8930_STATUS_ID_PM8038_L23_1			= 88,
+	MSM_RPM_8930_STATUS_ID_PM8038_L24_0			= 89,
+	MSM_RPM_8930_STATUS_ID_PM8038_L24_1			= 90,
+	MSM_RPM_8930_STATUS_ID_PM8038_L25_0			= 91,
+	MSM_RPM_8930_STATUS_ID_PM8038_L25_1			= 92,
+	MSM_RPM_8930_STATUS_ID_PM8038_L26_0			= 93,
+	MSM_RPM_8930_STATUS_ID_PM8038_L26_1			= 94,
+	MSM_RPM_8930_STATUS_ID_PM8038_L27_0			= 95,
+	MSM_RPM_8930_STATUS_ID_PM8038_L27_1			= 96,
+	MSM_RPM_8930_STATUS_ID_PM8038_CLK1_0			= 97,
+	MSM_RPM_8930_STATUS_ID_PM8038_CLK1_1			= 98,
+	MSM_RPM_8930_STATUS_ID_PM8038_CLK2_0			= 99,
+	MSM_RPM_8930_STATUS_ID_PM8038_CLK2_1			= 100,
+	MSM_RPM_8930_STATUS_ID_PM8038_LVS1			= 101,
+	MSM_RPM_8930_STATUS_ID_PM8038_LVS2			= 102,
+	MSM_RPM_8930_STATUS_ID_NCP_0				= 103,
+	MSM_RPM_8930_STATUS_ID_NCP_1				= 104,
+	MSM_RPM_8930_STATUS_ID_CXO_BUFFERS			= 105,
+	MSM_RPM_8930_STATUS_ID_USB_OTG_SWITCH			= 106,
+	MSM_RPM_8930_STATUS_ID_HDMI_SWITCH			= 107,
+	MSM_RPM_8930_STATUS_ID_QDSS_CLK				= 108,
+	MSM_RPM_8930_STATUS_ID_LAST = MSM_RPM_8930_STATUS_ID_QDSS_CLK,
+};
+
+#endif /* __ARCH_ARM_MACH_MSM_RPM_8930_H */
diff --git a/arch/arm/mach-msm/include/mach/rpm-8960.h b/arch/arm/mach-msm/include/mach/rpm-8960.h
index 41b94ae..6fe8832 100644
--- a/arch/arm/mach-msm/include/mach/rpm-8960.h
+++ b/arch/arm/mach-msm/include/mach/rpm-8960.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,439 +13,404 @@
 #ifndef __ARCH_ARM_MACH_MSM_RPM_8960_H
 #define __ARCH_ARM_MACH_MSM_RPM_8960_H
 
-#define RPM_MAJOR_VER	3
-#define RPM_MINOR_VER	0
-#define RPM_BUILD_VER	0
-
 /* RPM control message RAM enums */
 enum {
-	MSM_RPM_CTRL_VERSION_MAJOR,
-	MSM_RPM_CTRL_VERSION_MINOR,
-	MSM_RPM_CTRL_VERSION_BUILD,
+	MSM_RPM_8960_CTRL_VERSION_MAJOR,
+	MSM_RPM_8960_CTRL_VERSION_MINOR,
+	MSM_RPM_8960_CTRL_VERSION_BUILD,
 
-	MSM_RPM_CTRL_REQ_CTX_0,
-	MSM_RPM_CTRL_REQ_CTX_7 = MSM_RPM_CTRL_REQ_CTX_0 + 7,
-	MSM_RPM_CTRL_REQ_SEL_0,
-	MSM_RPM_CTRL_REQ_SEL_3 = MSM_RPM_CTRL_REQ_SEL_0 + 3,
-	MSM_RPM_CTRL_ACK_CTX_0,
-	MSM_RPM_CTRL_ACK_CTX_7 = MSM_RPM_CTRL_ACK_CTX_0 + 7,
-	MSM_RPM_CTRL_ACK_SEL_0,
-	MSM_RPM_CTRL_ACK_SEL_7 = MSM_RPM_CTRL_ACK_SEL_0 + 7,
+	MSM_RPM_8960_CTRL_REQ_CTX_0,
+	MSM_RPM_8960_CTRL_REQ_CTX_7 = MSM_RPM_8960_CTRL_REQ_CTX_0 + 7,
+	MSM_RPM_8960_CTRL_REQ_SEL_0,
+	MSM_RPM_8960_CTRL_REQ_SEL_3 = MSM_RPM_8960_CTRL_REQ_SEL_0 + 3,
+	MSM_RPM_8960_CTRL_ACK_CTX_0,
+	MSM_RPM_8960_CTRL_ACK_CTX_7 = MSM_RPM_8960_CTRL_ACK_CTX_0 + 7,
+	MSM_RPM_8960_CTRL_ACK_SEL_0,
+	MSM_RPM_8960_CTRL_ACK_SEL_7 = MSM_RPM_8960_CTRL_ACK_SEL_0 + 7,
 };
 
-
 /* RPM resource select enums defined for RPM core
    NOT IN SEQUENTIAL ORDER */
 enum {
-	MSM_RPM_SEL_NOTIFICATION				= 0,
-	MSM_RPM_SEL_INVALIDATE					= 1,
-	MSM_RPM_SEL_TRIGGER_TIMED				= 2,
-	MSM_RPM_SEL_RPM_CTL					= 3,
+	MSM_RPM_8960_SEL_NOTIFICATION					= 0,
+	MSM_RPM_8960_SEL_INVALIDATE					= 1,
+	MSM_RPM_8960_SEL_TRIGGER_TIMED					= 2,
+	MSM_RPM_8960_SEL_RPM_CTL					= 3,
 
-	MSM_RPM_SEL_CXO_CLK					= 5,
-	MSM_RPM_SEL_PXO_CLK					= 6,
-	MSM_RPM_SEL_QDSS_CLK					= 7,
-	MSM_RPM_SEL_APPS_FABRIC_CLK				= 8,
-	MSM_RPM_SEL_SYSTEM_FABRIC_CLK				= 9,
-	MSM_RPM_SEL_MM_FABRIC_CLK				= 10,
-	MSM_RPM_SEL_DAYTONA_FABRIC_CLK				= 11,
-	MSM_RPM_SEL_SFPB_CLK					= 12,
-	MSM_RPM_SEL_CFPB_CLK					= 13,
-	MSM_RPM_SEL_MMFPB_CLK					= 14,
-	MSM_RPM_SEL_EBI1_CLK					= 16,
+	MSM_RPM_8960_SEL_CXO_CLK					= 5,
+	MSM_RPM_8960_SEL_PXO_CLK					= 6,
+	MSM_RPM_8960_SEL_QDSS_CLK					= 7,
+	MSM_RPM_8960_SEL_APPS_FABRIC_CLK				= 8,
+	MSM_RPM_8960_SEL_SYSTEM_FABRIC_CLK				= 9,
+	MSM_RPM_8960_SEL_MM_FABRIC_CLK					= 10,
+	MSM_RPM_8960_SEL_DAYTONA_FABRIC_CLK				= 11,
+	MSM_RPM_8960_SEL_SFPB_CLK					= 12,
+	MSM_RPM_8960_SEL_CFPB_CLK					= 13,
+	MSM_RPM_8960_SEL_MMFPB_CLK					= 14,
+	MSM_RPM_8960_SEL_EBI1_CLK					= 16,
 
-	MSM_RPM_SEL_APPS_FABRIC_CFG_HALT			= 18,
-	MSM_RPM_SEL_APPS_FABRIC_CFG_CLKMOD			= 19,
-	MSM_RPM_SEL_APPS_FABRIC_CFG_IOCTL			= 20,
-	MSM_RPM_SEL_APPS_FABRIC_ARB				= 21,
+	MSM_RPM_8960_SEL_APPS_FABRIC_CFG_HALT				= 18,
+	MSM_RPM_8960_SEL_APPS_FABRIC_CFG_CLKMOD				= 19,
+	MSM_RPM_8960_SEL_APPS_FABRIC_CFG_IOCTL				= 20,
+	MSM_RPM_8960_SEL_APPS_FABRIC_ARB				= 21,
 
-	MSM_RPM_SEL_SYS_FABRIC_CFG_HALT				= 22,
-	MSM_RPM_SEL_SYS_FABRIC_CFG_CLKMOD			= 23,
-	MSM_RPM_SEL_SYS_FABRIC_CFG_IOCTL			= 24,
-	MSM_RPM_SEL_SYSTEM_FABRIC_ARB				= 25,
+	MSM_RPM_8960_SEL_SYS_FABRIC_CFG_HALT				= 22,
+	MSM_RPM_8960_SEL_SYS_FABRIC_CFG_CLKMOD				= 23,
+	MSM_RPM_8960_SEL_SYS_FABRIC_CFG_IOCTL				= 24,
+	MSM_RPM_8960_SEL_SYSTEM_FABRIC_ARB				= 25,
 
-	MSM_RPM_SEL_MMSS_FABRIC_CFG_HALT			= 26,
-	MSM_RPM_SEL_MMSS_FABRIC_CFG_CLKMOD			= 27,
-	MSM_RPM_SEL_MMSS_FABRIC_CFG_IOCTL			= 28,
-	MSM_RPM_SEL_MM_FABRIC_ARB				= 29,
+	MSM_RPM_8960_SEL_MMSS_FABRIC_CFG_HALT				= 26,
+	MSM_RPM_8960_SEL_MMSS_FABRIC_CFG_CLKMOD				= 27,
+	MSM_RPM_8960_SEL_MMSS_FABRIC_CFG_IOCTL				= 28,
+	MSM_RPM_8960_SEL_MM_FABRIC_ARB					= 29,
 
-	MSM_RPM_SEL_PM8921_S1					= 30,
-	MSM_RPM_SEL_PM8921_S2					= 31,
-	MSM_RPM_SEL_PM8921_S3					= 32,
-	MSM_RPM_SEL_PM8921_S4					= 33,
-	MSM_RPM_SEL_PM8921_S5					= 34,
-	MSM_RPM_SEL_PM8921_S6					= 35,
-	MSM_RPM_SEL_PM8921_S7					= 36,
-	MSM_RPM_SEL_PM8921_S8					= 37,
-	MSM_RPM_SEL_PM8921_L1					= 38,
-	MSM_RPM_SEL_PM8921_L2					= 39,
-	MSM_RPM_SEL_PM8921_L3					= 40,
-	MSM_RPM_SEL_PM8921_L4					= 41,
-	MSM_RPM_SEL_PM8921_L5					= 42,
-	MSM_RPM_SEL_PM8921_L6					= 43,
-	MSM_RPM_SEL_PM8921_L7					= 44,
-	MSM_RPM_SEL_PM8921_L8					= 45,
-	MSM_RPM_SEL_PM8921_L9					= 46,
-	MSM_RPM_SEL_PM8921_L10					= 47,
-	MSM_RPM_SEL_PM8921_L11					= 48,
-	MSM_RPM_SEL_PM8921_L12					= 49,
-	MSM_RPM_SEL_PM8921_L13					= 50,
-	MSM_RPM_SEL_PM8921_L14					= 51,
-	MSM_RPM_SEL_PM8921_L15					= 52,
-	MSM_RPM_SEL_PM8921_L16					= 53,
-	MSM_RPM_SEL_PM8921_L17					= 54,
-	MSM_RPM_SEL_PM8921_L18					= 55,
-	MSM_RPM_SEL_PM8921_L19					= 56,
-	MSM_RPM_SEL_PM8921_L20					= 57,
-	MSM_RPM_SEL_PM8921_L21					= 58,
-	MSM_RPM_SEL_PM8921_L22					= 59,
-	MSM_RPM_SEL_PM8921_L23					= 60,
-	MSM_RPM_SEL_PM8921_L24					= 61,
-	MSM_RPM_SEL_PM8921_L25					= 62,
-	MSM_RPM_SEL_PM8921_L26					= 63,
-	MSM_RPM_SEL_PM8921_L27					= 64,
-	MSM_RPM_SEL_PM8921_L28					= 65,
-	MSM_RPM_SEL_PM8921_L29					= 66,
-	MSM_RPM_SEL_PM8921_CLK1					= 67,
-	MSM_RPM_SEL_PM8921_CLK2					= 68,
-	MSM_RPM_SEL_PM8921_LVS1					= 69,
-	MSM_RPM_SEL_PM8921_LVS2					= 70,
-	MSM_RPM_SEL_PM8921_LVS3					= 71,
-	MSM_RPM_SEL_PM8921_LVS4					= 72,
-	MSM_RPM_SEL_PM8921_LVS5					= 73,
-	MSM_RPM_SEL_PM8921_LVS6					= 74,
-	MSM_RPM_SEL_PM8921_LVS7					= 75,
+	MSM_RPM_8960_SEL_PM8921_S1					= 30,
+	MSM_RPM_8960_SEL_PM8921_S2					= 31,
+	MSM_RPM_8960_SEL_PM8921_S3					= 32,
+	MSM_RPM_8960_SEL_PM8921_S4					= 33,
+	MSM_RPM_8960_SEL_PM8921_S5					= 34,
+	MSM_RPM_8960_SEL_PM8921_S6					= 35,
+	MSM_RPM_8960_SEL_PM8921_S7					= 36,
+	MSM_RPM_8960_SEL_PM8921_S8					= 37,
+	MSM_RPM_8960_SEL_PM8921_L1					= 38,
+	MSM_RPM_8960_SEL_PM8921_L2					= 39,
+	MSM_RPM_8960_SEL_PM8921_L3					= 40,
+	MSM_RPM_8960_SEL_PM8921_L4					= 41,
+	MSM_RPM_8960_SEL_PM8921_L5					= 42,
+	MSM_RPM_8960_SEL_PM8921_L6					= 43,
+	MSM_RPM_8960_SEL_PM8921_L7					= 44,
+	MSM_RPM_8960_SEL_PM8921_L8					= 45,
+	MSM_RPM_8960_SEL_PM8921_L9					= 46,
+	MSM_RPM_8960_SEL_PM8921_L10					= 47,
+	MSM_RPM_8960_SEL_PM8921_L11					= 48,
+	MSM_RPM_8960_SEL_PM8921_L12					= 49,
+	MSM_RPM_8960_SEL_PM8921_L13					= 50,
+	MSM_RPM_8960_SEL_PM8921_L14					= 51,
+	MSM_RPM_8960_SEL_PM8921_L15					= 52,
+	MSM_RPM_8960_SEL_PM8921_L16					= 53,
+	MSM_RPM_8960_SEL_PM8921_L17					= 54,
+	MSM_RPM_8960_SEL_PM8921_L18					= 55,
+	MSM_RPM_8960_SEL_PM8921_L19					= 56,
+	MSM_RPM_8960_SEL_PM8921_L20					= 57,
+	MSM_RPM_8960_SEL_PM8921_L21					= 58,
+	MSM_RPM_8960_SEL_PM8921_L22					= 59,
+	MSM_RPM_8960_SEL_PM8921_L23					= 60,
+	MSM_RPM_8960_SEL_PM8921_L24					= 61,
+	MSM_RPM_8960_SEL_PM8921_L25					= 62,
+	MSM_RPM_8960_SEL_PM8921_L26					= 63,
+	MSM_RPM_8960_SEL_PM8921_L27					= 64,
+	MSM_RPM_8960_SEL_PM8921_L28					= 65,
+	MSM_RPM_8960_SEL_PM8921_L29					= 66,
+	MSM_RPM_8960_SEL_PM8921_CLK1					= 67,
+	MSM_RPM_8960_SEL_PM8921_CLK2					= 68,
+	MSM_RPM_8960_SEL_PM8921_LVS1					= 69,
+	MSM_RPM_8960_SEL_PM8921_LVS2					= 70,
+	MSM_RPM_8960_SEL_PM8921_LVS3					= 71,
+	MSM_RPM_8960_SEL_PM8921_LVS4					= 72,
+	MSM_RPM_8960_SEL_PM8921_LVS5					= 73,
+	MSM_RPM_8960_SEL_PM8921_LVS6					= 74,
+	MSM_RPM_8960_SEL_PM8921_LVS7					= 75,
 
-	MSM_RPM_SEL_NCP						= 80,
-	MSM_RPM_SEL_CXO_BUFFERS					= 81,
-	MSM_RPM_SEL_USB_OTG_SWITCH				= 82,
-	MSM_RPM_SEL_HDMI_SWITCH					= 83,
-	MSM_RPM_SEL_DDR_DMM					= 84,
+	MSM_RPM_8960_SEL_NCP						= 80,
+	MSM_RPM_8960_SEL_CXO_BUFFERS					= 81,
+	MSM_RPM_8960_SEL_USB_OTG_SWITCH					= 82,
+	MSM_RPM_8960_SEL_HDMI_SWITCH					= 83,
+	MSM_RPM_8960_SEL_DDR_DMM					= 84,
 
-	MSM_RPM_SEL_LAST = MSM_RPM_SEL_DDR_DMM,
+	MSM_RPM_8960_SEL_LAST = MSM_RPM_8960_SEL_DDR_DMM,
 };
 
 /* RPM resource (4 byte) word ID enum */
 enum {
-	MSM_RPM_ID_NOTIFICATION_CONFIGURED_0			= 0,
-	MSM_RPM_ID_NOTIFICATION_CONFIGURED_3 =
-		MSM_RPM_ID_NOTIFICATION_CONFIGURED_0 + 3,
+	MSM_RPM_8960_ID_NOTIFICATION_CONFIGURED_0			= 0,
+	MSM_RPM_8960_ID_NOTIFICATION_CONFIGURED_3 =
+		MSM_RPM_8960_ID_NOTIFICATION_CONFIGURED_0 + 3,
 
-	MSM_RPM_ID_NOTIFICATION_REGISTERED_0			= 4,
-	MSM_RPM_ID_NOTIFICATION_REGISTERED_3 =
-		MSM_RPM_ID_NOTIFICATION_REGISTERED_0 + 3,
+	MSM_RPM_8960_ID_NOTIFICATION_REGISTERED_0			= 4,
+	MSM_RPM_8960_ID_NOTIFICATION_REGISTERED_3 =
+		MSM_RPM_8960_ID_NOTIFICATION_REGISTERED_0 + 3,
 
-	MSM_RPM_ID_INVALIDATE_0					= 8,
-	MSM_RPM_ID_INVALIDATE_7 =
-		MSM_RPM_ID_INVALIDATE_0 + 7,
+	MSM_RPM_8960_ID_INVALIDATE_0					= 8,
+	MSM_RPM_8960_ID_INVALIDATE_7 =
+		MSM_RPM_8960_ID_INVALIDATE_0 + 7,
 
-	MSM_RPM_ID_TRIGGER_TIMED_TO				= 16,
-	MSM_RPM_ID_TRIGGER_TIMED_SCLK_COUNT			= 17,
+	MSM_RPM_8960_ID_TRIGGER_TIMED_TO				= 16,
+	MSM_RPM_8960_ID_TRIGGER_TIMED_SCLK_COUNT			= 17,
 
-	MSM_RPM_ID_RPM_CTL					= 18,
+	MSM_RPM_8960_ID_RPM_CTL						= 18,
 
 	/* TRIGGER_CLEAR/SET deprecated in these 24 RESERVED bytes */
-	MSM_RPM_ID_RESERVED_0					= 19,
-	MSM_RPM_ID_RESERVED_5 =
-		MSM_RPM_ID_RESERVED_0 + 5,
+	MSM_RPM_8960_ID_RESERVED_0					= 19,
+	MSM_RPM_8960_ID_RESERVED_5 =
+		MSM_RPM_8960_ID_RESERVED_0 + 5,
 
-	MSM_RPM_ID_CXO_CLK					= 25,
-	MSM_RPM_ID_PXO_CLK					= 26,
-	MSM_RPM_ID_APPS_FABRIC_CLK				= 27,
-	MSM_RPM_ID_SYSTEM_FABRIC_CLK				= 28,
-	MSM_RPM_ID_MM_FABRIC_CLK				= 29,
-	MSM_RPM_ID_DAYTONA_FABRIC_CLK				= 30,
-	MSM_RPM_ID_SFPB_CLK					= 31,
-	MSM_RPM_ID_CFPB_CLK					= 32,
-	MSM_RPM_ID_MMFPB_CLK					= 33,
-	MSM_RPM_ID_EBI1_CLK					= 34,
+	MSM_RPM_8960_ID_CXO_CLK						= 25,
+	MSM_RPM_8960_ID_PXO_CLK						= 26,
+	MSM_RPM_8960_ID_APPS_FABRIC_CLK					= 27,
+	MSM_RPM_8960_ID_SYSTEM_FABRIC_CLK				= 28,
+	MSM_RPM_8960_ID_MM_FABRIC_CLK					= 29,
+	MSM_RPM_8960_ID_DAYTONA_FABRIC_CLK				= 30,
+	MSM_RPM_8960_ID_SFPB_CLK					= 31,
+	MSM_RPM_8960_ID_CFPB_CLK					= 32,
+	MSM_RPM_8960_ID_MMFPB_CLK					= 33,
+	MSM_RPM_8960_ID_EBI1_CLK					= 34,
 
-	MSM_RPM_ID_APPS_FABRIC_CFG_HALT_0			= 35,
-	MSM_RPM_ID_APPS_FABRIC_CFG_HALT_1			= 36,
-	MSM_RPM_ID_APPS_FABRIC_CFG_CLKMOD_0			= 37,
-	MSM_RPM_ID_APPS_FABRIC_CFG_CLKMOD_1			= 38,
-	MSM_RPM_ID_APPS_FABRIC_CFG_CLKMOD_2			= 39,
-	MSM_RPM_ID_APPS_FABRIC_CFG_IOCTL			= 40,
-	MSM_RPM_ID_APPS_FABRIC_ARB_0				= 41,
-	MSM_RPM_ID_APPS_FABRIC_ARB_11 =
-		MSM_RPM_ID_APPS_FABRIC_ARB_0 + 11,
+	MSM_RPM_8960_ID_APPS_FABRIC_CFG_HALT_0				= 35,
+	MSM_RPM_8960_ID_APPS_FABRIC_CFG_HALT_1				= 36,
+	MSM_RPM_8960_ID_APPS_FABRIC_CFG_CLKMOD_0			= 37,
+	MSM_RPM_8960_ID_APPS_FABRIC_CFG_CLKMOD_1			= 38,
+	MSM_RPM_8960_ID_APPS_FABRIC_CFG_CLKMOD_2			= 39,
+	MSM_RPM_8960_ID_APPS_FABRIC_CFG_IOCTL				= 40,
+	MSM_RPM_8960_ID_APPS_FABRIC_ARB_0				= 41,
+	MSM_RPM_8960_ID_APPS_FABRIC_ARB_11 =
+		MSM_RPM_8960_ID_APPS_FABRIC_ARB_0 + 11,
 
-	MSM_RPM_ID_SYS_FABRIC_CFG_HALT_0			= 53,
-	MSM_RPM_ID_SYS_FABRIC_CFG_HALT_1			= 54,
-	MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_0			= 55,
-	MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_1			= 56,
-	MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_2			= 57,
-	MSM_RPM_ID_SYS_FABRIC_CFG_IOCTL				= 58,
-	MSM_RPM_ID_SYSTEM_FABRIC_ARB_0				= 59,
-	MSM_RPM_ID_SYSTEM_FABRIC_ARB_28 =
-		MSM_RPM_ID_SYSTEM_FABRIC_ARB_0 + 28,
+	MSM_RPM_8960_ID_SYS_FABRIC_CFG_HALT_0				= 53,
+	MSM_RPM_8960_ID_SYS_FABRIC_CFG_HALT_1				= 54,
+	MSM_RPM_8960_ID_SYS_FABRIC_CFG_CLKMOD_0				= 55,
+	MSM_RPM_8960_ID_SYS_FABRIC_CFG_CLKMOD_1				= 56,
+	MSM_RPM_8960_ID_SYS_FABRIC_CFG_CLKMOD_2				= 57,
+	MSM_RPM_8960_ID_SYS_FABRIC_CFG_IOCTL				= 58,
+	MSM_RPM_8960_ID_SYSTEM_FABRIC_ARB_0				= 59,
+	MSM_RPM_8960_ID_SYSTEM_FABRIC_ARB_28 =
+		MSM_RPM_8960_ID_SYSTEM_FABRIC_ARB_0 + 28,
 
-	MSM_RPM_ID_MMSS_FABRIC_CFG_HALT_0			= 88,
-	MSM_RPM_ID_MMSS_FABRIC_CFG_HALT_1			= 89,
-	MSM_RPM_ID_MMSS_FABRIC_CFG_CLKMOD_0			= 90,
-	MSM_RPM_ID_MMSS_FABRIC_CFG_CLKMOD_1			= 91,
-	MSM_RPM_ID_MMSS_FABRIC_CFG_CLKMOD_2			= 92,
-	MSM_RPM_ID_MMSS_FABRIC_CFG_IOCTL			= 93,
-	MSM_RPM_ID_MM_FABRIC_ARB_0				= 94,
-	MSM_RPM_ID_MM_FABRIC_ARB_22 =
-		MSM_RPM_ID_MM_FABRIC_ARB_0 + 22,
+	MSM_RPM_8960_ID_MMSS_FABRIC_CFG_HALT_0				= 88,
+	MSM_RPM_8960_ID_MMSS_FABRIC_CFG_HALT_1				= 89,
+	MSM_RPM_8960_ID_MMSS_FABRIC_CFG_CLKMOD_0			= 90,
+	MSM_RPM_8960_ID_MMSS_FABRIC_CFG_CLKMOD_1			= 91,
+	MSM_RPM_8960_ID_MMSS_FABRIC_CFG_CLKMOD_2			= 92,
+	MSM_RPM_8960_ID_MMSS_FABRIC_CFG_IOCTL				= 93,
+	MSM_RPM_8960_ID_MM_FABRIC_ARB_0					= 94,
+	MSM_RPM_8960_ID_MM_FABRIC_ARB_22 =
+		MSM_RPM_8960_ID_MM_FABRIC_ARB_0 + 22,
 
-	MSM_RPM_ID_PM8921_S1_0					= 117,
-	MSM_RPM_ID_PM8921_S1_1					= 118,
-	MSM_RPM_ID_PM8921_S2_0					= 119,
-	MSM_RPM_ID_PM8921_S2_1					= 120,
-	MSM_RPM_ID_PM8921_S3_0					= 121,
-	MSM_RPM_ID_PM8921_S3_1					= 122,
-	MSM_RPM_ID_PM8921_S4_0					= 123,
-	MSM_RPM_ID_PM8921_S4_1					= 124,
-	MSM_RPM_ID_PM8921_S5_0					= 125,
-	MSM_RPM_ID_PM8921_S5_1					= 126,
-	MSM_RPM_ID_PM8921_S6_0					= 127,
-	MSM_RPM_ID_PM8921_S6_1					= 128,
-	MSM_RPM_ID_PM8921_S7_0					= 129,
-	MSM_RPM_ID_PM8921_S7_1					= 130,
-	MSM_RPM_ID_PM8921_S8_0					= 131,
-	MSM_RPM_ID_PM8921_S8_1					= 132,
-	MSM_RPM_ID_PM8921_L1_0					= 133,
-	MSM_RPM_ID_PM8921_L1_1					= 134,
-	MSM_RPM_ID_PM8921_L2_0					= 135,
-	MSM_RPM_ID_PM8921_L2_1					= 136,
-	MSM_RPM_ID_PM8921_L3_0					= 137,
-	MSM_RPM_ID_PM8921_L3_1					= 138,
-	MSM_RPM_ID_PM8921_L4_0					= 139,
-	MSM_RPM_ID_PM8921_L4_1					= 140,
-	MSM_RPM_ID_PM8921_L5_0					= 141,
-	MSM_RPM_ID_PM8921_L5_1					= 142,
-	MSM_RPM_ID_PM8921_L6_0					= 143,
-	MSM_RPM_ID_PM8921_L6_1					= 144,
-	MSM_RPM_ID_PM8921_L7_0					= 145,
-	MSM_RPM_ID_PM8921_L7_1					= 146,
-	MSM_RPM_ID_PM8921_L8_0					= 147,
-	MSM_RPM_ID_PM8921_L8_1					= 148,
-	MSM_RPM_ID_PM8921_L9_0					= 149,
-	MSM_RPM_ID_PM8921_L9_1					= 150,
-	MSM_RPM_ID_PM8921_L10_0					= 151,
-	MSM_RPM_ID_PM8921_L10_1					= 152,
-	MSM_RPM_ID_PM8921_L11_0					= 153,
-	MSM_RPM_ID_PM8921_L11_1					= 154,
-	MSM_RPM_ID_PM8921_L12_0					= 155,
-	MSM_RPM_ID_PM8921_L12_1					= 156,
-	MSM_RPM_ID_PM8921_L13_0					= 157,
-	MSM_RPM_ID_PM8921_L13_1					= 158,
-	MSM_RPM_ID_PM8921_L14_0					= 159,
-	MSM_RPM_ID_PM8921_L14_1					= 160,
-	MSM_RPM_ID_PM8921_L15_0					= 161,
-	MSM_RPM_ID_PM8921_L15_1					= 162,
-	MSM_RPM_ID_PM8921_L16_0					= 163,
-	MSM_RPM_ID_PM8921_L16_1					= 164,
-	MSM_RPM_ID_PM8921_L17_0					= 165,
-	MSM_RPM_ID_PM8921_L17_1					= 166,
-	MSM_RPM_ID_PM8921_L18_0					= 167,
-	MSM_RPM_ID_PM8921_L18_1					= 168,
-	MSM_RPM_ID_PM8921_L19_0					= 169,
-	MSM_RPM_ID_PM8921_L19_1					= 170,
-	MSM_RPM_ID_PM8921_L20_0					= 171,
-	MSM_RPM_ID_PM8921_L20_1					= 172,
-	MSM_RPM_ID_PM8921_L21_0					= 173,
-	MSM_RPM_ID_PM8921_L21_1					= 174,
-	MSM_RPM_ID_PM8921_L22_0					= 175,
-	MSM_RPM_ID_PM8921_L22_1					= 176,
-	MSM_RPM_ID_PM8921_L23_0					= 177,
-	MSM_RPM_ID_PM8921_L23_1					= 178,
-	MSM_RPM_ID_PM8921_L24_0					= 179,
-	MSM_RPM_ID_PM8921_L24_1					= 180,
-	MSM_RPM_ID_PM8921_L25_0					= 181,
-	MSM_RPM_ID_PM8921_L25_1					= 182,
-	MSM_RPM_ID_PM8921_L26_0					= 183,
-	MSM_RPM_ID_PM8921_L26_1					= 184,
-	MSM_RPM_ID_PM8921_L27_0					= 185,
-	MSM_RPM_ID_PM8921_L27_1					= 186,
-	MSM_RPM_ID_PM8921_L28_0					= 187,
-	MSM_RPM_ID_PM8921_L28_1					= 188,
-	MSM_RPM_ID_PM8921_L29_0					= 189,
-	MSM_RPM_ID_PM8921_L29_1					= 190,
-	MSM_RPM_ID_PM8921_CLK1_0				= 191,
-	MSM_RPM_ID_PM8921_CLK1_1				= 192,
-	MSM_RPM_ID_PM8921_CLK2_0				= 193,
-	MSM_RPM_ID_PM8921_CLK2_1				= 194,
-	MSM_RPM_ID_PM8921_LVS1					= 195,
-	MSM_RPM_ID_PM8921_LVS2					= 196,
-	MSM_RPM_ID_PM8921_LVS3					= 197,
-	MSM_RPM_ID_PM8921_LVS4					= 198,
-	MSM_RPM_ID_PM8921_LVS5					= 199,
-	MSM_RPM_ID_PM8921_LVS6					= 200,
-	MSM_RPM_ID_PM8921_LVS7					= 201,
-	MSM_RPM_ID_NCP_0					= 202,
-	MSM_RPM_ID_NCP_1					= 203,
-	MSM_RPM_ID_CXO_BUFFERS					= 204,
-	MSM_RPM_ID_USB_OTG_SWITCH				= 205,
-	MSM_RPM_ID_HDMI_SWITCH					= 206,
-	MSM_RPM_ID_DDR_DMM_0					= 207,
-	MSM_RPM_ID_DDR_DMM_1					= 208,
-	MSM_RPM_ID_QDSS_CLK					= 209,
+	MSM_RPM_8960_ID_PM8921_S1_0					= 117,
+	MSM_RPM_8960_ID_PM8921_S1_1					= 118,
+	MSM_RPM_8960_ID_PM8921_S2_0					= 119,
+	MSM_RPM_8960_ID_PM8921_S2_1					= 120,
+	MSM_RPM_8960_ID_PM8921_S3_0					= 121,
+	MSM_RPM_8960_ID_PM8921_S3_1					= 122,
+	MSM_RPM_8960_ID_PM8921_S4_0					= 123,
+	MSM_RPM_8960_ID_PM8921_S4_1					= 124,
+	MSM_RPM_8960_ID_PM8921_S5_0					= 125,
+	MSM_RPM_8960_ID_PM8921_S5_1					= 126,
+	MSM_RPM_8960_ID_PM8921_S6_0					= 127,
+	MSM_RPM_8960_ID_PM8921_S6_1					= 128,
+	MSM_RPM_8960_ID_PM8921_S7_0					= 129,
+	MSM_RPM_8960_ID_PM8921_S7_1					= 130,
+	MSM_RPM_8960_ID_PM8921_S8_0					= 131,
+	MSM_RPM_8960_ID_PM8921_S8_1					= 132,
+	MSM_RPM_8960_ID_PM8921_L1_0					= 133,
+	MSM_RPM_8960_ID_PM8921_L1_1					= 134,
+	MSM_RPM_8960_ID_PM8921_L2_0					= 135,
+	MSM_RPM_8960_ID_PM8921_L2_1					= 136,
+	MSM_RPM_8960_ID_PM8921_L3_0					= 137,
+	MSM_RPM_8960_ID_PM8921_L3_1					= 138,
+	MSM_RPM_8960_ID_PM8921_L4_0					= 139,
+	MSM_RPM_8960_ID_PM8921_L4_1					= 140,
+	MSM_RPM_8960_ID_PM8921_L5_0					= 141,
+	MSM_RPM_8960_ID_PM8921_L5_1					= 142,
+	MSM_RPM_8960_ID_PM8921_L6_0					= 143,
+	MSM_RPM_8960_ID_PM8921_L6_1					= 144,
+	MSM_RPM_8960_ID_PM8921_L7_0					= 145,
+	MSM_RPM_8960_ID_PM8921_L7_1					= 146,
+	MSM_RPM_8960_ID_PM8921_L8_0					= 147,
+	MSM_RPM_8960_ID_PM8921_L8_1					= 148,
+	MSM_RPM_8960_ID_PM8921_L9_0					= 149,
+	MSM_RPM_8960_ID_PM8921_L9_1					= 150,
+	MSM_RPM_8960_ID_PM8921_L10_0					= 151,
+	MSM_RPM_8960_ID_PM8921_L10_1					= 152,
+	MSM_RPM_8960_ID_PM8921_L11_0					= 153,
+	MSM_RPM_8960_ID_PM8921_L11_1					= 154,
+	MSM_RPM_8960_ID_PM8921_L12_0					= 155,
+	MSM_RPM_8960_ID_PM8921_L12_1					= 156,
+	MSM_RPM_8960_ID_PM8921_L13_0					= 157,
+	MSM_RPM_8960_ID_PM8921_L13_1					= 158,
+	MSM_RPM_8960_ID_PM8921_L14_0					= 159,
+	MSM_RPM_8960_ID_PM8921_L14_1					= 160,
+	MSM_RPM_8960_ID_PM8921_L15_0					= 161,
+	MSM_RPM_8960_ID_PM8921_L15_1					= 162,
+	MSM_RPM_8960_ID_PM8921_L16_0					= 163,
+	MSM_RPM_8960_ID_PM8921_L16_1					= 164,
+	MSM_RPM_8960_ID_PM8921_L17_0					= 165,
+	MSM_RPM_8960_ID_PM8921_L17_1					= 166,
+	MSM_RPM_8960_ID_PM8921_L18_0					= 167,
+	MSM_RPM_8960_ID_PM8921_L18_1					= 168,
+	MSM_RPM_8960_ID_PM8921_L19_0					= 169,
+	MSM_RPM_8960_ID_PM8921_L19_1					= 170,
+	MSM_RPM_8960_ID_PM8921_L20_0					= 171,
+	MSM_RPM_8960_ID_PM8921_L20_1					= 172,
+	MSM_RPM_8960_ID_PM8921_L21_0					= 173,
+	MSM_RPM_8960_ID_PM8921_L21_1					= 174,
+	MSM_RPM_8960_ID_PM8921_L22_0					= 175,
+	MSM_RPM_8960_ID_PM8921_L22_1					= 176,
+	MSM_RPM_8960_ID_PM8921_L23_0					= 177,
+	MSM_RPM_8960_ID_PM8921_L23_1					= 178,
+	MSM_RPM_8960_ID_PM8921_L24_0					= 179,
+	MSM_RPM_8960_ID_PM8921_L24_1					= 180,
+	MSM_RPM_8960_ID_PM8921_L25_0					= 181,
+	MSM_RPM_8960_ID_PM8921_L25_1					= 182,
+	MSM_RPM_8960_ID_PM8921_L26_0					= 183,
+	MSM_RPM_8960_ID_PM8921_L26_1					= 184,
+	MSM_RPM_8960_ID_PM8921_L27_0					= 185,
+	MSM_RPM_8960_ID_PM8921_L27_1					= 186,
+	MSM_RPM_8960_ID_PM8921_L28_0					= 187,
+	MSM_RPM_8960_ID_PM8921_L28_1					= 188,
+	MSM_RPM_8960_ID_PM8921_L29_0					= 189,
+	MSM_RPM_8960_ID_PM8921_L29_1					= 190,
+	MSM_RPM_8960_ID_PM8921_CLK1_0					= 191,
+	MSM_RPM_8960_ID_PM8921_CLK1_1					= 192,
+	MSM_RPM_8960_ID_PM8921_CLK2_0					= 193,
+	MSM_RPM_8960_ID_PM8921_CLK2_1					= 194,
+	MSM_RPM_8960_ID_PM8921_LVS1					= 195,
+	MSM_RPM_8960_ID_PM8921_LVS2					= 196,
+	MSM_RPM_8960_ID_PM8921_LVS3					= 197,
+	MSM_RPM_8960_ID_PM8921_LVS4					= 198,
+	MSM_RPM_8960_ID_PM8921_LVS5					= 199,
+	MSM_RPM_8960_ID_PM8921_LVS6					= 200,
+	MSM_RPM_8960_ID_PM8921_LVS7					= 201,
+	MSM_RPM_8960_ID_NCP_0						= 202,
+	MSM_RPM_8960_ID_NCP_1						= 203,
+	MSM_RPM_8960_ID_CXO_BUFFERS					= 204,
+	MSM_RPM_8960_ID_USB_OTG_SWITCH					= 205,
+	MSM_RPM_8960_ID_HDMI_SWITCH					= 206,
+	MSM_RPM_8960_ID_DDR_DMM_0					= 207,
+	MSM_RPM_8960_ID_DDR_DMM_1					= 208,
+	MSM_RPM_8960_ID_QDSS_CLK					= 209,
 
-	MSM_RPM_ID_LAST = MSM_RPM_ID_QDSS_CLK,
-};
-
-/* RPM resources RPM_ID aliases */
-enum {
-	MSM_RPMRS_ID_RPM_CTL = MSM_RPM_ID_RPM_CTL,
-	MSM_RPMRS_ID_PXO_CLK = MSM_RPM_ID_PXO_CLK,
-	MSM_RPMRS_ID_VDD_DIG_0 = MSM_RPM_ID_PM8921_S3_0,
-	MSM_RPMRS_ID_VDD_DIG_1 = MSM_RPM_ID_PM8921_S3_1,
-	MSM_RPMRS_ID_VDD_MEM_0 = MSM_RPM_ID_PM8921_L24_0,
-	MSM_RPMRS_ID_VDD_MEM_1 = MSM_RPM_ID_PM8921_L24_1,
-
-	/* MSM8960 L2 cache power control not via RPM
-	 * MSM_RPM_ID_LAST + 1 indicates invalid */
-	MSM_RPMRS_ID_APPS_L2_CACHE_CTL = MSM_RPM_ID_LAST + 1
-};
-
-/* VDD values are in microvolts */
-#define MSM_RPMRS_VDD_MASK  0x7fffff
-enum {
-	MSM_RPMRS_VDD_MEM_RET_LOW	=  750000,
-	MSM_RPMRS_VDD_MEM_RET_HIGH	=  750000,
-	MSM_RPMRS_VDD_MEM_ACTIVE	= 1050000,
-	MSM_RPMRS_VDD_MEM_MAX		= 1150000,
-};
-
-enum {
-	MSM_RPMRS_VDD_DIG_RET_LOW	=  500000,
-	MSM_RPMRS_VDD_DIG_RET_HIGH	=  750000,
-	MSM_RPMRS_VDD_DIG_ACTIVE	=  950000,
-	MSM_RPMRS_VDD_DIG_MAX		= 1150000,
+	MSM_RPM_8960_ID_LAST = MSM_RPM_8960_ID_QDSS_CLK,
 };
 
 /* RPM status ID enum */
 enum {
-	MSM_RPM_STATUS_ID_VERSION_MAJOR				= 0,
-	MSM_RPM_STATUS_ID_VERSION_MINOR				= 1,
-	MSM_RPM_STATUS_ID_VERSION_BUILD				= 2,
-	MSM_RPM_STATUS_ID_SUPPORTED_RESOURCES_0			= 3,
-	MSM_RPM_STATUS_ID_SUPPORTED_RESOURCES_1			= 4,
-	MSM_RPM_STATUS_ID_SUPPORTED_RESOURCES_2			= 5,
-	MSM_RPM_STATUS_ID_RESERVED_SUPPORTED_RESOURCES_0	= 6,
-	MSM_RPM_STATUS_ID_SEQUENCE				= 7,
-	MSM_RPM_STATUS_ID_RPM_CTL				= 8,
-	MSM_RPM_STATUS_ID_CXO_CLK				= 9,
-	MSM_RPM_STATUS_ID_PXO_CLK				= 10,
-	MSM_RPM_STATUS_ID_APPS_FABRIC_CLK			= 11,
-	MSM_RPM_STATUS_ID_SYSTEM_FABRIC_CLK			= 12,
-	MSM_RPM_STATUS_ID_MM_FABRIC_CLK				= 13,
-	MSM_RPM_STATUS_ID_DAYTONA_FABRIC_CLK			= 14,
-	MSM_RPM_STATUS_ID_SFPB_CLK				= 15,
-	MSM_RPM_STATUS_ID_CFPB_CLK				= 16,
-	MSM_RPM_STATUS_ID_MMFPB_CLK				= 17,
-	MSM_RPM_STATUS_ID_EBI1_CLK				= 18,
-	MSM_RPM_STATUS_ID_APPS_FABRIC_CFG_HALT			= 19,
-	MSM_RPM_STATUS_ID_APPS_FABRIC_CFG_CLKMOD		= 20,
-	MSM_RPM_STATUS_ID_APPS_FABRIC_CFG_IOCTL			= 21,
-	MSM_RPM_STATUS_ID_APPS_FABRIC_ARB			= 22,
-	MSM_RPM_STATUS_ID_SYS_FABRIC_CFG_HALT			= 23,
-	MSM_RPM_STATUS_ID_SYS_FABRIC_CFG_CLKMOD			= 24,
-	MSM_RPM_STATUS_ID_SYS_FABRIC_CFG_IOCTL			= 25,
-	MSM_RPM_STATUS_ID_SYSTEM_FABRIC_ARB			= 26,
-	MSM_RPM_STATUS_ID_MMSS_FABRIC_CFG_HALT			= 27,
-	MSM_RPM_STATUS_ID_MMSS_FABRIC_CFG_CLKMOD		= 28,
-	MSM_RPM_STATUS_ID_MMSS_FABRIC_CFG_IOCTL			= 29,
-	MSM_RPM_STATUS_ID_MM_FABRIC_ARB				= 30,
-	MSM_RPM_STATUS_ID_PM8921_S1_0				= 31,
-	MSM_RPM_STATUS_ID_PM8921_S1_1				= 32,
-	MSM_RPM_STATUS_ID_PM8921_S2_0				= 33,
-	MSM_RPM_STATUS_ID_PM8921_S2_1				= 34,
-	MSM_RPM_STATUS_ID_PM8921_S3_0				= 35,
-	MSM_RPM_STATUS_ID_PM8921_S3_1				= 36,
-	MSM_RPM_STATUS_ID_PM8921_S4_0				= 37,
-	MSM_RPM_STATUS_ID_PM8921_S4_1				= 38,
-	MSM_RPM_STATUS_ID_PM8921_S5_0				= 39,
-	MSM_RPM_STATUS_ID_PM8921_S5_1				= 40,
-	MSM_RPM_STATUS_ID_PM8921_S6_0				= 41,
-	MSM_RPM_STATUS_ID_PM8921_S6_1				= 42,
-	MSM_RPM_STATUS_ID_PM8921_S7_0				= 43,
-	MSM_RPM_STATUS_ID_PM8921_S7_1				= 44,
-	MSM_RPM_STATUS_ID_PM8921_S8_0				= 45,
-	MSM_RPM_STATUS_ID_PM8921_S8_1				= 46,
-	MSM_RPM_STATUS_ID_PM8921_L1_0				= 47,
-	MSM_RPM_STATUS_ID_PM8921_L1_1				= 48,
-	MSM_RPM_STATUS_ID_PM8921_L2_0				= 49,
-	MSM_RPM_STATUS_ID_PM8921_L2_1				= 50,
-	MSM_RPM_STATUS_ID_PM8921_L3_0				= 51,
-	MSM_RPM_STATUS_ID_PM8921_L3_1				= 52,
-	MSM_RPM_STATUS_ID_PM8921_L4_0				= 53,
-	MSM_RPM_STATUS_ID_PM8921_L4_1				= 54,
-	MSM_RPM_STATUS_ID_PM8921_L5_0				= 55,
-	MSM_RPM_STATUS_ID_PM8921_L5_1				= 56,
-	MSM_RPM_STATUS_ID_PM8921_L6_0				= 57,
-	MSM_RPM_STATUS_ID_PM8921_L6_1				= 58,
-	MSM_RPM_STATUS_ID_PM8921_L7_0				= 59,
-	MSM_RPM_STATUS_ID_PM8921_L7_1				= 60,
-	MSM_RPM_STATUS_ID_PM8921_L8_0				= 61,
-	MSM_RPM_STATUS_ID_PM8921_L8_1				= 62,
-	MSM_RPM_STATUS_ID_PM8921_L9_0				= 63,
-	MSM_RPM_STATUS_ID_PM8921_L9_1				= 64,
-	MSM_RPM_STATUS_ID_PM8921_L10_0				= 65,
-	MSM_RPM_STATUS_ID_PM8921_L10_1				= 66,
-	MSM_RPM_STATUS_ID_PM8921_L11_0				= 67,
-	MSM_RPM_STATUS_ID_PM8921_L11_1				= 68,
-	MSM_RPM_STATUS_ID_PM8921_L12_0				= 69,
-	MSM_RPM_STATUS_ID_PM8921_L12_1				= 70,
-	MSM_RPM_STATUS_ID_PM8921_L13_0				= 71,
-	MSM_RPM_STATUS_ID_PM8921_L13_1				= 72,
-	MSM_RPM_STATUS_ID_PM8921_L14_0				= 73,
-	MSM_RPM_STATUS_ID_PM8921_L14_1				= 74,
-	MSM_RPM_STATUS_ID_PM8921_L15_0				= 75,
-	MSM_RPM_STATUS_ID_PM8921_L15_1				= 76,
-	MSM_RPM_STATUS_ID_PM8921_L16_0				= 77,
-	MSM_RPM_STATUS_ID_PM8921_L16_1				= 78,
-	MSM_RPM_STATUS_ID_PM8921_L17_0				= 79,
-	MSM_RPM_STATUS_ID_PM8921_L17_1				= 80,
-	MSM_RPM_STATUS_ID_PM8921_L18_0				= 81,
-	MSM_RPM_STATUS_ID_PM8921_L18_1				= 82,
-	MSM_RPM_STATUS_ID_PM8921_L19_0				= 83,
-	MSM_RPM_STATUS_ID_PM8921_L19_1				= 84,
-	MSM_RPM_STATUS_ID_PM8921_L20_0				= 85,
-	MSM_RPM_STATUS_ID_PM8921_L20_1				= 86,
-	MSM_RPM_STATUS_ID_PM8921_L21_0				= 87,
-	MSM_RPM_STATUS_ID_PM8921_L21_1				= 88,
-	MSM_RPM_STATUS_ID_PM8921_L22_0				= 89,
-	MSM_RPM_STATUS_ID_PM8921_L22_1				= 90,
-	MSM_RPM_STATUS_ID_PM8921_L23_0				= 91,
-	MSM_RPM_STATUS_ID_PM8921_L23_1				= 92,
-	MSM_RPM_STATUS_ID_PM8921_L24_0				= 93,
-	MSM_RPM_STATUS_ID_PM8921_L24_1				= 94,
-	MSM_RPM_STATUS_ID_PM8921_L25_0				= 95,
-	MSM_RPM_STATUS_ID_PM8921_L25_1				= 96,
-	MSM_RPM_STATUS_ID_PM8921_L26_0				= 97,
-	MSM_RPM_STATUS_ID_PM8921_L26_1				= 98,
-	MSM_RPM_STATUS_ID_PM8921_L27_0				= 99,
-	MSM_RPM_STATUS_ID_PM8921_L27_1				= 100,
-	MSM_RPM_STATUS_ID_PM8921_L28_0				= 101,
-	MSM_RPM_STATUS_ID_PM8921_L28_1				= 102,
-	MSM_RPM_STATUS_ID_PM8921_L29_0				= 103,
-	MSM_RPM_STATUS_ID_PM8921_L29_1				= 104,
-	MSM_RPM_STATUS_ID_PM8921_CLK1_0				= 105,
-	MSM_RPM_STATUS_ID_PM8921_CLK1_1				= 106,
-	MSM_RPM_STATUS_ID_PM8921_CLK2_0				= 107,
-	MSM_RPM_STATUS_ID_PM8921_CLK2_1				= 108,
-	MSM_RPM_STATUS_ID_PM8921_LVS1				= 109,
-	MSM_RPM_STATUS_ID_PM8921_LVS2				= 110,
-	MSM_RPM_STATUS_ID_PM8921_LVS3				= 111,
-	MSM_RPM_STATUS_ID_PM8921_LVS4				= 112,
-	MSM_RPM_STATUS_ID_PM8921_LVS5				= 113,
-	MSM_RPM_STATUS_ID_PM8921_LVS6				= 114,
-	MSM_RPM_STATUS_ID_PM8921_LVS7				= 115,
-	MSM_RPM_STATUS_ID_NCP_0					= 116,
-	MSM_RPM_STATUS_ID_NCP_1					= 117,
-	MSM_RPM_STATUS_ID_CXO_BUFFERS				= 118,
-	MSM_RPM_STATUS_ID_USB_OTG_SWITCH			= 119,
-	MSM_RPM_STATUS_ID_HDMI_SWITCH				= 120,
-	MSM_RPM_STATUS_ID_DDR_DMM_0				= 121,
-	MSM_RPM_STATUS_ID_DDR_DMM_1				= 122,
-	MSM_RPM_STATUS_ID_EBI1_CH0_RANGE			= 123,
-	MSM_RPM_STATUS_ID_EBI1_CH1_RANGE			= 124,
+	MSM_RPM_8960_STATUS_ID_VERSION_MAJOR				= 0,
+	MSM_RPM_8960_STATUS_ID_VERSION_MINOR				= 1,
+	MSM_RPM_8960_STATUS_ID_VERSION_BUILD				= 2,
+	MSM_RPM_8960_STATUS_ID_SUPPORTED_RESOURCES_0			= 3,
+	MSM_RPM_8960_STATUS_ID_SUPPORTED_RESOURCES_1			= 4,
+	MSM_RPM_8960_STATUS_ID_SUPPORTED_RESOURCES_2			= 5,
+	MSM_RPM_8960_STATUS_ID_RESERVED_SUPPORTED_RESOURCES_0		= 6,
+	MSM_RPM_8960_STATUS_ID_SEQUENCE					= 7,
+	MSM_RPM_8960_STATUS_ID_RPM_CTL					= 8,
+	MSM_RPM_8960_STATUS_ID_CXO_CLK					= 9,
+	MSM_RPM_8960_STATUS_ID_PXO_CLK					= 10,
+	MSM_RPM_8960_STATUS_ID_APPS_FABRIC_CLK				= 11,
+	MSM_RPM_8960_STATUS_ID_SYSTEM_FABRIC_CLK			= 12,
+	MSM_RPM_8960_STATUS_ID_MM_FABRIC_CLK				= 13,
+	MSM_RPM_8960_STATUS_ID_DAYTONA_FABRIC_CLK			= 14,
+	MSM_RPM_8960_STATUS_ID_SFPB_CLK					= 15,
+	MSM_RPM_8960_STATUS_ID_CFPB_CLK					= 16,
+	MSM_RPM_8960_STATUS_ID_MMFPB_CLK				= 17,
+	MSM_RPM_8960_STATUS_ID_EBI1_CLK					= 18,
+	MSM_RPM_8960_STATUS_ID_APPS_FABRIC_CFG_HALT			= 19,
+	MSM_RPM_8960_STATUS_ID_APPS_FABRIC_CFG_CLKMOD			= 20,
+	MSM_RPM_8960_STATUS_ID_APPS_FABRIC_CFG_IOCTL			= 21,
+	MSM_RPM_8960_STATUS_ID_APPS_FABRIC_ARB				= 22,
+	MSM_RPM_8960_STATUS_ID_SYS_FABRIC_CFG_HALT			= 23,
+	MSM_RPM_8960_STATUS_ID_SYS_FABRIC_CFG_CLKMOD			= 24,
+	MSM_RPM_8960_STATUS_ID_SYS_FABRIC_CFG_IOCTL			= 25,
+	MSM_RPM_8960_STATUS_ID_SYSTEM_FABRIC_ARB			= 26,
+	MSM_RPM_8960_STATUS_ID_MMSS_FABRIC_CFG_HALT			= 27,
+	MSM_RPM_8960_STATUS_ID_MMSS_FABRIC_CFG_CLKMOD			= 28,
+	MSM_RPM_8960_STATUS_ID_MMSS_FABRIC_CFG_IOCTL			= 29,
+	MSM_RPM_8960_STATUS_ID_MM_FABRIC_ARB				= 30,
+	MSM_RPM_8960_STATUS_ID_PM8921_S1_0				= 31,
+	MSM_RPM_8960_STATUS_ID_PM8921_S1_1				= 32,
+	MSM_RPM_8960_STATUS_ID_PM8921_S2_0				= 33,
+	MSM_RPM_8960_STATUS_ID_PM8921_S2_1				= 34,
+	MSM_RPM_8960_STATUS_ID_PM8921_S3_0				= 35,
+	MSM_RPM_8960_STATUS_ID_PM8921_S3_1				= 36,
+	MSM_RPM_8960_STATUS_ID_PM8921_S4_0				= 37,
+	MSM_RPM_8960_STATUS_ID_PM8921_S4_1				= 38,
+	MSM_RPM_8960_STATUS_ID_PM8921_S5_0				= 39,
+	MSM_RPM_8960_STATUS_ID_PM8921_S5_1				= 40,
+	MSM_RPM_8960_STATUS_ID_PM8921_S6_0				= 41,
+	MSM_RPM_8960_STATUS_ID_PM8921_S6_1				= 42,
+	MSM_RPM_8960_STATUS_ID_PM8921_S7_0				= 43,
+	MSM_RPM_8960_STATUS_ID_PM8921_S7_1				= 44,
+	MSM_RPM_8960_STATUS_ID_PM8921_S8_0				= 45,
+	MSM_RPM_8960_STATUS_ID_PM8921_S8_1				= 46,
+	MSM_RPM_8960_STATUS_ID_PM8921_L1_0				= 47,
+	MSM_RPM_8960_STATUS_ID_PM8921_L1_1				= 48,
+	MSM_RPM_8960_STATUS_ID_PM8921_L2_0				= 49,
+	MSM_RPM_8960_STATUS_ID_PM8921_L2_1				= 50,
+	MSM_RPM_8960_STATUS_ID_PM8921_L3_0				= 51,
+	MSM_RPM_8960_STATUS_ID_PM8921_L3_1				= 52,
+	MSM_RPM_8960_STATUS_ID_PM8921_L4_0				= 53,
+	MSM_RPM_8960_STATUS_ID_PM8921_L4_1				= 54,
+	MSM_RPM_8960_STATUS_ID_PM8921_L5_0				= 55,
+	MSM_RPM_8960_STATUS_ID_PM8921_L5_1				= 56,
+	MSM_RPM_8960_STATUS_ID_PM8921_L6_0				= 57,
+	MSM_RPM_8960_STATUS_ID_PM8921_L6_1				= 58,
+	MSM_RPM_8960_STATUS_ID_PM8921_L7_0				= 59,
+	MSM_RPM_8960_STATUS_ID_PM8921_L7_1				= 60,
+	MSM_RPM_8960_STATUS_ID_PM8921_L8_0				= 61,
+	MSM_RPM_8960_STATUS_ID_PM8921_L8_1				= 62,
+	MSM_RPM_8960_STATUS_ID_PM8921_L9_0				= 63,
+	MSM_RPM_8960_STATUS_ID_PM8921_L9_1				= 64,
+	MSM_RPM_8960_STATUS_ID_PM8921_L10_0				= 65,
+	MSM_RPM_8960_STATUS_ID_PM8921_L10_1				= 66,
+	MSM_RPM_8960_STATUS_ID_PM8921_L11_0				= 67,
+	MSM_RPM_8960_STATUS_ID_PM8921_L11_1				= 68,
+	MSM_RPM_8960_STATUS_ID_PM8921_L12_0				= 69,
+	MSM_RPM_8960_STATUS_ID_PM8921_L12_1				= 70,
+	MSM_RPM_8960_STATUS_ID_PM8921_L13_0				= 71,
+	MSM_RPM_8960_STATUS_ID_PM8921_L13_1				= 72,
+	MSM_RPM_8960_STATUS_ID_PM8921_L14_0				= 73,
+	MSM_RPM_8960_STATUS_ID_PM8921_L14_1				= 74,
+	MSM_RPM_8960_STATUS_ID_PM8921_L15_0				= 75,
+	MSM_RPM_8960_STATUS_ID_PM8921_L15_1				= 76,
+	MSM_RPM_8960_STATUS_ID_PM8921_L16_0				= 77,
+	MSM_RPM_8960_STATUS_ID_PM8921_L16_1				= 78,
+	MSM_RPM_8960_STATUS_ID_PM8921_L17_0				= 79,
+	MSM_RPM_8960_STATUS_ID_PM8921_L17_1				= 80,
+	MSM_RPM_8960_STATUS_ID_PM8921_L18_0				= 81,
+	MSM_RPM_8960_STATUS_ID_PM8921_L18_1				= 82,
+	MSM_RPM_8960_STATUS_ID_PM8921_L19_0				= 83,
+	MSM_RPM_8960_STATUS_ID_PM8921_L19_1				= 84,
+	MSM_RPM_8960_STATUS_ID_PM8921_L20_0				= 85,
+	MSM_RPM_8960_STATUS_ID_PM8921_L20_1				= 86,
+	MSM_RPM_8960_STATUS_ID_PM8921_L21_0				= 87,
+	MSM_RPM_8960_STATUS_ID_PM8921_L21_1				= 88,
+	MSM_RPM_8960_STATUS_ID_PM8921_L22_0				= 89,
+	MSM_RPM_8960_STATUS_ID_PM8921_L22_1				= 90,
+	MSM_RPM_8960_STATUS_ID_PM8921_L23_0				= 91,
+	MSM_RPM_8960_STATUS_ID_PM8921_L23_1				= 92,
+	MSM_RPM_8960_STATUS_ID_PM8921_L24_0				= 93,
+	MSM_RPM_8960_STATUS_ID_PM8921_L24_1				= 94,
+	MSM_RPM_8960_STATUS_ID_PM8921_L25_0				= 95,
+	MSM_RPM_8960_STATUS_ID_PM8921_L25_1				= 96,
+	MSM_RPM_8960_STATUS_ID_PM8921_L26_0				= 97,
+	MSM_RPM_8960_STATUS_ID_PM8921_L26_1				= 98,
+	MSM_RPM_8960_STATUS_ID_PM8921_L27_0				= 99,
+	MSM_RPM_8960_STATUS_ID_PM8921_L27_1				= 100,
+	MSM_RPM_8960_STATUS_ID_PM8921_L28_0				= 101,
+	MSM_RPM_8960_STATUS_ID_PM8921_L28_1				= 102,
+	MSM_RPM_8960_STATUS_ID_PM8921_L29_0				= 103,
+	MSM_RPM_8960_STATUS_ID_PM8921_L29_1				= 104,
+	MSM_RPM_8960_STATUS_ID_PM8921_CLK1_0				= 105,
+	MSM_RPM_8960_STATUS_ID_PM8921_CLK1_1				= 106,
+	MSM_RPM_8960_STATUS_ID_PM8921_CLK2_0				= 107,
+	MSM_RPM_8960_STATUS_ID_PM8921_CLK2_1				= 108,
+	MSM_RPM_8960_STATUS_ID_PM8921_LVS1				= 109,
+	MSM_RPM_8960_STATUS_ID_PM8921_LVS2				= 110,
+	MSM_RPM_8960_STATUS_ID_PM8921_LVS3				= 111,
+	MSM_RPM_8960_STATUS_ID_PM8921_LVS4				= 112,
+	MSM_RPM_8960_STATUS_ID_PM8921_LVS5				= 113,
+	MSM_RPM_8960_STATUS_ID_PM8921_LVS6				= 114,
+	MSM_RPM_8960_STATUS_ID_PM8921_LVS7				= 115,
+	MSM_RPM_8960_STATUS_ID_NCP_0					= 116,
+	MSM_RPM_8960_STATUS_ID_NCP_1					= 117,
+	MSM_RPM_8960_STATUS_ID_CXO_BUFFERS				= 118,
+	MSM_RPM_8960_STATUS_ID_USB_OTG_SWITCH				= 119,
+	MSM_RPM_8960_STATUS_ID_HDMI_SWITCH				= 120,
+	MSM_RPM_8960_STATUS_ID_DDR_DMM_0				= 121,
+	MSM_RPM_8960_STATUS_ID_DDR_DMM_1				= 122,
+	MSM_RPM_8960_STATUS_ID_EBI1_CH0_RANGE				= 123,
+	MSM_RPM_8960_STATUS_ID_EBI1_CH1_RANGE				= 124,
 
-	MSM_RPM_STATUS_ID_LAST = MSM_RPM_STATUS_ID_EBI1_CH1_RANGE,
+	MSM_RPM_8960_STATUS_ID_LAST = MSM_RPM_8960_STATUS_ID_EBI1_CH1_RANGE,
 };
 
 #endif /* __ARCH_ARM_MACH_MSM_RPM_8960_H */
diff --git a/arch/arm/mach-msm/include/mach/rpm-9615.h b/arch/arm/mach-msm/include/mach/rpm-9615.h
index 68fd6ce..6ae7bae 100644
--- a/arch/arm/mach-msm/include/mach/rpm-9615.h
+++ b/arch/arm/mach-msm/include/mach/rpm-9615.h
@@ -13,264 +13,226 @@
 #ifndef __ARCH_ARM_MACH_MSM_RPM_9615_H
 #define __ARCH_ARM_MACH_MSM_RPM_9615_H
 
-#define RPM_MAJOR_VER	3
-#define RPM_MINOR_VER	0
-#define RPM_BUILD_VER	0
-
 /* RPM control message RAM enums */
 enum {
-	MSM_RPM_CTRL_VERSION_MAJOR,
-	MSM_RPM_CTRL_VERSION_MINOR,
-	MSM_RPM_CTRL_VERSION_BUILD,
+	MSM_RPM_9615_CTRL_VERSION_MAJOR,
+	MSM_RPM_9615_CTRL_VERSION_MINOR,
+	MSM_RPM_9615_CTRL_VERSION_BUILD,
 
-	MSM_RPM_CTRL_REQ_CTX_0,
-	MSM_RPM_CTRL_REQ_CTX_7 = MSM_RPM_CTRL_REQ_CTX_0 + 7,
-	MSM_RPM_CTRL_REQ_SEL_0,
-	MSM_RPM_CTRL_REQ_SEL_3 = MSM_RPM_CTRL_REQ_SEL_0 + 3,
-	MSM_RPM_CTRL_ACK_CTX_0,
-	MSM_RPM_CTRL_ACK_CTX_7 = MSM_RPM_CTRL_ACK_CTX_0 + 7,
-	MSM_RPM_CTRL_ACK_SEL_0,
-	MSM_RPM_CTRL_ACK_SEL_7 = MSM_RPM_CTRL_ACK_SEL_0 + 7,
+	MSM_RPM_9615_CTRL_REQ_CTX_0,
+	MSM_RPM_9615_CTRL_REQ_CTX_7 = MSM_RPM_9615_CTRL_REQ_CTX_0 + 7,
+	MSM_RPM_9615_CTRL_REQ_SEL_0,
+	MSM_RPM_9615_CTRL_REQ_SEL_3 = MSM_RPM_9615_CTRL_REQ_SEL_0 + 3,
+	MSM_RPM_9615_CTRL_ACK_CTX_0,
+	MSM_RPM_9615_CTRL_ACK_CTX_7 = MSM_RPM_9615_CTRL_ACK_CTX_0 + 7,
+	MSM_RPM_9615_CTRL_ACK_SEL_0,
+	MSM_RPM_9615_CTRL_ACK_SEL_7 = MSM_RPM_9615_CTRL_ACK_SEL_0 + 7,
 };
 
-
-/* RPM resource select enums defined for RPM core
-   NOT IN SEQUENTIAL ORDER */
 enum {
-	MSM_RPM_SEL_NOTIFICATION				= 0,
-	MSM_RPM_SEL_INVALIDATE					= 1,
-	MSM_RPM_SEL_TRIGGER_TIMED				= 2,
-	MSM_RPM_SEL_RPM_CTL					= 3,
+	MSM_RPM_9615_SEL_NOTIFICATION				= 0,
+	MSM_RPM_9615_SEL_INVALIDATE				= 1,
+	MSM_RPM_9615_SEL_TRIGGER_TIMED				= 2,
+	MSM_RPM_9615_SEL_RPM_CTL				= 3,
 
-	MSM_RPM_SEL_CXO_CLK					= 5,
-	MSM_RPM_SEL_SYSTEM_FABRIC_CLK				= 9,
-	MSM_RPM_SEL_DAYTONA_FABRIC_CLK				= 11,
-	MSM_RPM_SEL_SFPB_CLK					= 12,
-	MSM_RPM_SEL_CFPB_CLK					= 13,
-	MSM_RPM_SEL_EBI1_CLK					= 16,
+	MSM_RPM_9615_SEL_CXO_CLK				= 5,
+	MSM_RPM_9615_SEL_SYSTEM_FABRIC_CLK			= 9,
+	MSM_RPM_9615_SEL_DAYTONA_FABRIC_CLK			= 11,
+	MSM_RPM_9615_SEL_SFPB_CLK				= 12,
+	MSM_RPM_9615_SEL_CFPB_CLK				= 13,
+	MSM_RPM_9615_SEL_EBI1_CLK				= 16,
 
-	MSM_RPM_SEL_SYS_FABRIC_CFG_HALT				= 22,
-	MSM_RPM_SEL_SYS_FABRIC_CFG_CLKMOD			= 23,
-	MSM_RPM_SEL_SYS_FABRIC_CFG_IOCTL			= 24,
-	MSM_RPM_SEL_SYSTEM_FABRIC_ARB				= 25,
+	MSM_RPM_9615_SEL_SYS_FABRIC_CFG_HALT			= 22,
+	MSM_RPM_9615_SEL_SYS_FABRIC_CFG_CLKMOD			= 23,
+	MSM_RPM_9615_SEL_SYS_FABRIC_CFG_IOCTL			= 24,
+	MSM_RPM_9615_SEL_SYSTEM_FABRIC_ARB			= 25,
 
-	MSM_RPM_SEL_PM8018_S1					= 30,
-	MSM_RPM_SEL_PM8018_S2					= 31,
-	MSM_RPM_SEL_PM8018_S3					= 32,
-	MSM_RPM_SEL_PM8018_S4					= 33,
-	MSM_RPM_SEL_PM8018_S5					= 34,
-	MSM_RPM_SEL_PM8018_L1					= 35,
-	MSM_RPM_SEL_PM8018_L2					= 36,
-	MSM_RPM_SEL_PM8018_L3					= 37,
-	MSM_RPM_SEL_PM8018_L4					= 38,
-	MSM_RPM_SEL_PM8018_L5					= 39,
-	MSM_RPM_SEL_PM8018_L6					= 40,
-	MSM_RPM_SEL_PM8018_L7					= 41,
-	MSM_RPM_SEL_PM8018_L8					= 42,
-	MSM_RPM_SEL_PM8018_L9					= 43,
-	MSM_RPM_SEL_PM8018_L10					= 44,
-	MSM_RPM_SEL_PM8018_L11					= 45,
-	MSM_RPM_SEL_PM8018_L12					= 46,
-	MSM_RPM_SEL_PM8018_L13					= 47,
-	MSM_RPM_SEL_PM8018_L14					= 48,
-	MSM_RPM_SEL_PM8018_LVS1					= 49,
+	MSM_RPM_9615_SEL_PM8018_S1				= 30,
+	MSM_RPM_9615_SEL_PM8018_S2				= 31,
+	MSM_RPM_9615_SEL_PM8018_S3				= 32,
+	MSM_RPM_9615_SEL_PM8018_S4				= 33,
+	MSM_RPM_9615_SEL_PM8018_S5				= 34,
+	MSM_RPM_9615_SEL_PM8018_L1				= 35,
+	MSM_RPM_9615_SEL_PM8018_L2				= 36,
+	MSM_RPM_9615_SEL_PM8018_L3				= 37,
+	MSM_RPM_9615_SEL_PM8018_L4				= 38,
+	MSM_RPM_9615_SEL_PM8018_L5				= 39,
+	MSM_RPM_9615_SEL_PM8018_L6				= 40,
+	MSM_RPM_9615_SEL_PM8018_L7				= 41,
+	MSM_RPM_9615_SEL_PM8018_L8				= 42,
+	MSM_RPM_9615_SEL_PM8018_L9				= 43,
+	MSM_RPM_9615_SEL_PM8018_L10				= 44,
+	MSM_RPM_9615_SEL_PM8018_L11				= 45,
+	MSM_RPM_9615_SEL_PM8018_L12				= 46,
+	MSM_RPM_9615_SEL_PM8018_L13				= 47,
+	MSM_RPM_9615_SEL_PM8018_L14				= 48,
+	MSM_RPM_9615_SEL_PM8018_LVS1				= 49,
 
-	MSM_RPM_SEL_NCP						= 80,
-	MSM_RPM_SEL_CXO_BUFFERS					= 81,
-	MSM_RPM_SEL_USB_OTG_SWITCH				= 82,
-	MSM_RPM_SEL_HDMI_SWITCH					= 83,
+	MSM_RPM_9615_SEL_NCP					= 80,
+	MSM_RPM_9615_SEL_CXO_BUFFERS				= 81,
+	MSM_RPM_9615_SEL_USB_OTG_SWITCH				= 82,
+	MSM_RPM_9615_SEL_HDMI_SWITCH				= 83,
 
-	MSM_RPM_SEL_LAST = MSM_RPM_SEL_HDMI_SWITCH,
+	MSM_RPM_9615_SEL_LAST = MSM_RPM_9615_SEL_HDMI_SWITCH,
 };
 
 /* RPM resource (4 byte) word ID enum */
 enum {
-	MSM_RPM_ID_NOTIFICATION_CONFIGURED_0			= 0,
-	MSM_RPM_ID_NOTIFICATION_CONFIGURED_3 =
-		MSM_RPM_ID_NOTIFICATION_CONFIGURED_0 + 3,
+	MSM_RPM_9615_ID_NOTIFICATION_CONFIGURED_0		= 0,
+	MSM_RPM_9615_ID_NOTIFICATION_CONFIGURED_3 =
+		MSM_RPM_9615_ID_NOTIFICATION_CONFIGURED_0 + 3,
 
-	MSM_RPM_ID_NOTIFICATION_REGISTERED_0			= 4,
-	MSM_RPM_ID_NOTIFICATION_REGISTERED_3 =
-		MSM_RPM_ID_NOTIFICATION_REGISTERED_0 + 3,
+	MSM_RPM_9615_ID_NOTIFICATION_REGISTERED_0		= 4,
+	MSM_RPM_9615_ID_NOTIFICATION_REGISTERED_3 =
+		MSM_RPM_9615_ID_NOTIFICATION_REGISTERED_0 + 3,
 
-	MSM_RPM_ID_INVALIDATE_0					= 8,
-	MSM_RPM_ID_INVALIDATE_7 =
-		MSM_RPM_ID_INVALIDATE_0 + 7,
+	MSM_RPM_9615_ID_INVALIDATE_0				= 8,
+	MSM_RPM_9615_ID_INVALIDATE_7 =
+		MSM_RPM_9615_ID_INVALIDATE_0 + 7,
 
-	MSM_RPM_ID_TRIGGER_TIMED_TO				= 16,
-	MSM_RPM_ID_TRIGGER_TIMED_SCLK_COUNT			= 17,
+	MSM_RPM_9615_ID_TRIGGER_TIMED_TO			= 16,
+	MSM_RPM_9615_ID_TRIGGER_TIMED_SCLK_COUNT		= 17,
 
-	MSM_RPM_ID_RPM_CTL					= 18,
+	MSM_RPM_9615_ID_RPM_CTL					= 18,
 
 	/* TRIGGER_CLEAR/SET deprecated in these 24 RESERVED bytes */
-	MSM_RPM_ID_RESERVED_0					= 19,
-	MSM_RPM_ID_RESERVED_5 =
-		MSM_RPM_ID_RESERVED_0 + 5,
+	MSM_RPM_9615_ID_RESERVED_0				= 19,
+	MSM_RPM_9615_ID_RESERVED_5 =
+		MSM_RPM_9615_ID_RESERVED_0 + 5,
 
-	MSM_RPM_ID_CXO_CLK					= 25,
-	MSM_RPM_ID_SYSTEM_FABRIC_CLK				= 26,
-	MSM_RPM_ID_DAYTONA_FABRIC_CLK				= 27,
-	MSM_RPM_ID_SFPB_CLK					= 28,
-	MSM_RPM_ID_CFPB_CLK					= 29,
-	MSM_RPM_ID_EBI1_CLK					= 30,
+	MSM_RPM_9615_ID_CXO_CLK					= 25,
+	MSM_RPM_9615_ID_SYSTEM_FABRIC_CLK			= 26,
+	MSM_RPM_9615_ID_DAYTONA_FABRIC_CLK			= 27,
+	MSM_RPM_9615_ID_SFPB_CLK				= 28,
+	MSM_RPM_9615_ID_CFPB_CLK				= 29,
+	MSM_RPM_9615_ID_EBI1_CLK				= 30,
 
-	MSM_RPM_ID_SYS_FABRIC_CFG_HALT_0			= 31,
-	MSM_RPM_ID_SYS_FABRIC_CFG_HALT_1			= 32,
-	MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_0			= 33,
-	MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_1			= 34,
-	MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_2			= 35,
-	MSM_RPM_ID_SYS_FABRIC_CFG_IOCTL				= 36,
-	MSM_RPM_ID_SYSTEM_FABRIC_ARB_0				= 37,
-	MSM_RPM_ID_SYSTEM_FABRIC_ARB_26 =
-		MSM_RPM_ID_SYSTEM_FABRIC_ARB_0 + 26,
+	MSM_RPM_9615_ID_SYS_FABRIC_CFG_HALT_0			= 31,
+	MSM_RPM_9615_ID_SYS_FABRIC_CFG_HALT_1			= 32,
+	MSM_RPM_9615_ID_SYS_FABRIC_CFG_CLKMOD_0			= 33,
+	MSM_RPM_9615_ID_SYS_FABRIC_CFG_CLKMOD_1			= 34,
+	MSM_RPM_9615_ID_SYS_FABRIC_CFG_CLKMOD_2			= 35,
+	MSM_RPM_9615_ID_SYS_FABRIC_CFG_IOCTL			= 36,
+	MSM_RPM_9615_ID_SYSTEM_FABRIC_ARB_0			= 37,
+	MSM_RPM_9615_ID_SYSTEM_FABRIC_ARB_26 =
+		MSM_RPM_9615_ID_SYSTEM_FABRIC_ARB_0 + 26,
 
-	MSM_RPM_ID_PM8018_S1_0					= 64,
-	MSM_RPM_ID_PM8018_S1_1					= 65,
-	MSM_RPM_ID_PM8018_S2_0					= 66,
-	MSM_RPM_ID_PM8018_S2_1					= 67,
-	MSM_RPM_ID_PM8018_S3_0					= 68,
-	MSM_RPM_ID_PM8018_S3_1					= 69,
-	MSM_RPM_ID_PM8018_S4_0					= 70,
-	MSM_RPM_ID_PM8018_S4_1					= 71,
-	MSM_RPM_ID_PM8018_S5_0					= 72,
-	MSM_RPM_ID_PM8018_S5_1					= 73,
-	MSM_RPM_ID_PM8018_L1_0					= 74,
-	MSM_RPM_ID_PM8018_L1_1					= 75,
-	MSM_RPM_ID_PM8018_L2_0					= 76,
-	MSM_RPM_ID_PM8018_L2_1					= 77,
-	MSM_RPM_ID_PM8018_L3_0					= 78,
-	MSM_RPM_ID_PM8018_L3_1					= 79,
-	MSM_RPM_ID_PM8018_L4_0					= 80,
-	MSM_RPM_ID_PM8018_L4_1					= 81,
-	MSM_RPM_ID_PM8018_L5_0					= 82,
-	MSM_RPM_ID_PM8018_L5_1					= 83,
-	MSM_RPM_ID_PM8018_L6_0					= 84,
-	MSM_RPM_ID_PM8018_L6_1					= 85,
-	MSM_RPM_ID_PM8018_L7_0					= 86,
-	MSM_RPM_ID_PM8018_L7_1					= 87,
-	MSM_RPM_ID_PM8018_L8_0					= 88,
-	MSM_RPM_ID_PM8018_L8_1					= 89,
-	MSM_RPM_ID_PM8018_L9_0					= 90,
-	MSM_RPM_ID_PM8018_L9_1					= 91,
-	MSM_RPM_ID_PM8018_L10_0					= 92,
-	MSM_RPM_ID_PM8018_L10_1					= 93,
-	MSM_RPM_ID_PM8018_L11_0					= 94,
-	MSM_RPM_ID_PM8018_L11_1					= 95,
-	MSM_RPM_ID_PM8018_L12_0					= 96,
-	MSM_RPM_ID_PM8018_L12_1					= 97,
-	MSM_RPM_ID_PM8018_L13_0					= 98,
-	MSM_RPM_ID_PM8018_L13_1					= 99,
-	MSM_RPM_ID_PM8018_L14_0					= 100,
-	MSM_RPM_ID_PM8018_L14_1					= 101,
-	MSM_RPM_ID_PM8018_LVS1					= 102,
+	MSM_RPM_9615_ID_PM8018_S1_0				= 64,
+	MSM_RPM_9615_ID_PM8018_S1_1				= 65,
+	MSM_RPM_9615_ID_PM8018_S2_0				= 66,
+	MSM_RPM_9615_ID_PM8018_S2_1				= 67,
+	MSM_RPM_9615_ID_PM8018_S3_0				= 68,
+	MSM_RPM_9615_ID_PM8018_S3_1				= 69,
+	MSM_RPM_9615_ID_PM8018_S4_0				= 70,
+	MSM_RPM_9615_ID_PM8018_S4_1				= 71,
+	MSM_RPM_9615_ID_PM8018_S5_0				= 72,
+	MSM_RPM_9615_ID_PM8018_S5_1				= 73,
+	MSM_RPM_9615_ID_PM8018_L1_0				= 74,
+	MSM_RPM_9615_ID_PM8018_L1_1				= 75,
+	MSM_RPM_9615_ID_PM8018_L2_0				= 76,
+	MSM_RPM_9615_ID_PM8018_L2_1				= 77,
+	MSM_RPM_9615_ID_PM8018_L3_0				= 78,
+	MSM_RPM_9615_ID_PM8018_L3_1				= 79,
+	MSM_RPM_9615_ID_PM8018_L4_0				= 80,
+	MSM_RPM_9615_ID_PM8018_L4_1				= 81,
+	MSM_RPM_9615_ID_PM8018_L5_0				= 82,
+	MSM_RPM_9615_ID_PM8018_L5_1				= 83,
+	MSM_RPM_9615_ID_PM8018_L6_0				= 84,
+	MSM_RPM_9615_ID_PM8018_L6_1				= 85,
+	MSM_RPM_9615_ID_PM8018_L7_0				= 86,
+	MSM_RPM_9615_ID_PM8018_L7_1				= 87,
+	MSM_RPM_9615_ID_PM8018_L8_0				= 88,
+	MSM_RPM_9615_ID_PM8018_L8_1				= 89,
+	MSM_RPM_9615_ID_PM8018_L9_0				= 90,
+	MSM_RPM_9615_ID_PM8018_L9_1				= 91,
+	MSM_RPM_9615_ID_PM8018_L10_0				= 92,
+	MSM_RPM_9615_ID_PM8018_L10_1				= 93,
+	MSM_RPM_9615_ID_PM8018_L11_0				= 94,
+	MSM_RPM_9615_ID_PM8018_L11_1				= 95,
+	MSM_RPM_9615_ID_PM8018_L12_0				= 96,
+	MSM_RPM_9615_ID_PM8018_L12_1				= 97,
+	MSM_RPM_9615_ID_PM8018_L13_0				= 98,
+	MSM_RPM_9615_ID_PM8018_L13_1				= 99,
+	MSM_RPM_9615_ID_PM8018_L14_0				= 100,
+	MSM_RPM_9615_ID_PM8018_L14_1				= 101,
+	MSM_RPM_9615_ID_PM8018_LVS1				= 102,
 
-	MSM_RPM_ID_NCP_0					= 103,
-	MSM_RPM_ID_NCP_1					= 104,
-	MSM_RPM_ID_CXO_BUFFERS					= 105,
-	MSM_RPM_ID_USB_OTG_SWITCH				= 106,
-	MSM_RPM_ID_HDMI_SWITCH					= 107,
+	MSM_RPM_9615_ID_NCP_0					= 103,
+	MSM_RPM_9615_ID_NCP_1					= 104,
+	MSM_RPM_9615_ID_CXO_BUFFERS				= 105,
+	MSM_RPM_9615_ID_USB_OTG_SWITCH				= 106,
+	MSM_RPM_9615_ID_HDMI_SWITCH				= 107,
 
-	MSM_RPM_ID_LAST = MSM_RPM_ID_HDMI_SWITCH,
-};
-
-/* RPM resources RPM_ID aliases */
-enum {
-	MSM_RPMRS_ID_RPM_CTL = MSM_RPM_ID_RPM_CTL,
-	/* XO clock for this target is CXO */
-	MSM_RPMRS_ID_PXO_CLK = MSM_RPM_ID_CXO_CLK,
-	MSM_RPMRS_ID_VDD_DIG_0 = MSM_RPM_ID_PM8018_S1_0,
-	MSM_RPMRS_ID_VDD_DIG_1 = MSM_RPM_ID_PM8018_S1_1,
-	MSM_RPMRS_ID_VDD_MEM_0 = MSM_RPM_ID_PM8018_L9_0,
-	MSM_RPMRS_ID_VDD_MEM_1 = MSM_RPM_ID_PM8018_L9_1,
-
-	/* MSM9615 L2 cache power control not via RPM
-	 * MSM_RPM_ID_LAST + 1 indicates invalid */
-	MSM_RPMRS_ID_APPS_L2_CACHE_CTL = MSM_RPM_ID_LAST + 1
-};
-
-/* VDD values are in microvolts */
-#define MSM_RPMRS_VDD_MASK  0x7fffff
-enum {
-	MSM_RPMRS_VDD_MEM_RET_LOW	=  750000,
-	MSM_RPMRS_VDD_MEM_RET_HIGH	=  750000,
-	MSM_RPMRS_VDD_MEM_ACTIVE	= 1050000,
-	MSM_RPMRS_VDD_MEM_MAX		= 1150000,
-};
-
-enum {
-	MSM_RPMRS_VDD_DIG_RET_LOW	=  500000,
-	MSM_RPMRS_VDD_DIG_RET_HIGH	=  750000,
-	MSM_RPMRS_VDD_DIG_ACTIVE	=  950000,
-	MSM_RPMRS_VDD_DIG_MAX		= 1150000,
+	MSM_RPM_9615_ID_LAST = MSM_RPM_9615_ID_HDMI_SWITCH,
 };
 
 /* RPM status ID enum */
 enum {
-	MSM_RPM_STATUS_ID_VERSION_MAJOR				= 0,
-	MSM_RPM_STATUS_ID_VERSION_MINOR				= 1,
-	MSM_RPM_STATUS_ID_VERSION_BUILD				= 2,
-	MSM_RPM_STATUS_ID_SUPPORTED_RESOURCES_0			= 3,
-	MSM_RPM_STATUS_ID_SUPPORTED_RESOURCES_1			= 4,
-	MSM_RPM_STATUS_ID_SUPPORTED_RESOURCES_2			= 5,
-	MSM_RPM_STATUS_ID_RESERVED_SUPPORTED_RESOURCES_0	= 6,
-	MSM_RPM_STATUS_ID_SEQUENCE				= 7,
-	MSM_RPM_STATUS_ID_RPM_CTL				= 8,
-	MSM_RPM_STATUS_ID_CXO_CLK				= 9,
-	MSM_RPM_STATUS_ID_SYSTEM_FABRIC_CLK			= 10,
-	MSM_RPM_STATUS_ID_DAYTONA_FABRIC_CLK			= 11,
-	MSM_RPM_STATUS_ID_SFPB_CLK				= 12,
-	MSM_RPM_STATUS_ID_CFPB_CLK				= 13,
-	MSM_RPM_STATUS_ID_EBI1_CLK				= 14,
-	MSM_RPM_STATUS_ID_SYS_FABRIC_CFG_HALT			= 15,
-	MSM_RPM_STATUS_ID_SYS_FABRIC_CFG_CLKMOD			= 16,
-	MSM_RPM_STATUS_ID_SYS_FABRIC_CFG_IOCTL			= 17,
-	MSM_RPM_STATUS_ID_SYSTEM_FABRIC_ARB			= 18,
-	MSM_RPM_STATUS_ID_PM8018_S1_0				= 19,
-	MSM_RPM_STATUS_ID_PM8018_S1_1				= 20,
-	MSM_RPM_STATUS_ID_PM8018_S2_0				= 21,
-	MSM_RPM_STATUS_ID_PM8018_S2_1				= 22,
-	MSM_RPM_STATUS_ID_PM8018_S3_0				= 23,
-	MSM_RPM_STATUS_ID_PM8018_S3_1				= 24,
-	MSM_RPM_STATUS_ID_PM8018_S4_0				= 25,
-	MSM_RPM_STATUS_ID_PM8018_S4_1				= 26,
-	MSM_RPM_STATUS_ID_PM8018_S5_0				= 27,
-	MSM_RPM_STATUS_ID_PM8018_S5_1				= 28,
-	MSM_RPM_STATUS_ID_PM8018_L1_0				= 29,
-	MSM_RPM_STATUS_ID_PM8018_L1_1				= 30,
-	MSM_RPM_STATUS_ID_PM8018_L2_0				= 31,
-	MSM_RPM_STATUS_ID_PM8018_L2_1				= 32,
-	MSM_RPM_STATUS_ID_PM8018_L3_0				= 33,
-	MSM_RPM_STATUS_ID_PM8018_L3_1				= 34,
-	MSM_RPM_STATUS_ID_PM8018_L4_0				= 35,
-	MSM_RPM_STATUS_ID_PM8018_L4_1				= 36,
-	MSM_RPM_STATUS_ID_PM8018_L5_0				= 37,
-	MSM_RPM_STATUS_ID_PM8018_L5_1				= 38,
-	MSM_RPM_STATUS_ID_PM8018_L6_0				= 39,
-	MSM_RPM_STATUS_ID_PM8018_L6_1				= 40,
-	MSM_RPM_STATUS_ID_PM8018_L7_0				= 41,
-	MSM_RPM_STATUS_ID_PM8018_L7_1				= 42,
-	MSM_RPM_STATUS_ID_PM8018_L8_0				= 43,
-	MSM_RPM_STATUS_ID_PM8018_L8_1				= 44,
-	MSM_RPM_STATUS_ID_PM8018_L9_0				= 45,
-	MSM_RPM_STATUS_ID_PM8018_L9_1				= 46,
-	MSM_RPM_STATUS_ID_PM8018_L10_0				= 47,
-	MSM_RPM_STATUS_ID_PM8018_L10_1				= 48,
-	MSM_RPM_STATUS_ID_PM8018_L11_0				= 49,
-	MSM_RPM_STATUS_ID_PM8018_L11_1				= 50,
-	MSM_RPM_STATUS_ID_PM8018_L12_0				= 51,
-	MSM_RPM_STATUS_ID_PM8018_L12_1				= 52,
-	MSM_RPM_STATUS_ID_PM8018_L13_0				= 53,
-	MSM_RPM_STATUS_ID_PM8018_L13_1				= 54,
-	MSM_RPM_STATUS_ID_PM8018_L14_0				= 55,
-	MSM_RPM_STATUS_ID_PM8018_L14_1				= 56,
-	MSM_RPM_STATUS_ID_PM8018_LVS1				= 57,
-	MSM_RPM_STATUS_ID_NCP_0					= 58,
-	MSM_RPM_STATUS_ID_NCP_1					= 59,
-	MSM_RPM_STATUS_ID_CXO_BUFFERS				= 60,
-	MSM_RPM_STATUS_ID_USB_OTG_SWITCH			= 61,
-	MSM_RPM_STATUS_ID_HDMI_SWITCH				= 62,
+	MSM_RPM_9615_STATUS_ID_VERSION_MAJOR			= 0,
+	MSM_RPM_9615_STATUS_ID_VERSION_MINOR			= 1,
+	MSM_RPM_9615_STATUS_ID_VERSION_BUILD			= 2,
+	MSM_RPM_9615_STATUS_ID_SUPPORTED_RESOURCES_0		= 3,
+	MSM_RPM_9615_STATUS_ID_SUPPORTED_RESOURCES_1		= 4,
+	MSM_RPM_9615_STATUS_ID_SUPPORTED_RESOURCES_2		= 5,
+	MSM_RPM_9615_STATUS_ID_RESERVED_SUPPORTED_RESOURCES_0	= 6,
+	MSM_RPM_9615_STATUS_ID_SEQUENCE				= 7,
+	MSM_RPM_9615_STATUS_ID_RPM_CTL				= 8,
+	MSM_RPM_9615_STATUS_ID_CXO_CLK				= 9,
+	MSM_RPM_9615_STATUS_ID_SYSTEM_FABRIC_CLK		= 10,
+	MSM_RPM_9615_STATUS_ID_DAYTONA_FABRIC_CLK		= 11,
+	MSM_RPM_9615_STATUS_ID_SFPB_CLK				= 12,
+	MSM_RPM_9615_STATUS_ID_CFPB_CLK				= 13,
+	MSM_RPM_9615_STATUS_ID_EBI1_CLK				= 14,
+	MSM_RPM_9615_STATUS_ID_SYS_FABRIC_CFG_HALT		= 15,
+	MSM_RPM_9615_STATUS_ID_SYS_FABRIC_CFG_CLKMOD		= 16,
+	MSM_RPM_9615_STATUS_ID_SYS_FABRIC_CFG_IOCTL		= 17,
+	MSM_RPM_9615_STATUS_ID_SYSTEM_FABRIC_ARB		= 18,
+	MSM_RPM_9615_STATUS_ID_PM8018_S1_0			= 19,
+	MSM_RPM_9615_STATUS_ID_PM8018_S1_1			= 20,
+	MSM_RPM_9615_STATUS_ID_PM8018_S2_0			= 21,
+	MSM_RPM_9615_STATUS_ID_PM8018_S2_1			= 22,
+	MSM_RPM_9615_STATUS_ID_PM8018_S3_0			= 23,
+	MSM_RPM_9615_STATUS_ID_PM8018_S3_1			= 24,
+	MSM_RPM_9615_STATUS_ID_PM8018_S4_0			= 25,
+	MSM_RPM_9615_STATUS_ID_PM8018_S4_1			= 26,
+	MSM_RPM_9615_STATUS_ID_PM8018_S5_0			= 27,
+	MSM_RPM_9615_STATUS_ID_PM8018_S5_1			= 28,
+	MSM_RPM_9615_STATUS_ID_PM8018_L1_0			= 29,
+	MSM_RPM_9615_STATUS_ID_PM8018_L1_1			= 30,
+	MSM_RPM_9615_STATUS_ID_PM8018_L2_0			= 31,
+	MSM_RPM_9615_STATUS_ID_PM8018_L2_1			= 32,
+	MSM_RPM_9615_STATUS_ID_PM8018_L3_0			= 33,
+	MSM_RPM_9615_STATUS_ID_PM8018_L3_1			= 34,
+	MSM_RPM_9615_STATUS_ID_PM8018_L4_0			= 35,
+	MSM_RPM_9615_STATUS_ID_PM8018_L4_1			= 36,
+	MSM_RPM_9615_STATUS_ID_PM8018_L5_0			= 37,
+	MSM_RPM_9615_STATUS_ID_PM8018_L5_1			= 38,
+	MSM_RPM_9615_STATUS_ID_PM8018_L6_0			= 39,
+	MSM_RPM_9615_STATUS_ID_PM8018_L6_1			= 40,
+	MSM_RPM_9615_STATUS_ID_PM8018_L7_0			= 41,
+	MSM_RPM_9615_STATUS_ID_PM8018_L7_1			= 42,
+	MSM_RPM_9615_STATUS_ID_PM8018_L8_0			= 43,
+	MSM_RPM_9615_STATUS_ID_PM8018_L8_1			= 44,
+	MSM_RPM_9615_STATUS_ID_PM8018_L9_0			= 45,
+	MSM_RPM_9615_STATUS_ID_PM8018_L9_1			= 46,
+	MSM_RPM_9615_STATUS_ID_PM8018_L10_0			= 47,
+	MSM_RPM_9615_STATUS_ID_PM8018_L10_1			= 48,
+	MSM_RPM_9615_STATUS_ID_PM8018_L11_0			= 49,
+	MSM_RPM_9615_STATUS_ID_PM8018_L11_1			= 50,
+	MSM_RPM_9615_STATUS_ID_PM8018_L12_0			= 51,
+	MSM_RPM_9615_STATUS_ID_PM8018_L12_1			= 52,
+	MSM_RPM_9615_STATUS_ID_PM8018_L13_0			= 53,
+	MSM_RPM_9615_STATUS_ID_PM8018_L13_1			= 54,
+	MSM_RPM_9615_STATUS_ID_PM8018_L14_0			= 55,
+	MSM_RPM_9615_STATUS_ID_PM8018_L14_1			= 56,
+	MSM_RPM_9615_STATUS_ID_PM8018_LVS1			= 57,
+	MSM_RPM_9615_STATUS_ID_NCP_0				= 58,
+	MSM_RPM_9615_STATUS_ID_NCP_1				= 59,
+	MSM_RPM_9615_STATUS_ID_CXO_BUFFERS			= 60,
+	MSM_RPM_9615_STATUS_ID_USB_OTG_SWITCH			= 61,
+	MSM_RPM_9615_STATUS_ID_HDMI_SWITCH			= 62,
 
-	MSM_RPM_STATUS_ID_LAST = MSM_RPM_STATUS_ID_HDMI_SWITCH,
+	MSM_RPM_9615_STATUS_ID_LAST = MSM_RPM_9615_STATUS_ID_HDMI_SWITCH,
 };
 
 #endif /* __ARCH_ARM_MACH_MSM_RPM_9615_H */
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h b/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h
new file mode 100644
index 0000000..9e654ed
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h
@@ -0,0 +1,164 @@
+/*
+ * 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 __ARCH_ARM_MACH_MSM_INCLUDE_MACH_RPM_REGULATOR_8930_H
+#define __ARCH_ARM_MACH_MSM_INCLUDE_MACH_RPM_REGULATOR_8930_H
+
+/* Pin control input signals. */
+#define RPM_VREG_PIN_CTRL_PM8038_D1	0x01
+#define RPM_VREG_PIN_CTRL_PM8038_A0	0x02
+#define RPM_VREG_PIN_CTRL_PM8038_A1	0x04
+#define RPM_VREG_PIN_CTRL_PM8038_A2	0x08
+
+/**
+ * enum rpm_vreg_pin_fn_8930 - RPM regulator pin function choices
+ * %RPM_VREG_PIN_FN_8930_DONT_CARE:	do not care about pin control state of
+ *					the regulator; allow another master
+ *					processor to specify pin control
+ * %RPM_VREG_PIN_FN_8930_ENABLE:	pin control switches between disable and
+ *					enable
+ * %RPM_VREG_PIN_FN_8930_MODE:		pin control switches between LPM and HPM
+ * %RPM_VREG_PIN_FN_8930_SLEEP_B:	regulator is forced into LPM when
+ *					sleep_b signal is asserted
+ * %RPM_VREG_PIN_FN_8930_NONE:		do not use pin control for the regulator
+ *					and do not allow another master to
+ *					request pin control
+ *
+ * The pin function specified in platform data corresponds to the active state
+ * pin function value.  Pin function will be NONE until a consumer requests
+ * pin control to be enabled.
+ */
+enum rpm_vreg_pin_fn_8930 {
+	RPM_VREG_PIN_FN_8930_DONT_CARE,
+	RPM_VREG_PIN_FN_8930_ENABLE,
+	RPM_VREG_PIN_FN_8930_MODE,
+	RPM_VREG_PIN_FN_8930_SLEEP_B,
+	RPM_VREG_PIN_FN_8930_NONE,
+};
+
+/**
+ * enum rpm_vreg_force_mode_8930 - RPM regulator force mode choices
+ * %RPM_VREG_FORCE_MODE_8930_PIN_CTRL:	allow pin control usage
+ * %RPM_VREG_FORCE_MODE_8930_NONE:	do not force any mode
+ * %RPM_VREG_FORCE_MODE_8930_LPM:	force into low power mode
+ * %RPM_VREG_FORCE_MODE_8930_AUTO:	allow regulator to automatically select
+ *					its own mode based on realtime current
+ *					draw (only available for SMPS
+ *					regulators)
+ * %RPM_VREG_FORCE_MODE_8930_HPM:	force into high power mode
+ * %RPM_VREG_FORCE_MODE_8930_BYPASS:	set regulator to use bypass mode, i.e.
+ *					to act as a switch and not regulate
+ *					(only available for LDO regulators)
+ *
+ * Force mode is used to override aggregation with other masters and to set
+ * special operating modes.
+ */
+enum rpm_vreg_force_mode_8930 {
+	RPM_VREG_FORCE_MODE_8930_PIN_CTRL = 0,
+	RPM_VREG_FORCE_MODE_8930_NONE = 0,
+	RPM_VREG_FORCE_MODE_8930_LPM,
+	RPM_VREG_FORCE_MODE_8930_AUTO,		/* SMPS only */
+	RPM_VREG_FORCE_MODE_8930_HPM,
+	RPM_VREG_FORCE_MODE_8930_BYPASS,	/* LDO only */
+};
+
+/**
+ * enum rpm_vreg_power_mode_8930 - power mode for SMPS regulators
+ * %RPM_VREG_POWER_MODE_8930_HYSTERETIC: Use hysteretic mode for HPM and when
+ *					 usage goes high in AUTO
+ * %RPM_VREG_POWER_MODE_8930_PWM:	 Use PWM mode for HPM and when usage
+ *					 goes high in AUTO
+ */
+enum rpm_vreg_power_mode_8930 {
+	RPM_VREG_POWER_MODE_8930_HYSTERETIC,
+	RPM_VREG_POWER_MODE_8930_PWM,
+};
+
+/**
+ * enum rpm_vreg_id - RPM regulator ID numbers (both real and pin control)
+ */
+enum rpm_vreg_id_8930 {
+	RPM_VREG_ID_PM8038_L1,
+	RPM_VREG_ID_PM8038_L2,
+	RPM_VREG_ID_PM8038_L3,
+	RPM_VREG_ID_PM8038_L4,
+	RPM_VREG_ID_PM8038_L5,
+	RPM_VREG_ID_PM8038_L6,
+	RPM_VREG_ID_PM8038_L7,
+	RPM_VREG_ID_PM8038_L8,
+	RPM_VREG_ID_PM8038_L9,
+	RPM_VREG_ID_PM8038_L10,
+	RPM_VREG_ID_PM8038_L11,
+	RPM_VREG_ID_PM8038_L12,
+	RPM_VREG_ID_PM8038_L14,
+	RPM_VREG_ID_PM8038_L15,
+	RPM_VREG_ID_PM8038_L16,
+	RPM_VREG_ID_PM8038_L17,
+	RPM_VREG_ID_PM8038_L18,
+	RPM_VREG_ID_PM8038_L19,
+	RPM_VREG_ID_PM8038_L20,
+	RPM_VREG_ID_PM8038_L21,
+	RPM_VREG_ID_PM8038_L22,
+	RPM_VREG_ID_PM8038_L23,
+	RPM_VREG_ID_PM8038_L24,
+	RPM_VREG_ID_PM8038_L26,
+	RPM_VREG_ID_PM8038_L27,
+	RPM_VREG_ID_PM8038_S1,
+	RPM_VREG_ID_PM8038_S2,
+	RPM_VREG_ID_PM8038_S3,
+	RPM_VREG_ID_PM8038_S4,
+	RPM_VREG_ID_PM8038_S5,
+	RPM_VREG_ID_PM8038_S6,
+	RPM_VREG_ID_PM8038_LVS1,
+	RPM_VREG_ID_PM8038_LVS2,
+	RPM_VREG_ID_PM8038_MAX_REAL = RPM_VREG_ID_PM8038_LVS2,
+
+	/* The following are IDs for regulator devices to enable pin control. */
+	RPM_VREG_ID_PM8038_L2_PC,
+	RPM_VREG_ID_PM8038_L3_PC,
+	RPM_VREG_ID_PM8038_L4_PC,
+	RPM_VREG_ID_PM8038_L5_PC,
+	RPM_VREG_ID_PM8038_L6_PC,
+	RPM_VREG_ID_PM8038_L7_PC,
+	RPM_VREG_ID_PM8038_L8_PC,
+	RPM_VREG_ID_PM8038_L9_PC,
+	RPM_VREG_ID_PM8038_L10_PC,
+	RPM_VREG_ID_PM8038_L11_PC,
+	RPM_VREG_ID_PM8038_L12_PC,
+	RPM_VREG_ID_PM8038_L14_PC,
+	RPM_VREG_ID_PM8038_L15_PC,
+	RPM_VREG_ID_PM8038_L17_PC,
+	RPM_VREG_ID_PM8038_L18_PC,
+	RPM_VREG_ID_PM8038_L21_PC,
+	RPM_VREG_ID_PM8038_L22_PC,
+	RPM_VREG_ID_PM8038_L23_PC,
+	RPM_VREG_ID_PM8038_L26_PC,
+	RPM_VREG_ID_PM8038_S1_PC,
+	RPM_VREG_ID_PM8038_S2_PC,
+	RPM_VREG_ID_PM8038_S3_PC,
+	RPM_VREG_ID_PM8038_S4_PC,
+	RPM_VREG_ID_PM8038_LVS1_PC,
+	RPM_VREG_ID_PM8038_LVS2_PC,
+	RPM_VREG_ID_PM8038_MAX = RPM_VREG_ID_PM8038_LVS2_PC,
+};
+
+/* Minimum high power mode loads in uA. */
+#define RPM_VREG_8930_LDO_50_HPM_MIN_LOAD		5000
+#define RPM_VREG_8930_LDO_150_HPM_MIN_LOAD		10000
+#define RPM_VREG_8930_LDO_300_HPM_MIN_LOAD		10000
+#define RPM_VREG_8930_LDO_600_HPM_MIN_LOAD		10000
+#define RPM_VREG_8930_LDO_1200_HPM_MIN_LOAD		10000
+#define RPM_VREG_8930_SMPS_1500_HPM_MIN_LOAD		100000
+#define RPM_VREG_8930_SMPS_2000_HPM_MIN_LOAD		100000
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator.h b/arch/arm/mach-msm/include/mach/rpm-regulator.h
index 1095078..0d113ac 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator.h
@@ -21,6 +21,7 @@
 #include <mach/rpm-regulator-8960.h>
 #include <mach/rpm-regulator-9615.h>
 #include <mach/rpm-regulator-copper.h>
+#include <mach/rpm-regulator-8930.h>
 
 /**
  * enum rpm_vreg_version - supported RPM regulator versions
@@ -29,7 +30,8 @@
 	RPM_VREG_VERSION_8660,
 	RPM_VREG_VERSION_8960,
 	RPM_VREG_VERSION_9615,
-	RPM_VREG_VERSION_MAX = RPM_VREG_VERSION_9615,
+	RPM_VREG_VERSION_8930,
+	RPM_VREG_VERSION_MAX = RPM_VREG_VERSION_8930,
 };
 
 #define RPM_VREG_PIN_CTRL_NONE		0x00
diff --git a/arch/arm/mach-msm/include/mach/rpm.h b/arch/arm/mach-msm/include/mach/rpm.h
index dda9954..80ec683 100644
--- a/arch/arm/mach-msm/include/mach/rpm.h
+++ b/arch/arm/mach-msm/include/mach/rpm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,14 +18,13 @@
 #include <linux/list.h>
 #include <linux/semaphore.h>
 
-#if defined(CONFIG_ARCH_MSM8X60)
 #include <mach/rpm-8660.h>
-#elif defined(CONFIG_ARCH_MSM9615)
 #include <mach/rpm-9615.h>
-#elif defined(CONFIG_ARCH_MSM8960)
 #include <mach/rpm-8960.h>
-#endif
+#include <mach/rpm-8930.h>
+#include <mach/rpm-8064.h>
 
+#define SEL_MASK_SIZE (5)
 
 enum {
 	MSM_RPM_PAGE_STATUS,
@@ -44,13 +43,795 @@
 	MSM_RPM_CTX_REJECTED = 31,
 };
 
+/* RPM control message RAM enums */
+enum {
+	MSM_RPM_CTRL_VERSION_MAJOR,
+	MSM_RPM_CTRL_VERSION_MINOR,
+	MSM_RPM_CTRL_VERSION_BUILD,
+
+	MSM_RPM_CTRL_REQ_CTX_0,
+	MSM_RPM_CTRL_REQ_SEL_0,
+	MSM_RPM_CTRL_ACK_CTX_0,
+	MSM_RPM_CTRL_ACK_SEL_0,
+
+	MSM_RPM_CTRL_LAST,
+};
+
+enum {
+	MSM_RPM_ID_NOTIFICATION_CONFIGURED_0 = 0,
+	MSM_RPM_ID_NOTIFICATION_CONFIGURED_7 =
+		MSM_RPM_ID_NOTIFICATION_CONFIGURED_0 + 7,
+
+	MSM_RPM_ID_NOTIFICATION_REGISTERED_0,
+	MSM_RPM_ID_NOTIFICATION_REGISTERED_7 =
+		MSM_RPM_ID_NOTIFICATION_REGISTERED_0 + 7,
+
+	MSM_RPM_ID_INVALIDATE_0,
+	MSM_RPM_ID_INVALIDATE_7 =
+		MSM_RPM_ID_INVALIDATE_0 + 7,
+
+	MSM_RPM_ID_TRIGGER_TIMED_TO,
+	MSM_RPM_ID_TRIGGER_TIMED_0,
+	MSM_RPM_ID_TRIGGER_TIMED_SCLK_COUNT,
+
+	MSM_RPM_ID_RPM_CTL,
+
+	/* TRIGGER_CLEAR/SET deprecated in these 24 RESERVED bytes */
+	MSM_RPM_ID_RESERVED_0,
+	MSM_RPM_ID_RESERVED_5 =
+		MSM_RPM_ID_RESERVED_0 + 5,
+
+	MSM_RPM_ID_CXO_CLK,
+	MSM_RPM_ID_PXO_CLK,
+	MSM_RPM_ID_APPS_FABRIC_CLK,
+	MSM_RPM_ID_SYSTEM_FABRIC_CLK,
+	MSM_RPM_ID_MM_FABRIC_CLK,
+	MSM_RPM_ID_DAYTONA_FABRIC_CLK,
+	MSM_RPM_ID_SFPB_CLK,
+	MSM_RPM_ID_CFPB_CLK,
+	MSM_RPM_ID_MMFPB_CLK,
+	MSM_RPM_ID_EBI1_CLK,
+
+	MSM_RPM_ID_APPS_FABRIC_CFG_HALT_0,
+	MSM_RPM_ID_APPS_FABRIC_HALT_0 =
+		MSM_RPM_ID_APPS_FABRIC_CFG_HALT_0,
+	MSM_RPM_ID_APPS_FABRIC_CFG_HALT_1,
+	MSM_RPM_ID_APPS_FABRIC_CFG_CLKMOD_0,
+	MSM_RPM_ID_APPS_FABRIC_CLOCK_MODE_0 =
+		MSM_RPM_ID_APPS_FABRIC_CFG_CLKMOD_0,
+	MSM_RPM_ID_APPS_FABRIC_CFG_CLKMOD_1,
+	MSM_RPM_ID_APPS_FABRIC_CFG_CLKMOD_2,
+	MSM_RPM_ID_APPS_FABRIC_CFG_IOCTL,
+	MSM_RPM_ID_APPS_FABRIC_ARB_0,
+	MSM_RPM_ID_APPS_FABRIC_ARB_11 =
+		MSM_RPM_ID_APPS_FABRIC_ARB_0 + 11,
+
+	MSM_RPM_ID_SYS_FABRIC_CFG_HALT_0,
+	MSM_RPM_ID_SYSTEM_FABRIC_HALT_0 =
+		MSM_RPM_ID_SYS_FABRIC_CFG_HALT_0,
+	MSM_RPM_ID_SYS_FABRIC_CFG_HALT_1,
+	MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_0,
+	MSM_RPM_ID_SYSTEM_FABRIC_CLOCK_MODE_0 =
+		MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_0,
+	MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_1,
+	MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_2,
+	MSM_RPM_ID_SYS_FABRIC_CFG_IOCTL,
+	MSM_RPM_ID_SYSTEM_FABRIC_ARB_0,
+	MSM_RPM_ID_SYSTEM_FABRIC_ARB_28 =
+		MSM_RPM_ID_SYSTEM_FABRIC_ARB_0 + 28,
+
+	MSM_RPM_ID_MMSS_FABRIC_CFG_HALT_0,
+	MSM_RPM_ID_MM_FABRIC_HALT_0 =
+		MSM_RPM_ID_MMSS_FABRIC_CFG_HALT_0,
+	MSM_RPM_ID_MMSS_FABRIC_CFG_HALT_1,
+	MSM_RPM_ID_MMSS_FABRIC_CFG_CLKMOD_0,
+	MSM_RPM_ID_MM_FABRIC_CLOCK_MODE_0 =
+		MSM_RPM_ID_MMSS_FABRIC_CFG_CLKMOD_0,
+	MSM_RPM_ID_MMSS_FABRIC_CFG_CLKMOD_1,
+	MSM_RPM_ID_MMSS_FABRIC_CFG_CLKMOD_2,
+	MSM_RPM_ID_MMSS_FABRIC_CFG_IOCTL,
+	MSM_RPM_ID_MM_FABRIC_ARB_0,
+	MSM_RPM_ID_MM_FABRIC_ARB_22 =
+		MSM_RPM_ID_MM_FABRIC_ARB_0 + 22,
+
+	MSM_RPM_ID_PM8921_S1_0,
+	MSM_RPM_ID_PM8921_S1_1,
+	MSM_RPM_ID_PM8921_S2_0,
+	MSM_RPM_ID_PM8921_S2_1,
+	MSM_RPM_ID_PM8921_S3_0,
+	MSM_RPM_ID_PM8921_S3_1,
+	MSM_RPM_ID_PM8921_S4_0,
+	MSM_RPM_ID_PM8921_S4_1,
+	MSM_RPM_ID_PM8921_S5_0,
+	MSM_RPM_ID_PM8921_S5_1,
+	MSM_RPM_ID_PM8921_S6_0,
+	MSM_RPM_ID_PM8921_S6_1,
+	MSM_RPM_ID_PM8921_S7_0,
+	MSM_RPM_ID_PM8921_S7_1,
+	MSM_RPM_ID_PM8921_S8_0,
+	MSM_RPM_ID_PM8921_S8_1,
+	MSM_RPM_ID_PM8921_L1_0,
+	MSM_RPM_ID_PM8921_L1_1,
+	MSM_RPM_ID_PM8921_L2_0,
+	MSM_RPM_ID_PM8921_L2_1,
+	MSM_RPM_ID_PM8921_L3_0,
+	MSM_RPM_ID_PM8921_L3_1,
+	MSM_RPM_ID_PM8921_L4_0,
+	MSM_RPM_ID_PM8921_L4_1,
+	MSM_RPM_ID_PM8921_L5_0,
+	MSM_RPM_ID_PM8921_L5_1,
+	MSM_RPM_ID_PM8921_L6_0,
+	MSM_RPM_ID_PM8921_L6_1,
+	MSM_RPM_ID_PM8921_L7_0,
+	MSM_RPM_ID_PM8921_L7_1,
+	MSM_RPM_ID_PM8921_L8_0,
+	MSM_RPM_ID_PM8921_L8_1,
+	MSM_RPM_ID_PM8921_L9_0,
+	MSM_RPM_ID_PM8921_L9_1,
+	MSM_RPM_ID_PM8921_L10_0,
+	MSM_RPM_ID_PM8921_L10_1,
+	MSM_RPM_ID_PM8921_L11_0,
+	MSM_RPM_ID_PM8921_L11_1,
+	MSM_RPM_ID_PM8921_L12_0,
+	MSM_RPM_ID_PM8921_L12_1,
+	MSM_RPM_ID_PM8921_L13_0,
+	MSM_RPM_ID_PM8921_L13_1,
+	MSM_RPM_ID_PM8921_L14_0,
+	MSM_RPM_ID_PM8921_L14_1,
+	MSM_RPM_ID_PM8921_L15_0,
+	MSM_RPM_ID_PM8921_L15_1,
+	MSM_RPM_ID_PM8921_L16_0,
+	MSM_RPM_ID_PM8921_L16_1,
+	MSM_RPM_ID_PM8921_L17_0,
+	MSM_RPM_ID_PM8921_L17_1,
+	MSM_RPM_ID_PM8921_L18_0,
+	MSM_RPM_ID_PM8921_L18_1,
+	MSM_RPM_ID_PM8921_L19_0,
+	MSM_RPM_ID_PM8921_L19_1,
+	MSM_RPM_ID_PM8921_L20_0,
+	MSM_RPM_ID_PM8921_L20_1,
+	MSM_RPM_ID_PM8921_L21_0,
+	MSM_RPM_ID_PM8921_L21_1,
+	MSM_RPM_ID_PM8921_L22_0,
+	MSM_RPM_ID_PM8921_L22_1,
+	MSM_RPM_ID_PM8921_L23_0,
+	MSM_RPM_ID_PM8921_L23_1,
+	MSM_RPM_ID_PM8921_L24_0,
+	MSM_RPM_ID_PM8921_L24_1,
+	MSM_RPM_ID_PM8921_L25_0,
+	MSM_RPM_ID_PM8921_L25_1,
+	MSM_RPM_ID_PM8921_L26_0,
+	MSM_RPM_ID_PM8921_L26_1,
+	MSM_RPM_ID_PM8921_L27_0,
+	MSM_RPM_ID_PM8921_L27_1,
+	MSM_RPM_ID_PM8921_L28_0,
+	MSM_RPM_ID_PM8921_L28_1,
+	MSM_RPM_ID_PM8921_L29_0,
+	MSM_RPM_ID_PM8921_L29_1,
+	MSM_RPM_ID_PM8921_CLK1_0,
+	MSM_RPM_ID_PM8921_CLK1_1,
+	MSM_RPM_ID_PM8921_CLK2_0,
+	MSM_RPM_ID_PM8921_CLK2_1,
+	MSM_RPM_ID_PM8921_LVS1,
+	MSM_RPM_ID_PM8921_LVS2,
+	MSM_RPM_ID_PM8921_LVS3,
+	MSM_RPM_ID_PM8921_LVS4,
+	MSM_RPM_ID_PM8921_LVS5,
+	MSM_RPM_ID_PM8921_LVS6,
+	MSM_RPM_ID_PM8921_LVS7,
+	MSM_RPM_ID_NCP_0,
+	MSM_RPM_ID_NCP_1,
+	MSM_RPM_ID_CXO_BUFFERS,
+	MSM_RPM_ID_USB_OTG_SWITCH,
+	MSM_RPM_ID_HDMI_SWITCH,
+	MSM_RPM_ID_DDR_DMM_0,
+	MSM_RPM_ID_DDR_DMM_1,
+	MSM_RPM_ID_QDSS_CLK,
+
+	/* 8660 specific ids */
+	MSM_RPM_ID_TRIGGER_SET_FROM,
+	MSM_RPM_ID_TRIGGER_SET_TO,
+	MSM_RPM_ID_TRIGGER_SET_TRIGGER,
+
+	MSM_RPM_ID_TRIGGER_CLEAR_FROM,
+	MSM_RPM_ID_TRIGGER_CLEAR_TO,
+	MSM_RPM_ID_TRIGGER_CLEAR_TRIGGER,
+	MSM_RPM_ID_PLL_4,
+	MSM_RPM_ID_SMI_CLK,
+	MSM_RPM_ID_APPS_L2_CACHE_CTL,
+
+	/* pmic 8901 */
+	MSM_RPM_ID_SMPS0B_0,
+	MSM_RPM_ID_SMPS0B_1,
+	MSM_RPM_ID_SMPS1B_0,
+	MSM_RPM_ID_SMPS1B_1,
+	MSM_RPM_ID_SMPS2B_0,
+	MSM_RPM_ID_SMPS2B_1,
+	MSM_RPM_ID_SMPS3B_0,
+	MSM_RPM_ID_SMPS3B_1,
+	MSM_RPM_ID_SMPS4B_0,
+	MSM_RPM_ID_SMPS4B_1,
+	MSM_RPM_ID_LDO0B_0,
+	MSM_RPM_ID_LDO0B_1,
+	MSM_RPM_ID_LDO1B_0,
+	MSM_RPM_ID_LDO1B_1,
+	MSM_RPM_ID_LDO2B_0,
+	MSM_RPM_ID_LDO2B_1,
+	MSM_RPM_ID_LDO3B_0,
+	MSM_RPM_ID_LDO3B_1,
+	MSM_RPM_ID_LDO4B_0,
+	MSM_RPM_ID_LDO4B_1,
+	MSM_RPM_ID_LDO5B_0,
+	MSM_RPM_ID_LDO5B_1,
+	MSM_RPM_ID_LDO6B_0,
+	MSM_RPM_ID_LDO6B_1,
+	MSM_RPM_ID_LVS0B,
+	MSM_RPM_ID_LVS1B,
+	MSM_RPM_ID_LVS2B,
+	MSM_RPM_ID_LVS3B,
+	MSM_RPM_ID_MVS,
+
+	/* pmic 8058 */
+	MSM_RPM_ID_SMPS0_0,
+	MSM_RPM_ID_SMPS0_1,
+	MSM_RPM_ID_SMPS1_0,
+	MSM_RPM_ID_SMPS1_1,
+	MSM_RPM_ID_SMPS2_0,
+	MSM_RPM_ID_SMPS2_1,
+	MSM_RPM_ID_SMPS3_0,
+	MSM_RPM_ID_SMPS3_1,
+	MSM_RPM_ID_SMPS4_0,
+	MSM_RPM_ID_SMPS4_1,
+	MSM_RPM_ID_LDO0_0,
+	MSM_RPM_ID_LDO0_1,
+	MSM_RPM_ID_LDO1_0,
+	MSM_RPM_ID_LDO1_1,
+	MSM_RPM_ID_LDO2_0,
+	MSM_RPM_ID_LDO2_1,
+	MSM_RPM_ID_LDO3_0,
+	MSM_RPM_ID_LDO3_1,
+	MSM_RPM_ID_LDO4_0,
+	MSM_RPM_ID_LDO4_1,
+	MSM_RPM_ID_LDO5_0,
+	MSM_RPM_ID_LDO5_1,
+	MSM_RPM_ID_LDO6_0,
+	MSM_RPM_ID_LDO6_1,
+	MSM_RPM_ID_LDO7_0,
+	MSM_RPM_ID_LDO7_1,
+	MSM_RPM_ID_LDO8_0,
+	MSM_RPM_ID_LDO8_1,
+	MSM_RPM_ID_LDO9_0,
+	MSM_RPM_ID_LDO9_1,
+	MSM_RPM_ID_LDO10_0,
+	MSM_RPM_ID_LDO10_1,
+	MSM_RPM_ID_LDO11_0,
+	MSM_RPM_ID_LDO11_1,
+	MSM_RPM_ID_LDO12_0,
+	MSM_RPM_ID_LDO12_1,
+	MSM_RPM_ID_LDO13_0,
+	MSM_RPM_ID_LDO13_1,
+	MSM_RPM_ID_LDO14_0,
+	MSM_RPM_ID_LDO14_1,
+	MSM_RPM_ID_LDO15_0,
+	MSM_RPM_ID_LDO15_1,
+	MSM_RPM_ID_LDO16_0,
+	MSM_RPM_ID_LDO16_1,
+	MSM_RPM_ID_LDO17_0,
+	MSM_RPM_ID_LDO17_1,
+	MSM_RPM_ID_LDO18_0,
+	MSM_RPM_ID_LDO18_1,
+	MSM_RPM_ID_LDO19_0,
+	MSM_RPM_ID_LDO19_1,
+	MSM_RPM_ID_LDO20_0,
+	MSM_RPM_ID_LDO20_1,
+	MSM_RPM_ID_LDO21_0,
+	MSM_RPM_ID_LDO21_1,
+	MSM_RPM_ID_LDO22_0,
+	MSM_RPM_ID_LDO22_1,
+	MSM_RPM_ID_LDO23_0,
+	MSM_RPM_ID_LDO23_1,
+	MSM_RPM_ID_LDO24_0,
+	MSM_RPM_ID_LDO24_1,
+	MSM_RPM_ID_LDO25_0,
+	MSM_RPM_ID_LDO25_1,
+	MSM_RPM_ID_LVS0,
+	MSM_RPM_ID_LVS1,
+
+	/* 9615 specific */
+	MSM_RPM_ID_PM8018_S1_0,
+	MSM_RPM_ID_PM8018_S1_1,
+	MSM_RPM_ID_PM8018_S2_0,
+	MSM_RPM_ID_PM8018_S2_1,
+	MSM_RPM_ID_PM8018_S3_0,
+	MSM_RPM_ID_PM8018_S3_1,
+	MSM_RPM_ID_PM8018_S4_0,
+	MSM_RPM_ID_PM8018_S4_1,
+	MSM_RPM_ID_PM8018_S5_0,
+	MSM_RPM_ID_PM8018_S5_1,
+	MSM_RPM_ID_PM8018_L1_0,
+	MSM_RPM_ID_PM8018_L1_1,
+	MSM_RPM_ID_PM8018_L2_0,
+	MSM_RPM_ID_PM8018_L2_1,
+	MSM_RPM_ID_PM8018_L3_0,
+	MSM_RPM_ID_PM8018_L3_1,
+	MSM_RPM_ID_PM8018_L4_0,
+	MSM_RPM_ID_PM8018_L4_1,
+	MSM_RPM_ID_PM8018_L5_0,
+	MSM_RPM_ID_PM8018_L5_1,
+	MSM_RPM_ID_PM8018_L6_0,
+	MSM_RPM_ID_PM8018_L6_1,
+	MSM_RPM_ID_PM8018_L7_0,
+	MSM_RPM_ID_PM8018_L7_1,
+	MSM_RPM_ID_PM8018_L8_0,
+	MSM_RPM_ID_PM8018_L8_1,
+	MSM_RPM_ID_PM8018_L9_0,
+	MSM_RPM_ID_PM8018_L9_1,
+	MSM_RPM_ID_PM8018_L10_0,
+	MSM_RPM_ID_PM8018_L10_1,
+	MSM_RPM_ID_PM8018_L11_0,
+	MSM_RPM_ID_PM8018_L11_1,
+	MSM_RPM_ID_PM8018_L12_0,
+	MSM_RPM_ID_PM8018_L12_1,
+	MSM_RPM_ID_PM8018_L13_0,
+	MSM_RPM_ID_PM8018_L13_1,
+	MSM_RPM_ID_PM8018_L14_0,
+	MSM_RPM_ID_PM8018_L14_1,
+	MSM_RPM_ID_PM8018_LVS1,
+
+	/* 8930 specific */
+	MSM_RPM_ID_PM8038_S1_0,
+	MSM_RPM_ID_PM8038_S1_1,
+	MSM_RPM_ID_PM8038_S2_0,
+	MSM_RPM_ID_PM8038_S2_1,
+	MSM_RPM_ID_PM8038_S3_0,
+	MSM_RPM_ID_PM8038_S3_1,
+	MSM_RPM_ID_PM8038_S4_0,
+	MSM_RPM_ID_PM8038_S4_1,
+	MSM_RPM_ID_PM8038_S5_0,
+	MSM_RPM_ID_PM8038_S5_1,
+	MSM_RPM_ID_PM8038_S6_0,
+	MSM_RPM_ID_PM8038_S6_1,
+	MSM_RPM_ID_PM8038_L1_0,
+	MSM_RPM_ID_PM8038_L1_1,
+	MSM_RPM_ID_PM8038_L2_0,
+	MSM_RPM_ID_PM8038_L2_1,
+	MSM_RPM_ID_PM8038_L3_0,
+	MSM_RPM_ID_PM8038_L3_1,
+	MSM_RPM_ID_PM8038_L4_0,
+	MSM_RPM_ID_PM8038_L4_1,
+	MSM_RPM_ID_PM8038_L5_0,
+	MSM_RPM_ID_PM8038_L5_1,
+	MSM_RPM_ID_PM8038_L6_0,
+	MSM_RPM_ID_PM8038_L6_1,
+	MSM_RPM_ID_PM8038_L7_0,
+	MSM_RPM_ID_PM8038_L7_1,
+	MSM_RPM_ID_PM8038_L8_0,
+	MSM_RPM_ID_PM8038_L8_1,
+	MSM_RPM_ID_PM8038_L9_0,
+	MSM_RPM_ID_PM8038_L9_1,
+	MSM_RPM_ID_PM8038_L10_0,
+	MSM_RPM_ID_PM8038_L10_1,
+	MSM_RPM_ID_PM8038_L11_0,
+	MSM_RPM_ID_PM8038_L11_1,
+	MSM_RPM_ID_PM8038_L12_0,
+	MSM_RPM_ID_PM8038_L12_1,
+	MSM_RPM_ID_PM8038_L13_0,
+	MSM_RPM_ID_PM8038_L13_1,
+	MSM_RPM_ID_PM8038_L14_0,
+	MSM_RPM_ID_PM8038_L14_1,
+	MSM_RPM_ID_PM8038_L15_0,
+	MSM_RPM_ID_PM8038_L15_1,
+	MSM_RPM_ID_PM8038_L16_0,
+	MSM_RPM_ID_PM8038_L16_1,
+	MSM_RPM_ID_PM8038_L17_0,
+	MSM_RPM_ID_PM8038_L17_1,
+	MSM_RPM_ID_PM8038_L18_0,
+	MSM_RPM_ID_PM8038_L18_1,
+	MSM_RPM_ID_PM8038_L19_0,
+	MSM_RPM_ID_PM8038_L19_1,
+	MSM_RPM_ID_PM8038_L20_0,
+	MSM_RPM_ID_PM8038_L20_1,
+	MSM_RPM_ID_PM8038_L21_0,
+	MSM_RPM_ID_PM8038_L21_1,
+	MSM_RPM_ID_PM8038_L22_0,
+	MSM_RPM_ID_PM8038_L22_1,
+	MSM_RPM_ID_PM8038_L23_0,
+	MSM_RPM_ID_PM8038_L23_1,
+	MSM_RPM_ID_PM8038_L24_0,
+	MSM_RPM_ID_PM8038_L24_1,
+	MSM_RPM_ID_PM8038_L25_0,
+	MSM_RPM_ID_PM8038_L25_1,
+	MSM_RPM_ID_PM8038_L26_0,
+	MSM_RPM_ID_PM8038_L26_1,
+	MSM_RPM_ID_PM8038_L27_0,
+	MSM_RPM_ID_PM8038_L27_1,
+	MSM_RPM_ID_PM8038_CLK1_0,
+	MSM_RPM_ID_PM8038_CLK1_1,
+	MSM_RPM_ID_PM8038_CLK2_0,
+	MSM_RPM_ID_PM8038_CLK2_1,
+	MSM_RPM_ID_PM8038_LVS1,
+	MSM_RPM_ID_PM8038_LVS2,
+
+	/* 8064 specific */
+	MSM_RPM_ID_PM8821_S1_0,
+	MSM_RPM_ID_PM8821_S1_1,
+	MSM_RPM_ID_PM8821_S2_0,
+	MSM_RPM_ID_PM8821_S2_1,
+	MSM_RPM_ID_PM8821_L1_0,
+	MSM_RPM_ID_PM8821_L1_1,
+
+	MSM_RPM_ID_LAST,
+};
+
+enum {
+	MSM_RPM_STATUS_ID_VERSION_MAJOR,
+	MSM_RPM_STATUS_ID_VERSION_MINOR,
+	MSM_RPM_STATUS_ID_VERSION_BUILD,
+	MSM_RPM_STATUS_ID_SUPPORTED_RESOURCES_0,
+	MSM_RPM_STATUS_ID_SUPPORTED_RESOURCES_1,
+	MSM_RPM_STATUS_ID_SUPPORTED_RESOURCES_2,
+	MSM_RPM_STATUS_ID_RESERVED_SUPPORTED_RESOURCES_0,
+	MSM_RPM_STATUS_ID_SEQUENCE,
+	MSM_RPM_STATUS_ID_RPM_CTL,
+	MSM_RPM_STATUS_ID_CXO_CLK,
+	MSM_RPM_STATUS_ID_PXO_CLK,
+	MSM_RPM_STATUS_ID_APPS_FABRIC_CLK,
+	MSM_RPM_STATUS_ID_SYSTEM_FABRIC_CLK,
+	MSM_RPM_STATUS_ID_MM_FABRIC_CLK,
+	MSM_RPM_STATUS_ID_DAYTONA_FABRIC_CLK,
+	MSM_RPM_STATUS_ID_SFPB_CLK,
+	MSM_RPM_STATUS_ID_CFPB_CLK,
+	MSM_RPM_STATUS_ID_MMFPB_CLK,
+	MSM_RPM_STATUS_ID_EBI1_CLK,
+	MSM_RPM_STATUS_ID_APPS_FABRIC_CFG_HALT,
+	MSM_RPM_STATUS_ID_APPS_FABRIC_HALT =
+		MSM_RPM_STATUS_ID_APPS_FABRIC_CFG_HALT,
+	MSM_RPM_STATUS_ID_APPS_FABRIC_CFG_CLKMOD,
+	MSM_RPM_STATUS_ID_APPS_FABRIC_CLOCK_MODE =
+		MSM_RPM_STATUS_ID_APPS_FABRIC_CFG_CLKMOD,
+	MSM_RPM_STATUS_ID_APPS_FABRIC_CFG_IOCTL,
+	MSM_RPM_STATUS_ID_APPS_FABRIC_ARB,
+	MSM_RPM_STATUS_ID_SYS_FABRIC_CFG_HALT,
+	MSM_RPM_STATUS_ID_SYSTEM_FABRIC_HALT =
+		MSM_RPM_STATUS_ID_SYS_FABRIC_CFG_HALT,
+	MSM_RPM_STATUS_ID_SYS_FABRIC_CFG_CLKMOD,
+	MSM_RPM_STATUS_ID_SYSTEM_FABRIC_CLOCK_MODE =
+		MSM_RPM_STATUS_ID_SYS_FABRIC_CFG_CLKMOD,
+	MSM_RPM_STATUS_ID_SYS_FABRIC_CFG_IOCTL,
+	MSM_RPM_STATUS_ID_SYSTEM_FABRIC_ARB,
+	MSM_RPM_STATUS_ID_MMSS_FABRIC_CFG_HALT,
+	MSM_RPM_STATUS_ID_MM_FABRIC_HALT =
+		MSM_RPM_STATUS_ID_MMSS_FABRIC_CFG_HALT,
+	MSM_RPM_STATUS_ID_MMSS_FABRIC_CFG_CLKMOD,
+	MSM_RPM_STATUS_ID_MM_FABRIC_CLOCK_MODE =
+		MSM_RPM_STATUS_ID_MMSS_FABRIC_CFG_CLKMOD,
+	MSM_RPM_STATUS_ID_MMSS_FABRIC_CFG_IOCTL,
+	MSM_RPM_STATUS_ID_MM_FABRIC_ARB,
+	MSM_RPM_STATUS_ID_PM8921_S1_0,
+	MSM_RPM_STATUS_ID_PM8921_S1_1,
+	MSM_RPM_STATUS_ID_PM8921_S2_0,
+	MSM_RPM_STATUS_ID_PM8921_S2_1,
+	MSM_RPM_STATUS_ID_PM8921_S3_0,
+	MSM_RPM_STATUS_ID_PM8921_S3_1,
+	MSM_RPM_STATUS_ID_PM8921_S4_0,
+	MSM_RPM_STATUS_ID_PM8921_S4_1,
+	MSM_RPM_STATUS_ID_PM8921_S5_0,
+	MSM_RPM_STATUS_ID_PM8921_S5_1,
+	MSM_RPM_STATUS_ID_PM8921_S6_0,
+	MSM_RPM_STATUS_ID_PM8921_S6_1,
+	MSM_RPM_STATUS_ID_PM8921_S7_0,
+	MSM_RPM_STATUS_ID_PM8921_S7_1,
+	MSM_RPM_STATUS_ID_PM8921_S8_0,
+	MSM_RPM_STATUS_ID_PM8921_S8_1,
+	MSM_RPM_STATUS_ID_PM8921_L1_0,
+	MSM_RPM_STATUS_ID_PM8921_L1_1,
+	MSM_RPM_STATUS_ID_PM8921_L2_0,
+	MSM_RPM_STATUS_ID_PM8921_L2_1,
+	MSM_RPM_STATUS_ID_PM8921_L3_0,
+	MSM_RPM_STATUS_ID_PM8921_L3_1,
+	MSM_RPM_STATUS_ID_PM8921_L4_0,
+	MSM_RPM_STATUS_ID_PM8921_L4_1,
+	MSM_RPM_STATUS_ID_PM8921_L5_0,
+	MSM_RPM_STATUS_ID_PM8921_L5_1,
+	MSM_RPM_STATUS_ID_PM8921_L6_0,
+	MSM_RPM_STATUS_ID_PM8921_L6_1,
+	MSM_RPM_STATUS_ID_PM8921_L7_0,
+	MSM_RPM_STATUS_ID_PM8921_L7_1,
+	MSM_RPM_STATUS_ID_PM8921_L8_0,
+	MSM_RPM_STATUS_ID_PM8921_L8_1,
+	MSM_RPM_STATUS_ID_PM8921_L9_0,
+	MSM_RPM_STATUS_ID_PM8921_L9_1,
+	MSM_RPM_STATUS_ID_PM8921_L10_0,
+	MSM_RPM_STATUS_ID_PM8921_L10_1,
+	MSM_RPM_STATUS_ID_PM8921_L11_0,
+	MSM_RPM_STATUS_ID_PM8921_L11_1,
+	MSM_RPM_STATUS_ID_PM8921_L12_0,
+	MSM_RPM_STATUS_ID_PM8921_L12_1,
+	MSM_RPM_STATUS_ID_PM8921_L13_0,
+	MSM_RPM_STATUS_ID_PM8921_L13_1,
+	MSM_RPM_STATUS_ID_PM8921_L14_0,
+	MSM_RPM_STATUS_ID_PM8921_L14_1,
+	MSM_RPM_STATUS_ID_PM8921_L15_0,
+	MSM_RPM_STATUS_ID_PM8921_L15_1,
+	MSM_RPM_STATUS_ID_PM8921_L16_0,
+	MSM_RPM_STATUS_ID_PM8921_L16_1,
+	MSM_RPM_STATUS_ID_PM8921_L17_0,
+	MSM_RPM_STATUS_ID_PM8921_L17_1,
+	MSM_RPM_STATUS_ID_PM8921_L18_0,
+	MSM_RPM_STATUS_ID_PM8921_L18_1,
+	MSM_RPM_STATUS_ID_PM8921_L19_0,
+	MSM_RPM_STATUS_ID_PM8921_L19_1,
+	MSM_RPM_STATUS_ID_PM8921_L20_0,
+	MSM_RPM_STATUS_ID_PM8921_L20_1,
+	MSM_RPM_STATUS_ID_PM8921_L21_0,
+	MSM_RPM_STATUS_ID_PM8921_L21_1,
+	MSM_RPM_STATUS_ID_PM8921_L22_0,
+	MSM_RPM_STATUS_ID_PM8921_L22_1,
+	MSM_RPM_STATUS_ID_PM8921_L23_0,
+	MSM_RPM_STATUS_ID_PM8921_L23_1,
+	MSM_RPM_STATUS_ID_PM8921_L24_0,
+	MSM_RPM_STATUS_ID_PM8921_L24_1,
+	MSM_RPM_STATUS_ID_PM8921_L25_0,
+	MSM_RPM_STATUS_ID_PM8921_L25_1,
+	MSM_RPM_STATUS_ID_PM8921_L26_0,
+	MSM_RPM_STATUS_ID_PM8921_L26_1,
+	MSM_RPM_STATUS_ID_PM8921_L27_0,
+	MSM_RPM_STATUS_ID_PM8921_L27_1,
+	MSM_RPM_STATUS_ID_PM8921_L28_0,
+	MSM_RPM_STATUS_ID_PM8921_L28_1,
+	MSM_RPM_STATUS_ID_PM8921_L29_0,
+	MSM_RPM_STATUS_ID_PM8921_L29_1,
+	MSM_RPM_STATUS_ID_PM8921_CLK1_0,
+	MSM_RPM_STATUS_ID_PM8921_CLK1_1,
+	MSM_RPM_STATUS_ID_PM8921_CLK2_0,
+	MSM_RPM_STATUS_ID_PM8921_CLK2_1,
+	MSM_RPM_STATUS_ID_PM8921_LVS1,
+	MSM_RPM_STATUS_ID_PM8921_LVS2,
+	MSM_RPM_STATUS_ID_PM8921_LVS3,
+	MSM_RPM_STATUS_ID_PM8921_LVS4,
+	MSM_RPM_STATUS_ID_PM8921_LVS5,
+	MSM_RPM_STATUS_ID_PM8921_LVS6,
+	MSM_RPM_STATUS_ID_PM8921_LVS7,
+	MSM_RPM_STATUS_ID_NCP_0,
+	MSM_RPM_STATUS_ID_NCP_1,
+	MSM_RPM_STATUS_ID_CXO_BUFFERS,
+	MSM_RPM_STATUS_ID_USB_OTG_SWITCH,
+	MSM_RPM_STATUS_ID_HDMI_SWITCH,
+	MSM_RPM_STATUS_ID_DDR_DMM_0,
+	MSM_RPM_STATUS_ID_DDR_DMM_1,
+	MSM_RPM_STATUS_ID_EBI1_CH0_RANGE,
+	MSM_RPM_STATUS_ID_EBI1_CH1_RANGE,
+	MSM_RPM_STATUS_ID_QDSS_CLK,
+
+	/* 8660 Specific */
+	MSM_RPM_STATUS_ID_PLL_4,
+	MSM_RPM_STATUS_ID_SMI_CLK,
+	MSM_RPM_STATUS_ID_APPS_L2_CACHE_CTL,
+	MSM_RPM_STATUS_ID_SMPS0B_0,
+	MSM_RPM_STATUS_ID_SMPS0B_1,
+	MSM_RPM_STATUS_ID_SMPS1B_0,
+	MSM_RPM_STATUS_ID_SMPS1B_1,
+	MSM_RPM_STATUS_ID_SMPS2B_0,
+	MSM_RPM_STATUS_ID_SMPS2B_1,
+	MSM_RPM_STATUS_ID_SMPS3B_0,
+	MSM_RPM_STATUS_ID_SMPS3B_1,
+	MSM_RPM_STATUS_ID_SMPS4B_0,
+	MSM_RPM_STATUS_ID_SMPS4B_1,
+	MSM_RPM_STATUS_ID_LDO0B_0,
+	MSM_RPM_STATUS_ID_LDO0B_1,
+	MSM_RPM_STATUS_ID_LDO1B_0,
+	MSM_RPM_STATUS_ID_LDO1B_1,
+	MSM_RPM_STATUS_ID_LDO2B_0,
+	MSM_RPM_STATUS_ID_LDO2B_1,
+	MSM_RPM_STATUS_ID_LDO3B_0,
+	MSM_RPM_STATUS_ID_LDO3B_1,
+	MSM_RPM_STATUS_ID_LDO4B_0,
+	MSM_RPM_STATUS_ID_LDO4B_1,
+	MSM_RPM_STATUS_ID_LDO5B_0,
+	MSM_RPM_STATUS_ID_LDO5B_1,
+	MSM_RPM_STATUS_ID_LDO6B_0,
+	MSM_RPM_STATUS_ID_LDO6B_1,
+	MSM_RPM_STATUS_ID_LVS0B,
+	MSM_RPM_STATUS_ID_LVS1B,
+	MSM_RPM_STATUS_ID_LVS2B,
+	MSM_RPM_STATUS_ID_LVS3B,
+	MSM_RPM_STATUS_ID_MVS,
+	MSM_RPM_STATUS_ID_SMPS0_0,
+	MSM_RPM_STATUS_ID_SMPS0_1,
+	MSM_RPM_STATUS_ID_SMPS1_0,
+	MSM_RPM_STATUS_ID_SMPS1_1,
+	MSM_RPM_STATUS_ID_SMPS2_0,
+	MSM_RPM_STATUS_ID_SMPS2_1,
+	MSM_RPM_STATUS_ID_SMPS3_0,
+	MSM_RPM_STATUS_ID_SMPS3_1,
+	MSM_RPM_STATUS_ID_SMPS4_0,
+	MSM_RPM_STATUS_ID_SMPS4_1,
+	MSM_RPM_STATUS_ID_LDO0_0,
+	MSM_RPM_STATUS_ID_LDO0_1,
+	MSM_RPM_STATUS_ID_LDO1_0,
+	MSM_RPM_STATUS_ID_LDO1_1,
+	MSM_RPM_STATUS_ID_LDO2_0,
+	MSM_RPM_STATUS_ID_LDO2_1,
+	MSM_RPM_STATUS_ID_LDO3_0,
+	MSM_RPM_STATUS_ID_LDO3_1,
+	MSM_RPM_STATUS_ID_LDO4_0,
+	MSM_RPM_STATUS_ID_LDO4_1,
+	MSM_RPM_STATUS_ID_LDO5_0,
+	MSM_RPM_STATUS_ID_LDO5_1,
+	MSM_RPM_STATUS_ID_LDO6_0,
+	MSM_RPM_STATUS_ID_LDO6_1,
+	MSM_RPM_STATUS_ID_LDO7_0,
+	MSM_RPM_STATUS_ID_LDO7_1,
+	MSM_RPM_STATUS_ID_LDO8_0,
+	MSM_RPM_STATUS_ID_LDO8_1,
+	MSM_RPM_STATUS_ID_LDO9_0,
+	MSM_RPM_STATUS_ID_LDO9_1,
+	MSM_RPM_STATUS_ID_LDO10_0,
+	MSM_RPM_STATUS_ID_LDO10_1,
+	MSM_RPM_STATUS_ID_LDO11_0,
+	MSM_RPM_STATUS_ID_LDO11_1,
+	MSM_RPM_STATUS_ID_LDO12_0,
+	MSM_RPM_STATUS_ID_LDO12_1,
+	MSM_RPM_STATUS_ID_LDO13_0,
+	MSM_RPM_STATUS_ID_LDO13_1,
+	MSM_RPM_STATUS_ID_LDO14_0,
+	MSM_RPM_STATUS_ID_LDO14_1,
+	MSM_RPM_STATUS_ID_LDO15_0,
+	MSM_RPM_STATUS_ID_LDO15_1,
+	MSM_RPM_STATUS_ID_LDO16_0,
+	MSM_RPM_STATUS_ID_LDO16_1,
+	MSM_RPM_STATUS_ID_LDO17_0,
+	MSM_RPM_STATUS_ID_LDO17_1,
+	MSM_RPM_STATUS_ID_LDO18_0,
+	MSM_RPM_STATUS_ID_LDO18_1,
+	MSM_RPM_STATUS_ID_LDO19_0,
+	MSM_RPM_STATUS_ID_LDO19_1,
+	MSM_RPM_STATUS_ID_LDO20_0,
+	MSM_RPM_STATUS_ID_LDO20_1,
+	MSM_RPM_STATUS_ID_LDO21_0,
+	MSM_RPM_STATUS_ID_LDO21_1,
+	MSM_RPM_STATUS_ID_LDO22_0,
+	MSM_RPM_STATUS_ID_LDO22_1,
+	MSM_RPM_STATUS_ID_LDO23_0,
+	MSM_RPM_STATUS_ID_LDO23_1,
+	MSM_RPM_STATUS_ID_LDO24_0,
+	MSM_RPM_STATUS_ID_LDO24_1,
+	MSM_RPM_STATUS_ID_LDO25_0,
+	MSM_RPM_STATUS_ID_LDO25_1,
+	MSM_RPM_STATUS_ID_LVS0,
+	MSM_RPM_STATUS_ID_LVS1,
+
+	/* 9615 Specific */
+	MSM_RPM_STATUS_ID_PM8018_S1_0,
+	MSM_RPM_STATUS_ID_PM8018_S1_1,
+	MSM_RPM_STATUS_ID_PM8018_S2_0,
+	MSM_RPM_STATUS_ID_PM8018_S2_1,
+	MSM_RPM_STATUS_ID_PM8018_S3_0,
+	MSM_RPM_STATUS_ID_PM8018_S3_1,
+	MSM_RPM_STATUS_ID_PM8018_S4_0,
+	MSM_RPM_STATUS_ID_PM8018_S4_1,
+	MSM_RPM_STATUS_ID_PM8018_S5_0,
+	MSM_RPM_STATUS_ID_PM8018_S5_1,
+	MSM_RPM_STATUS_ID_PM8018_L1_0,
+	MSM_RPM_STATUS_ID_PM8018_L1_1,
+	MSM_RPM_STATUS_ID_PM8018_L2_0,
+	MSM_RPM_STATUS_ID_PM8018_L2_1,
+	MSM_RPM_STATUS_ID_PM8018_L3_0,
+	MSM_RPM_STATUS_ID_PM8018_L3_1,
+	MSM_RPM_STATUS_ID_PM8018_L4_0,
+	MSM_RPM_STATUS_ID_PM8018_L4_1,
+	MSM_RPM_STATUS_ID_PM8018_L5_0,
+	MSM_RPM_STATUS_ID_PM8018_L5_1,
+	MSM_RPM_STATUS_ID_PM8018_L6_0,
+	MSM_RPM_STATUS_ID_PM8018_L6_1,
+	MSM_RPM_STATUS_ID_PM8018_L7_0,
+	MSM_RPM_STATUS_ID_PM8018_L7_1,
+	MSM_RPM_STATUS_ID_PM8018_L8_0,
+	MSM_RPM_STATUS_ID_PM8018_L8_1,
+	MSM_RPM_STATUS_ID_PM8018_L9_0,
+	MSM_RPM_STATUS_ID_PM8018_L9_1,
+	MSM_RPM_STATUS_ID_PM8018_L10_0,
+	MSM_RPM_STATUS_ID_PM8018_L10_1,
+	MSM_RPM_STATUS_ID_PM8018_L11_0,
+	MSM_RPM_STATUS_ID_PM8018_L11_1,
+	MSM_RPM_STATUS_ID_PM8018_L12_0,
+	MSM_RPM_STATUS_ID_PM8018_L12_1,
+	MSM_RPM_STATUS_ID_PM8018_L13_0,
+	MSM_RPM_STATUS_ID_PM8018_L13_1,
+	MSM_RPM_STATUS_ID_PM8018_L14_0,
+	MSM_RPM_STATUS_ID_PM8018_L14_1,
+	MSM_RPM_STATUS_ID_PM8018_LVS1,
+
+	/* 8930 specific */
+	MSM_RPM_STATUS_ID_PM8038_S1_0,
+	MSM_RPM_STATUS_ID_PM8038_S1_1,
+	MSM_RPM_STATUS_ID_PM8038_S2_0,
+	MSM_RPM_STATUS_ID_PM8038_S2_1,
+	MSM_RPM_STATUS_ID_PM8038_S3_0,
+	MSM_RPM_STATUS_ID_PM8038_S3_1,
+	MSM_RPM_STATUS_ID_PM8038_S4_0,
+	MSM_RPM_STATUS_ID_PM8038_S4_1,
+	MSM_RPM_STATUS_ID_PM8038_S5_0,
+	MSM_RPM_STATUS_ID_PM8038_S5_1,
+	MSM_RPM_STATUS_ID_PM8038_S6_0,
+	MSM_RPM_STATUS_ID_PM8038_S6_1,
+	MSM_RPM_STATUS_ID_PM8038_L1_0,
+	MSM_RPM_STATUS_ID_PM8038_L1_1,
+	MSM_RPM_STATUS_ID_PM8038_L2_0,
+	MSM_RPM_STATUS_ID_PM8038_L2_1,
+	MSM_RPM_STATUS_ID_PM8038_L3_0,
+	MSM_RPM_STATUS_ID_PM8038_L3_1,
+	MSM_RPM_STATUS_ID_PM8038_L4_0,
+	MSM_RPM_STATUS_ID_PM8038_L4_1,
+	MSM_RPM_STATUS_ID_PM8038_L5_0,
+	MSM_RPM_STATUS_ID_PM8038_L5_1,
+	MSM_RPM_STATUS_ID_PM8038_L6_0,
+	MSM_RPM_STATUS_ID_PM8038_L6_1,
+	MSM_RPM_STATUS_ID_PM8038_L7_0,
+	MSM_RPM_STATUS_ID_PM8038_L7_1,
+	MSM_RPM_STATUS_ID_PM8038_L8_0,
+	MSM_RPM_STATUS_ID_PM8038_L8_1,
+	MSM_RPM_STATUS_ID_PM8038_L9_0,
+	MSM_RPM_STATUS_ID_PM8038_L9_1,
+	MSM_RPM_STATUS_ID_PM8038_L10_0,
+	MSM_RPM_STATUS_ID_PM8038_L10_1,
+	MSM_RPM_STATUS_ID_PM8038_L11_0,
+	MSM_RPM_STATUS_ID_PM8038_L11_1,
+	MSM_RPM_STATUS_ID_PM8038_L12_0,
+	MSM_RPM_STATUS_ID_PM8038_L12_1,
+	MSM_RPM_STATUS_ID_PM8038_L13_0,
+	MSM_RPM_STATUS_ID_PM8038_L13_1,
+	MSM_RPM_STATUS_ID_PM8038_L14_0,
+	MSM_RPM_STATUS_ID_PM8038_L14_1,
+	MSM_RPM_STATUS_ID_PM8038_L15_0,
+	MSM_RPM_STATUS_ID_PM8038_L15_1,
+	MSM_RPM_STATUS_ID_PM8038_L16_0,
+	MSM_RPM_STATUS_ID_PM8038_L16_1,
+	MSM_RPM_STATUS_ID_PM8038_L17_0,
+	MSM_RPM_STATUS_ID_PM8038_L17_1,
+	MSM_RPM_STATUS_ID_PM8038_L18_0,
+	MSM_RPM_STATUS_ID_PM8038_L18_1,
+	MSM_RPM_STATUS_ID_PM8038_L19_0,
+	MSM_RPM_STATUS_ID_PM8038_L19_1,
+	MSM_RPM_STATUS_ID_PM8038_L20_0,
+	MSM_RPM_STATUS_ID_PM8038_L20_1,
+	MSM_RPM_STATUS_ID_PM8038_L21_0,
+	MSM_RPM_STATUS_ID_PM8038_L21_1,
+	MSM_RPM_STATUS_ID_PM8038_L22_0,
+	MSM_RPM_STATUS_ID_PM8038_L22_1,
+	MSM_RPM_STATUS_ID_PM8038_L23_0,
+	MSM_RPM_STATUS_ID_PM8038_L23_1,
+	MSM_RPM_STATUS_ID_PM8038_L24_0,
+	MSM_RPM_STATUS_ID_PM8038_L24_1,
+	MSM_RPM_STATUS_ID_PM8038_L25_0,
+	MSM_RPM_STATUS_ID_PM8038_L25_1,
+	MSM_RPM_STATUS_ID_PM8038_L26_0,
+	MSM_RPM_STATUS_ID_PM8038_L26_1,
+	MSM_RPM_STATUS_ID_PM8038_L27_0,
+	MSM_RPM_STATUS_ID_PM8038_L27_1,
+	MSM_RPM_STATUS_ID_PM8038_CLK1_0,
+	MSM_RPM_STATUS_ID_PM8038_CLK1_1,
+	MSM_RPM_STATUS_ID_PM8038_CLK2_0,
+	MSM_RPM_STATUS_ID_PM8038_CLK2_1,
+	MSM_RPM_STATUS_ID_PM8038_LVS1,
+	MSM_RPM_STATUS_ID_PM8038_LVS2,
+
+	/* 8064 specific */
+	MSM_RPM_STATUS_ID_PM8821_S1_0,
+	MSM_RPM_STATUS_ID_PM8821_S1_1,
+	MSM_RPM_STATUS_ID_PM8821_S2_0,
+	MSM_RPM_STATUS_ID_PM8821_S2_1,
+	MSM_RPM_STATUS_ID_PM8821_L1_0,
+	MSM_RPM_STATUS_ID_PM8821_L1_1,
+
+	MSM_RPM_STATUS_ID_LAST,
+};
+
 static inline uint32_t msm_rpm_get_ctx_mask(unsigned int ctx)
 {
 	return 1UL << ctx;
 }
 
-#define MSM_RPM_SEL_MASK_SIZE  (MSM_RPM_SEL_LAST / 32 + 1)
-
 static inline unsigned int msm_rpm_get_sel_mask_reg(unsigned int sel)
 {
 	return sel / 32;
@@ -69,7 +850,7 @@
 struct msm_rpm_notification {
 	struct list_head list;  /* reserved for RPM use */
 	struct semaphore sem;
-	uint32_t sel_masks[MSM_RPM_SEL_MASK_SIZE];  /* reserved for RPM use */
+	uint32_t sel_masks[SEL_MASK_SIZE];  /* reserved for RPM use */
 };
 
 struct msm_rpm_map_data {
@@ -78,22 +859,41 @@
 	uint32_t count;
 };
 
-#define MSM_RPM_MAP(i, s, c) { \
-	.id = MSM_RPM_ID_##i, .sel = MSM_RPM_SEL_##s, .count = c }
+#define MSM_RPM_MAP(t, i, s, c) \
+	[MSM_RPM_ID_##i] = \
+	{\
+		.id = MSM_RPM_##t##_ID_##i, \
+		.sel = MSM_RPM_##t##_SEL_##s, \
+		.count = c, \
+	}
+
+#define MSM_RPM_STATUS_ID_VALID BIT(31)
+
+#define MSM_RPM_STATUS_ID_MAP(t, i) \
+	[MSM_RPM_STATUS_ID_## i] = (MSM_RPM_##t##_STATUS_ID_##i \
+					| MSM_RPM_STATUS_ID_VALID)
+
+#define MSM_RPM_CTRL_MAP(t, i) \
+	[MSM_RPM_CTRL_##i] = MSM_RPM_##t##_CTRL_##i
 
 
 struct msm_rpm_platform_data {
 	void __iomem *reg_base_addrs[MSM_RPM_PAGE_COUNT];
-
 	unsigned int irq_ack;
-	unsigned int irq_err;
-	unsigned int irq_vmpm;
-	void *msm_apps_ipc_rpm_reg;
-	unsigned int msm_apps_ipc_rpm_val;
+	void *ipc_rpm_reg;
+	unsigned int ipc_rpm_val;
+	struct msm_rpm_map_data target_id[MSM_RPM_ID_LAST];
+	unsigned int target_status[MSM_RPM_STATUS_ID_LAST];
+	unsigned int target_ctrl_id[MSM_RPM_CTRL_LAST];
+	unsigned int sel_invalidate, sel_notification, sel_last;
+	unsigned int ver[3];
 };
 
-extern struct msm_rpm_map_data rpm_map_data[];
-extern unsigned int rpm_map_data_size;
+extern struct msm_rpm_platform_data msm8660_rpm_data;
+extern struct msm_rpm_platform_data msm8960_rpm_data;
+extern struct msm_rpm_platform_data msm9615_rpm_data;
+extern struct msm_rpm_platform_data msm8930_rpm_data;
+extern struct msm_rpm_platform_data apq8064_rpm_data;
 
 int msm_rpm_local_request_is_outstanding(void);
 int msm_rpm_get_status(struct msm_rpm_iv_pair *status, int count);
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/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index a06b9ae..e1d4459 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.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
@@ -62,6 +62,7 @@
 	MSM_CPU_9615,
 	MSM_CPU_COPPER,
 	MSM_CPU_8627,
+	MSM_CPU_8625,
 };
 
 enum msm_cpu socinfo_get_msm_cpu(void);
@@ -266,4 +267,17 @@
 	return 0;
 #endif
 }
+
+static inline int cpu_is_msm8625(void)
+{
+#ifdef CONFIG_ARCH_MSM8625
+	enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+	BUG_ON(cpu == MSM_CPU_UNKNOWN);
+	return cpu == MSM_CPU_8625;
+#else
+	return 0;
+#endif
+}
+
 #endif
diff --git a/arch/arm/mach-msm/include/mach/uncompress.h b/arch/arm/mach-msm/include/mach/uncompress.h
index 7560dc2..d46bd77 100644
--- a/arch/arm/mach-msm/include/mach/uncompress.h
+++ b/arch/arm/mach-msm/include/mach/uncompress.h
@@ -1,6 +1,7 @@
 /* arch/arm/mach-msm/include/mach/uncompress.h
  *
  * Copyright (C) 2007 Google, Inc.
+ * 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
@@ -34,18 +35,18 @@
 	 * Wait for TX_READY to be set; but skip it if we have a
 	 * TX underrun.
 	 */
-	if (!(__raw_readl(base + UARTDM_SR_OFFSET) & 0x08))
-		while (!(__raw_readl(base + UARTDM_ISR_OFFSET) & 0x80))
+	if (!(__raw_readl_no_log(base + UARTDM_SR_OFFSET) & 0x08))
+		while (!(__raw_readl_no_log(base + UARTDM_ISR_OFFSET) & 0x80))
 			cpu_relax();
 
-	__raw_writel(0x300, base + UARTDM_CR_OFFSET);
-	__raw_writel(0x1, base + UARTDM_NCF_TX_OFFSET);
-	__raw_writel(c, base + UARTDM_TF_OFFSET);
+	__raw_writel_no_log(0x300, base + UARTDM_CR_OFFSET);
+	__raw_writel_no_log(0x1, base + UARTDM_NCF_TX_OFFSET);
+	__raw_writel_no_log(c, base + UARTDM_TF_OFFSET);
 #else
 	/* Wait for TX_READY to be set */
-	while (!(__raw_readl(base + 0x08) & 0x04))
+	while (!(__raw_readl_no_log(base + 0x08) & 0x04))
 		cpu_relax();
-	__raw_writel(c, base + 0x0c);
+	__raw_writel_no_log(c, base + 0x0c);
 #endif
 #endif
 }
diff --git a/arch/arm/mach-msm/include/mach/usb_bridge.h b/arch/arm/mach-msm/include/mach/usb_bridge.h
index effa395..1a1c23b 100644
--- a/arch/arm/mach-msm/include/mach/usb_bridge.h
+++ b/arch/arm/mach-msm/include/mach/usb_bridge.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
@@ -49,6 +49,43 @@
 	struct bridge_ops ops;
 };
 
+/**
+ * timestamp_info: stores timestamp info for skb life cycle during data
+ * transfer for tethered rmnet/DUN.
+ * @created: stores timestamp at the time of creation of SKB.
+ * @rx_queued: stores timestamp when SKB queued to HW to receive
+ * data.
+ * @rx_done: stores timestamp when skb queued to h/w is completed.
+ * @rx_done_sent: stores timestamp when SKB is sent from gadget rmnet/DUN
+ * driver to bridge rmnet/DUN driver or vice versa.
+ * @tx_queued: stores timestamp when SKB is queued to send data.
+ *
+ * note that size of this struct shouldnt exceed 48bytes that's the max skb->cb
+ * holds.
+ */
+struct timestamp_info {
+	struct data_bridge	*dev;
+
+	unsigned int		created;
+	unsigned int		rx_queued;
+	unsigned int		rx_done;
+	unsigned int		rx_done_sent;
+	unsigned int		tx_queued;
+};
+
+/* Maximum timestamp message length */
+#define DBG_DATA_MSG	128UL
+
+/* Maximum timestamp messages */
+#define DBG_DATA_MAX	32UL
+
+/* timestamp buffer descriptor */
+struct timestamp_buf {
+	char		(buf[DBG_DATA_MAX])[DBG_DATA_MSG];   /* buffer */
+	unsigned	idx;   /* index */
+	rwlock_t	lck;   /* lock */
+};
+
 #if defined(CONFIG_USB_QCOM_MDM_BRIDGE) ||	\
 	defined(CONFIG_USB_QCOM_MDM_BRIDGE_MODULE)
 
@@ -115,4 +152,5 @@
 }
 
 #endif
+
 #endif
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 9622a4c..830db1f 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -3,7 +3,7 @@
  * MSM7K, QSD io support
  *
  * 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
@@ -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
@@ -278,6 +278,8 @@
 		.length =   MSM_SHARED_RAM_SIZE,
 		.type =     MT_DEVICE,
 	},
+	MSM_CHIP_DEVICE(QFPROM, APQ8064),
+	MSM_CHIP_DEVICE(SIC_NON_SECURE, APQ8064),
 };
 
 void __init msm_map_apq8064_io(void)
@@ -396,6 +398,47 @@
 }
 #endif /* CONFIG_ARCH_MSM9615 */
 
+#ifdef CONFIG_ARCH_MSM8625
+static struct map_desc msm8625_io_desc[] __initdata = {
+	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_CHIP_DEVICE(DEBUG_UART, MSM7XXX),
+#endif
+#ifdef CONFIG_CACHE_L2X0
+	{
+		.virtual = (unsigned long) MSM_L2CC_BASE,
+		.pfn	 = __phys_to_pfn(MSM7XXX_L2CC_PHYS),
+		.length	 = MSM7XXX_L2CC_SIZE,
+		.type	 = MT_DEVICE,
+	},
+#endif
+	{
+		.virtual = (unsigned long) MSM_SHARED_RAM_BASE,
+		.length	 = MSM_SHARED_RAM_SIZE,
+		.type	 = MT_DEVICE,
+	},
+};
+
+void __init msm_map_msm8625_io(void)
+{
+	msm_map_io(msm8625_io_desc, ARRAY_SIZE(msm8625_io_desc));
+}
+#else
+void __init msm_map_msm8625_io(void) { return; }
+#endif /* CONFIG_ARCH_MSM8625 */
+
 void __iomem *
 __msm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
 {
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index 093d044..6e8c99e 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.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
@@ -27,6 +27,7 @@
 #include <net/sock.h>
 
 #include <mach/peripheral-loader.h>
+#include <mach/socinfo.h>
 
 #include "ipc_router.h"
 
@@ -46,11 +47,18 @@
 
 static void *msm_ipc_router_load_modem(void)
 {
-	void *pil;
+	void *pil = NULL;
 	int rc;
 
-	pil = pil_get("modem");
-	if (IS_ERR(pil)) {
+	/* Load GNSS for Standalone 8064 but not for Fusion 3 */
+	if (cpu_is_apq8064()) {
+		if (socinfo_get_platform_subtype() == 0x0)
+			pil = pil_get("gss");
+	} else {
+		pil = pil_get("modem");
+	}
+
+	if (IS_ERR(pil) || !pil) {
 		pr_debug("%s: modem load failed\n", __func__);
 		pil = NULL;
 	} else {
diff --git a/arch/arm/mach-msm/lpass-8660.c b/arch/arm/mach-msm/lpass-8660.c
index 36b8dcc..ff08eff 100644
--- a/arch/arm/mach-msm/lpass-8660.c
+++ b/arch/arm/mach-msm/lpass-8660.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
@@ -39,6 +39,7 @@
 static void *q6_ramdump_dev;
 static void q6_fatal_fn(struct work_struct *);
 static DECLARE_WORK(q6_fatal_work, q6_fatal_fn);
+static void __iomem *q6_wakeup_intr;
 
 static void q6_fatal_fn(struct work_struct *work)
 {
@@ -50,20 +51,16 @@
 static void send_q6_nmi(void)
 {
 	/* Send NMI to QDSP6 via an SCM call. */
-	uint32_t cmd = 0x1;
-	void __iomem *q6_wakeup_intr;
-
-	scm_call(SCM_SVC_UTIL, SCM_Q6_NMI_CMD,
-	&cmd, sizeof(cmd), NULL, 0);
+	scm_call_atomic1(SCM_SVC_UTIL, SCM_Q6_NMI_CMD, 0x1);
 
 	/* Wakeup the Q6 */
-	q6_wakeup_intr = ioremap_nocache(Q6SS_SOFT_INTR_WAKEUP, 8);
-	writel_relaxed(0x2000, q6_wakeup_intr);
-	iounmap(q6_wakeup_intr);
-	mb();
+	if (q6_wakeup_intr)
+		writel_relaxed(0x2000, q6_wakeup_intr);
+	else
+		pr_warn("lpass-8660: Unable to send wakeup interrupt to Q6.\n");
 
 	/* Q6 requires atleast 100ms to dump caches etc.*/
-	msleep(100);
+	mdelay(100);
 
 	pr_info("subsystem-fatal-8x60: Q6 NMI was sent.\n");
 }
@@ -133,6 +130,7 @@
 
 static void __exit lpass_fatal_exit(void)
 {
+	iounmap(q6_wakeup_intr);
 	free_irq(LPASS_Q6SS_WDOG_EXPIRED, NULL);
 }
 
@@ -156,6 +154,11 @@
 		goto out;
 	}
 
+	q6_wakeup_intr = ioremap_nocache(Q6SS_SOFT_INTR_WAKEUP, 8);
+
+	if (!q6_wakeup_intr)
+		pr_warn("lpass-8660: Unable to ioremap q6 wakeup address.");
+
 	ret = ssr_register_subsystem(&subsys_8x60_q6);
 out:
 	return ret;
diff --git a/arch/arm/mach-msm/lpass-8960.c b/arch/arm/mach-msm/lpass-8960.c
index 11b9092..5eccf06 100644
--- a/arch/arm/mach-msm/lpass-8960.c
+++ b/arch/arm/mach-msm/lpass-8960.c
@@ -66,6 +66,28 @@
 	.notifier_call = riva_notifier_cb,
 };
 
+static int modem_notifier_cb(struct notifier_block *this, unsigned long code,
+								void *ss_handle)
+{
+	int ret;
+	switch (code) {
+	case SUBSYS_BEFORE_SHUTDOWN:
+		pr_debug("%s: M-Notify: Shutdown started\n", __func__);
+		ret = sysmon_send_event(SYSMON_SS_LPASS, "modem",
+				SUBSYS_BEFORE_SHUTDOWN);
+		if (ret < 0)
+			pr_err("%s: sysmon_send_event error %d", __func__,
+				ret);
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+static void *ssr_modem_notif_hdle;
+static struct notifier_block mnb = {
+	.notifier_call = modem_notifier_cb,
+};
+
 static void lpass_fatal_fn(struct work_struct *work)
 {
 	pr_err("%s %s: Watchdog bite received from Q6!\n", MODULE_NAME,
@@ -213,6 +235,18 @@
 		goto out;
 	}
 
+	ssr_modem_notif_hdle = subsys_notif_register_notifier("modem",
+							&mnb);
+	if (IS_ERR(ssr_modem_notif_hdle) < 0) {
+		ret = PTR_ERR(ssr_modem_notif_hdle);
+		pr_err("%s: subsys_register_notifier for Modem: err = %d\n",
+			__func__, ret);
+		subsys_notif_unregister_notifier(ssr_notif_hdle, &rnb);
+		iounmap(q6_wakeup_intr);
+		free_irq(LPASS_Q6SS_WDOG_EXPIRED, NULL);
+		goto out;
+	}
+
 	pr_info("%s: lpass SSR driver init'ed.\n", __func__);
 out:
 	return ret;
@@ -221,6 +255,7 @@
 static void __exit lpass_fatal_exit(void)
 {
 	subsys_notif_unregister_notifier(ssr_notif_hdle, &rnb);
+	subsys_notif_unregister_notifier(ssr_modem_notif_hdle, &mnb);
 	iounmap(q6_wakeup_intr);
 	free_irq(LPASS_Q6SS_WDOG_EXPIRED, NULL);
 }
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index bf4e6a4..5db8b40 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.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
@@ -33,7 +33,6 @@
 #include <asm/mach-types.h>
 #include <asm/uaccess.h>
 #include <mach/mdm2.h>
-#include <mach/mdm-peripheral.h>
 #include <mach/restart.h>
 #include <mach/subsystem_notif.h>
 #include <mach/subsystem_restart.h>
@@ -46,38 +45,63 @@
 #define MDM_MODEM_TIMEOUT	6000
 #define MDM_HOLD_TIME		4000
 #define MDM_MODEM_DELTA		100
-#define IFLINE_UP			1
-#define IFLINE_DOWN			0
 
 static int mdm_debug_on;
-static struct mdm_callbacks mdm_cb;
+static int first_power_on = 1;
+static int hsic_peripheral_status = 1;
+static DEFINE_MUTEX(hsic_status_lock);
 
-#define MDM_DBG(...)	do { if (mdm_debug_on) \
-					pr_info(__VA_ARGS__); \
-			} while (0);
+static void mdm_peripheral_connect(struct mdm_modem_drv *mdm_drv)
+{
+	mutex_lock(&hsic_status_lock);
+	if (hsic_peripheral_status)
+		goto out;
+	if (mdm_drv->pdata->peripheral_platform_device)
+		platform_device_add(mdm_drv->pdata->peripheral_platform_device);
+	hsic_peripheral_status = 1;
+out:
+	mutex_unlock(&hsic_status_lock);
+}
+
+static void mdm_peripheral_disconnect(struct mdm_modem_drv *mdm_drv)
+{
+	mutex_lock(&hsic_status_lock);
+	if (!hsic_peripheral_status)
+		goto out;
+	if (mdm_drv->pdata->peripheral_platform_device)
+		platform_device_del(mdm_drv->pdata->peripheral_platform_device);
+	hsic_peripheral_status = 0;
+out:
+	mutex_unlock(&hsic_status_lock);
+}
 
 static void power_on_mdm(struct mdm_modem_drv *mdm_drv)
 {
-	peripheral_disconnect();
+	mdm_peripheral_disconnect(mdm_drv);
 
-	/* Pull both ERR_FATAL and RESET low */
-	MDM_DBG("Pulling PWR and RESET gpio's low\n");
+	/* Pull RESET gpio low and wait for it to settle. */
+	pr_debug("Pulling RESET gpio low\n");
 	gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 0);
-	gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 0);
-	/* Wait for them to settle. */
 	usleep(1000);
 
 	/* Deassert RESET first and wait for ir to settle. */
-	MDM_DBG("%s: Pulling RESET gpio high\n", __func__);
+	pr_debug("%s: Pulling RESET gpio high\n", __func__);
 	gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 1);
 	usleep(1000);
 
-	/* Pull PWR gpio high and wait for it to settle. */
-	MDM_DBG("%s: Powering on mdm modem\n", __func__);
-	gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 1);
-	usleep(1000);
-
-	peripheral_connect();
+	/* Pull PWR gpio high and wait for it to settle, but only
+	 * the first time the mdm is powered up.
+	 * Some targets do not use ap2mdm_kpdpwr_n_gpio.
+	 */
+	if (first_power_on) {
+		if (mdm_drv->ap2mdm_kpdpwr_n_gpio > 0) {
+			pr_debug("%s: Powering on mdm modem\n", __func__);
+			gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 1);
+			usleep(1000);
+		}
+		first_power_on = 0;
+	}
+	mdm_peripheral_connect(mdm_drv);
 
 	msleep(200);
 }
@@ -92,7 +116,6 @@
 		if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
 			break;
 	}
-
 	if (i <= 0) {
 		pr_err("%s: MDM2AP_STATUS never went low.\n",
 			 __func__);
@@ -103,12 +126,9 @@
 			msleep(MDM_MODEM_DELTA);
 		}
 	}
-
-	peripheral_disconnect();
-}
-
-static void normal_boot_done(struct mdm_modem_drv *mdm_drv)
-{
+	if (mdm_drv->ap2mdm_kpdpwr_n_gpio > 0)
+		gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 0);
+	mdm_peripheral_disconnect(mdm_drv);
 }
 
 static void debug_state_changed(int value)
@@ -116,24 +136,25 @@
 	mdm_debug_on = value;
 }
 
-static void mdm_status_changed(int value)
+static void mdm_status_changed(struct mdm_modem_drv *mdm_drv, int value)
 {
-	MDM_DBG("%s: value:%d\n", __func__, value);
+	pr_debug("%s: value:%d\n", __func__, value);
 
 	if (value) {
-		peripheral_disconnect();
-		peripheral_connect();
+		mdm_peripheral_disconnect(mdm_drv);
+		mdm_peripheral_connect(mdm_drv);
 	}
 }
 
+static struct mdm_ops mdm_cb = {
+	.power_on_mdm_cb = power_on_mdm,
+	.power_down_mdm_cb = power_down_mdm,
+	.debug_state_changed_cb = debug_state_changed,
+	.status_cb = mdm_status_changed,
+};
+
 static int __init mdm_modem_probe(struct platform_device *pdev)
 {
-	/* Instantiate driver object. */
-	mdm_cb.power_on_mdm_cb = power_on_mdm;
-	mdm_cb.power_down_mdm_cb = power_down_mdm;
-	mdm_cb.normal_boot_done_cb = normal_boot_done;
-	mdm_cb.debug_state_changed_cb = debug_state_changed;
-	mdm_cb.status_cb = mdm_status_changed;
 	return mdm_common_create(pdev, &mdm_cb);
 }
 
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index 023df69..7445a61 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.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
@@ -48,10 +48,6 @@
 
 #define EXTERNAL_MODEM "external_modem"
 
-#define MDM_DBG(...)	do { if (mdm_debug_on) \
-					pr_info(__VA_ARGS__); \
-			} while (0);
-
 static struct mdm_modem_drv *mdm_drv;
 
 DECLARE_COMPLETION(mdm_needs_reload);
@@ -70,11 +66,11 @@
 		return -EINVAL;
 	}
 
-	MDM_DBG("%s: Entering ioctl cmd = %d\n", __func__, _IOC_NR(cmd));
+	pr_debug("%s: Entering ioctl cmd = %d\n", __func__, _IOC_NR(cmd));
 	switch (cmd) {
 	case WAKE_CHARM:
-		MDM_DBG("%s: Powering on\n", __func__);
-		mdm_drv->power_on_mdm_cb(mdm_drv);
+		pr_info("%s: Powering on mdm\n", __func__);
+		mdm_drv->ops->power_on_mdm_cb(mdm_drv);
 		break;
 	case CHECK_FOR_BOOT:
 		if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
@@ -83,16 +79,19 @@
 			put_user(0, (unsigned long __user *) arg);
 		break;
 	case NORMAL_BOOT_DONE:
-		MDM_DBG("%s: check if mdm is booted up\n", __func__);
+		pr_debug("%s: check if mdm is booted up\n", __func__);
 		get_user(status, (unsigned long __user *) arg);
-		if (status)
+		if (status) {
+			pr_debug("%s: normal boot failed\n", __func__);
 			mdm_drv->mdm_boot_status = -EIO;
-		else
+		} else {
+			pr_info("%s: normal boot done\n", __func__);
 			mdm_drv->mdm_boot_status = 0;
+		}
 		mdm_drv->mdm_ready = 1;
 
-		if (mdm_drv->normal_boot_done_cb != NULL)
-			mdm_drv->normal_boot_done_cb(mdm_drv);
+		if (mdm_drv->ops->normal_boot_done_cb != NULL)
+			mdm_drv->ops->normal_boot_done_cb(mdm_drv);
 
 		if (!first_boot)
 			complete(&mdm_boot);
@@ -100,16 +99,18 @@
 			first_boot = 0;
 		break;
 	case RAM_DUMP_DONE:
-		MDM_DBG("%s: mdm done collecting RAM dumps\n", __func__);
+		pr_debug("%s: mdm done collecting RAM dumps\n", __func__);
 		get_user(status, (unsigned long __user *) arg);
 		if (status)
 			mdm_drv->mdm_ram_dump_status = -EIO;
-		else
+		else {
+			pr_info("%s: ramdump collection completed\n", __func__);
 			mdm_drv->mdm_ram_dump_status = 0;
+		}
 		complete(&mdm_ram_dumps);
 		break;
 	case WAIT_FOR_RESTART:
-		MDM_DBG("%s: wait for mdm to need images reloaded\n",
+		pr_debug("%s: wait for mdm to need images reloaded\n",
 				__func__);
 		ret = wait_for_completion_interruptible(&mdm_needs_reload);
 		if (!ret)
@@ -128,7 +129,7 @@
 
 static void mdm_fatal_fn(struct work_struct *work)
 {
-	MDM_DBG("%s: Reseting the mdm due to an errfatal\n", __func__);
+	pr_info("%s: Reseting the mdm due to an errfatal\n", __func__);
 	subsystem_restart(EXTERNAL_MODEM);
 }
 
@@ -138,15 +139,15 @@
 {
 	int value = gpio_get_value(mdm_drv->mdm2ap_status_gpio);
 
-	mdm_drv->status_cb(value);
+	mdm_drv->ops->status_cb(mdm_drv, value);
 
-	MDM_DBG("%s: status:%d\n", __func__, value);
+	pr_debug("%s: status:%d\n", __func__, value);
 
 	if ((value == 0) && mdm_drv->mdm_ready) {
-		MDM_DBG("%s: scheduling work now\n", __func__);
+		pr_info("%s: unexpected reset external modem\n", __func__);
 		subsystem_restart(EXTERNAL_MODEM);
 	} else if (value == 1) {
-		MDM_DBG("%s: mdm is now ready\n", __func__);
+		pr_info("%s: status = 1: mdm is now ready\n", __func__);
 	}
 }
 
@@ -161,10 +162,10 @@
 
 static irqreturn_t mdm_errfatal(int irq, void *dev_id)
 {
-	MDM_DBG("%s: mdm got errfatal interrupt\n", __func__);
+	pr_debug("%s: mdm got errfatal interrupt\n", __func__);
 	if (mdm_drv->mdm_ready &&
 		(gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 1)) {
-		MDM_DBG("%s: scheduling work now\n", __func__);
+		pr_debug("%s: scheduling work now\n", __func__);
 		queue_work(mdm_queue, &mdm_fatal_work);
 	}
 	return IRQ_HANDLED;
@@ -193,7 +194,7 @@
 {
 	int i;
 
-	MDM_DBG("%s: setting AP2MDM_ERRFATAL high for a non graceful reset\n",
+	pr_debug("%s: setting AP2MDM_ERRFATAL high for a non graceful reset\n",
 			 __func__);
 	mdm_disable_irqs();
 	gpio_set_value(mdm_drv->ap2mdm_errfatal_gpio, 1);
@@ -218,7 +219,7 @@
 
 static irqreturn_t mdm_status_change(int irq, void *dev_id)
 {
-	MDM_DBG("%s: mdm sent status change interrupt\n", __func__);
+	pr_debug("%s: mdm sent status change interrupt\n", __func__);
 
 	queue_work(mdm_queue, &mdm_status_work);
 
@@ -229,13 +230,19 @@
 {
 	mdm_drv->mdm_ready = 0;
 	gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 1);
-	mdm_drv->power_down_mdm_cb(mdm_drv);
+	if (mdm_drv->pdata->ramdump_delay_ms > 0) {
+		/* Wait for the external modem to complete
+		 * its preparation for ramdumps.
+		 */
+		mdelay(mdm_drv->pdata->ramdump_delay_ms);
+	}
+	mdm_drv->ops->power_down_mdm_cb(mdm_drv);
 	return 0;
 }
 
 static int mdm_subsys_powerup(const struct subsys_data *crashed_subsys)
 {
-	mdm_drv->power_on_mdm_cb(mdm_drv);
+	mdm_drv->ops->power_on_mdm_cb(mdm_drv);
 	mdm_drv->boot_type = CHARM_NORMAL_BOOT;
 	complete(&mdm_needs_reload);
 	wait_for_completion(&mdm_boot);
@@ -254,7 +261,7 @@
 		wait_for_completion(&mdm_ram_dumps);
 		INIT_COMPLETION(mdm_ram_dumps);
 		gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 1);
-		mdm_drv->power_down_mdm_cb(mdm_drv);
+		mdm_drv->ops->power_down_mdm_cb(mdm_drv);
 	}
 	return mdm_drv->mdm_ram_dump_status;
 }
@@ -269,8 +276,8 @@
 static int mdm_debug_on_set(void *data, u64 val)
 {
 	mdm_debug_on = val;
-	if (mdm_drv->debug_state_changed_cb)
-		mdm_drv->debug_state_changed_cb(mdm_debug_on);
+	if (mdm_drv->ops->debug_state_changed_cb)
+		mdm_drv->ops->debug_state_changed_cb(mdm_debug_on);
 	return 0;
 }
 
@@ -298,7 +305,7 @@
 }
 
 static void mdm_modem_initialize_data(struct platform_device  *pdev,
-				struct mdm_callbacks *p_mdm_cb)
+				struct mdm_ops *mdm_ops)
 {
 	struct resource *pres;
 
@@ -352,15 +359,12 @@
 
 	mdm_drv->boot_type                  = CHARM_NORMAL_BOOT;
 
-	mdm_drv->power_on_mdm_cb            = p_mdm_cb->power_on_mdm_cb;
-	mdm_drv->power_down_mdm_cb          = p_mdm_cb->power_down_mdm_cb;
-	mdm_drv->normal_boot_done_cb        = p_mdm_cb->normal_boot_done_cb;
-	mdm_drv->debug_state_changed_cb     = p_mdm_cb->debug_state_changed_cb;
-	mdm_drv->status_cb                  = p_mdm_cb->status_cb;
+	mdm_drv->ops      = mdm_ops;
+	mdm_drv->pdata    = pdev->dev.platform_data;
 }
 
 int mdm_common_create(struct platform_device  *pdev,
-					  struct mdm_callbacks *p_mdm_cb)
+					  struct mdm_ops *p_mdm_cb)
 {
 	int ret = -1, irq;
 
@@ -371,8 +375,8 @@
 	}
 
 	mdm_modem_initialize_data(pdev, p_mdm_cb);
-	if (mdm_drv->debug_state_changed_cb)
-		mdm_drv->debug_state_changed_cb(mdm_debug_on);
+	if (mdm_drv->ops->debug_state_changed_cb)
+		mdm_drv->ops->debug_state_changed_cb(mdm_debug_on);
 
 	gpio_request(mdm_drv->ap2mdm_status_gpio, "AP2MDM_STATUS");
 	gpio_request(mdm_drv->ap2mdm_errfatal_gpio, "AP2MDM_ERRFATAL");
@@ -451,6 +455,11 @@
 	mdm_drv->mdm_status_irq = irq;
 
 status_err:
+	/* Perform early powerup of the external modem in order to
+	 * allow tabla devices to be found.
+	 */
+	mdm_drv->ops->power_on_mdm_cb(mdm_drv);
+
 	pr_info("%s: Registering mdm modem\n", __func__);
 	return misc_register(&mdm_modem_misc);
 
@@ -494,7 +503,7 @@
 
 void mdm_common_modem_shutdown(struct platform_device *pdev)
 {
-	MDM_DBG("%s: setting AP2MDM_STATUS low for a graceful restart\n",
+	pr_debug("%s: setting AP2MDM_STATUS low for a graceful restart\n",
 		__func__);
 
 	mdm_disable_irqs();
@@ -504,7 +513,7 @@
 	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
 		gpio_set_value(mdm_drv->ap2mdm_wakeup_gpio, 1);
 
-	mdm_drv->power_down_mdm_cb(mdm_drv);
+	mdm_drv->ops->power_down_mdm_cb(mdm_drv);
 
 	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
 		gpio_set_value(mdm_drv->ap2mdm_wakeup_gpio, 0);
diff --git a/arch/arm/mach-msm/mdm_private.h b/arch/arm/mach-msm/mdm_private.h
index bc8541e..206bd8b 100644
--- a/arch/arm/mach-msm/mdm_private.h
+++ b/arch/arm/mach-msm/mdm_private.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
@@ -15,6 +15,14 @@
 
 struct mdm_modem_drv;
 
+struct mdm_ops {
+	void (*power_on_mdm_cb)(struct mdm_modem_drv *mdm_drv);
+	void (*normal_boot_done_cb)(struct mdm_modem_drv *mdm_drv);
+	void (*power_down_mdm_cb)(struct mdm_modem_drv *mdm_drv);
+	void (*debug_state_changed_cb)(int value);
+	void (*status_cb)(struct mdm_modem_drv *mdm_drv, int value);
+};
+
 /* Private mdm2 data structure */
 struct mdm_modem_drv {
 	unsigned mdm2ap_errfatal_gpio;
@@ -34,23 +42,12 @@
 	enum charm_boot_type boot_type;
 	int mdm_debug_on;
 
-	void (*power_on_mdm_cb)(struct mdm_modem_drv *mdm_drv);
-	void (*normal_boot_done_cb)(struct mdm_modem_drv *mdm_drv);
-	void (*power_down_mdm_cb)(struct mdm_modem_drv *mdm_drv);
-	void (*debug_state_changed_cb)(int value);
-	void (*status_cb)(int value);
-};
-
-struct mdm_callbacks {
-	void (*power_on_mdm_cb)(struct mdm_modem_drv *mdm_drv);
-	void (*normal_boot_done_cb)(struct mdm_modem_drv *mdm_drv);
-	void (*power_down_mdm_cb)(struct mdm_modem_drv *mdm_drv);
-	void (*debug_state_changed_cb)(int value);
-	void (*status_cb)(int value);
+	struct mdm_ops *ops;
+	struct mdm_platform_data *pdata;
 };
 
 int mdm_common_create(struct platform_device  *pdev,
-					  struct mdm_callbacks *mdm_cb);
+					  struct mdm_ops *mdm_cb);
 int mdm_common_modem_remove(struct platform_device *pdev);
 void mdm_common_modem_shutdown(struct platform_device *pdev);
 void mdm_common_set_debug_state(int value);
diff --git a/arch/arm/mach-msm/mpm.c b/arch/arm/mach-msm/mpm.c
index 70ee39b..746c0f8 100644
--- a/arch/arm/mach-msm/mpm.c
+++ b/arch/arm/mach-msm/mpm.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
@@ -20,8 +20,9 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irq.h>
-#include <asm/hardware/gic.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <asm/hardware/gic.h>
 #include <mach/msm_iomap.h>
 #include <mach/gpio.h>
 
@@ -68,6 +69,7 @@
 #define MSM_MPM_IRQ_INDEX(irq)  (irq / 32)
 #define MSM_MPM_IRQ_MASK(irq)  BIT(irq % 32)
 
+static struct msm_mpm_device_data msm_mpm_dev_data;
 static uint8_t msm_mpm_irqs_a2m[MSM_MPM_NR_APPS_IRQS];
 
 static DEFINE_SPINLOCK(msm_mpm_lock);
@@ -472,7 +474,7 @@
 }
 core_initcall(msm_mpm_early_init);
 
-void msm_mpm_irq_extn_init(void)
+void __init msm_mpm_irq_extn_init(struct msm_mpm_device_data *mpm_data)
 {
 	gic_arch_extn.irq_mask = msm_mpm_disable_irq;
 	gic_arch_extn.irq_unmask = msm_mpm_enable_irq;
@@ -487,6 +489,29 @@
 	msm_gpio_irq_extn.irq_set_wake = msm_mpm_set_irq_wake;
 
 	bitmap_set(msm_mpm_gpio_irqs_mask, NR_MSM_IRQS, NR_GPIO_IRQS);
+
+	if (!mpm_data) {
+#ifdef CONFIG_MSM_MPM
+		BUG();
+#endif
+		return;
+	}
+
+	memcpy(&msm_mpm_dev_data, mpm_data, sizeof(struct msm_mpm_device_data));
+
+	msm_mpm_dev_data.irqs_m2a =
+		kzalloc(msm_mpm_dev_data.irqs_m2a_size * sizeof(uint16_t),
+			GFP_KERNEL);
+	BUG_ON(!msm_mpm_dev_data.irqs_m2a);
+	memcpy(msm_mpm_dev_data.irqs_m2a, mpm_data->irqs_m2a,
+		msm_mpm_dev_data.irqs_m2a_size * sizeof(uint16_t));
+	msm_mpm_dev_data.bypassed_apps_irqs =
+		kzalloc(msm_mpm_dev_data.bypassed_apps_irqs_size *
+			sizeof(uint16_t), GFP_KERNEL);
+	BUG_ON(!msm_mpm_dev_data.bypassed_apps_irqs);
+	memcpy(msm_mpm_dev_data.bypassed_apps_irqs,
+		mpm_data->bypassed_apps_irqs,
+		msm_mpm_dev_data.bypassed_apps_irqs_size * sizeof(uint16_t));
 }
 
 static int __init msm_mpm_init(void)
diff --git a/arch/arm/mach-msm/mpm.h b/arch/arm/mach-msm/mpm.h
index 88e369c..85761bc 100644
--- a/arch/arm/mach-msm/mpm.h
+++ b/arch/arm/mach-msm/mpm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -38,9 +38,14 @@
 	unsigned int mpm_ipc_irq;
 };
 
-#ifdef CONFIG_MSM_MPM
-extern struct msm_mpm_device_data msm_mpm_dev_data;
+extern struct msm_mpm_device_data msm8660_mpm_dev_data;
+extern struct msm_mpm_device_data msm8960_mpm_dev_data;
+extern struct msm_mpm_device_data msm9615_mpm_dev_data;
+extern struct msm_mpm_device_data apq8064_mpm_dev_data;
 
+void msm_mpm_irq_extn_init(struct msm_mpm_device_data *mpm_data);
+
+#ifdef CONFIG_MSM_MPM
 int msm_mpm_enable_pin(enum msm_mpm_pin pin, unsigned int enable);
 int msm_mpm_set_pin_wake(enum msm_mpm_pin pin, unsigned int on);
 int msm_mpm_set_pin_type(enum msm_mpm_pin pin, unsigned int flow_type);
@@ -48,9 +53,7 @@
 bool msm_mpm_gpio_irqs_detectable(bool from_idle);
 void msm_mpm_enter_sleep(bool from_idle);
 void msm_mpm_exit_sleep(bool from_idle);
-void msm_mpm_irq_extn_init(void);
 #else
-
 int msm_mpm_enable_irq(unsigned int irq, unsigned int enable)
 { return -ENODEV; }
 int msm_mpm_set_irq_wake(unsigned int irq, unsigned int on)
@@ -69,7 +72,6 @@
 { return false; }
 void msm_mpm_enter_sleep(bool from_idle) {}
 void msm_mpm_exit_sleep(bool from_idle) {}
-void msm_mpm_irq_extn_init(void) {}
 #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..f93a79b
--- /dev/null
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -0,0 +1,230 @@
+/*
+ * 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,
+	.filter = 1 << LOGK_LOGBUF,
+};
+
+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/msm_watchdog.c b/arch/arm/mach-msm/msm_watchdog.c
index 5877fbf..4303f83 100644
--- a/arch/arm/mach-msm/msm_watchdog.c
+++ b/arch/arm/mach-msm/msm_watchdog.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -354,7 +354,7 @@
 		return ret;
 	}
 
-	enable_percpu_irq(WDT0_ACCSCSSNBARK_INT, 0);
+	enable_percpu_irq(WDT0_ACCSCSSNBARK_INT, IRQ_TYPE_EDGE_RISING);
 
 	/*
 	 * This is only temporary till SBLs turn on the XPUs
diff --git a/arch/arm/mach-msm/msm_xo.c b/arch/arm/mach-msm/msm_xo.c
index 802ee2a..74c64c1 100644
--- a/arch/arm/mach-msm/msm_xo.c
+++ b/arch/arm/mach-msm/msm_xo.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
@@ -115,7 +115,7 @@
 static int msm_xo_update_vote(struct msm_xo *xo)
 {
 	int ret;
-	unsigned vote, prev_vote = xo->mode;
+	unsigned vote, prev_vote = xo->mode, ctx_set;
 	struct msm_rpm_iv_pair cmd;
 
 	if (xo->votes[MSM_XO_MODE_ON])
@@ -141,7 +141,11 @@
 	} else if (xo == &msm_xo_sources[MSM_XO_CXO]) {
 		cmd.id = MSM_RPM_ID_CXO_CLK;
 		cmd.value = msm_xo_sources[MSM_XO_CXO].mode ? 1 : 0;
-		ret = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &cmd, 1);
+		if (cpu_is_msm9615())
+			ctx_set = MSM_RPM_CTX_SET_SLEEP;
+		else
+			ctx_set = MSM_RPM_CTX_SET_0;
+		ret = msm_rpmrs_set_noirq(ctx_set, &cmd, 1);
 	} else {
 		cmd.id = MSM_RPM_ID_CXO_BUFFERS;
 		cmd.value = (msm_xo_sources[MSM_XO_TCXO_D0].mode << 0)  |
@@ -149,7 +153,14 @@
 			    (msm_xo_sources[MSM_XO_TCXO_A0].mode << 16) |
 			    (msm_xo_sources[MSM_XO_TCXO_A1].mode << 24) |
 			    (msm_xo_sources[MSM_XO_TCXO_A2].mode << 28) |
-			    ((msm_xo_sources[MSM_XO_CORE].mode ? 1 : 0) << 20);
+			    /*
+			     * 8660 RPM has XO_CORE at bit 18 and 8960 RPM has
+			     * XO_CORE at bit 20. Since the opposite bit is
+			     * reserved in both cases, just set both and be
+			     * done with it.
+			     */
+			    ((msm_xo_sources[MSM_XO_CORE].mode ? 1 : 0) << 20) |
+			    ((msm_xo_sources[MSM_XO_CORE].mode ? 1 : 0) << 18);
 		ret = msm_rpm_set_noirq(MSM_RPM_CTX_SET_0, &cmd, 1);
 	}
 
@@ -228,10 +239,9 @@
 
 	/*
 	 * TODO: Remove early return for 8064 once RPM XO voting support
-	 * is available. Remove early return for 8960 CXO once all voters
-	 * for it are in place.
+	 * is available.
 	 */
-	if (cpu_is_apq8064() || (cpu_is_msm8960() && xo_id == MSM_XO_CXO))
+	if (cpu_is_apq8064())
 		return NULL;
 
 	if (xo_id >= NUM_MSM_XO_IDS) {
@@ -297,12 +307,25 @@
 int __init msm_xo_init(void)
 {
 	int i;
-	int ret;
+	int ret = 0;
 	struct msm_rpm_iv_pair cmd[2];
 
 	for (i = 0; i < ARRAY_SIZE(msm_xo_sources); i++)
 		INIT_LIST_HEAD(&msm_xo_sources[i].voters);
 
+	if (cpu_is_msm9615()) {
+		cmd[0].id = MSM_RPM_ID_CXO_CLK;
+		cmd[0].value = 1;
+		ret = msm_rpmrs_set(MSM_RPM_CTX_SET_0, cmd, 1);
+		if (ret)
+			goto out;
+
+		cmd[0].id = MSM_RPM_ID_CXO_CLK;
+		cmd[0].value = 0;
+		ret = msm_rpmrs_set(MSM_RPM_CTX_SET_SLEEP, cmd, 1);
+		goto out;
+	}
+
 	cmd[0].id = MSM_RPM_ID_PXO_CLK;
 	cmd[0].value = 1;
 	cmd[1].id = MSM_RPM_ID_CXO_BUFFERS;
diff --git a/arch/arm/mach-msm/no-pm.c b/arch/arm/mach-msm/no-pm.c
index f51286f..d1c474b 100644
--- a/arch/arm/mach-msm/no-pm.c
+++ b/arch/arm/mach-msm/no-pm.c
@@ -15,7 +15,7 @@
 
 #include <mach/cpuidle.h>
 #include "idle.h"
-#include <mach/pm.h>
+#include "pm.h"
 
 void arch_idle(void)
 { }
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-gss.c b/arch/arm/mach-msm/pil-gss.c
new file mode 100644
index 0000000..f3e83d9
--- /dev/null
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -0,0 +1,403 @@
+/*
+ * 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/err.h>
+#include <linux/io.h>
+#include <linux/elf.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/clk.h>
+#include <linux/smp.h>
+
+#include <mach/msm_iomap.h>
+#include <mach/msm_xo.h>
+
+#include "peripheral-loader.h"
+#include "scm-pas.h"
+
+#define GSS_CSR_AHB_CLK_SEL	0x0
+#define GSS_CSR_RESET		0x4
+#define GSS_CSR_CLK_BLK_CONFIG	0x8
+#define GSS_CSR_CLK_ENABLE	0xC
+#define GSS_CSR_BOOT_REMAP	0x14
+#define GSS_CSR_POWER_UP_DOWN	0x18
+#define GSS_CSR_CFG_HID		0x2C
+
+#define GSS_SLP_CLK_CTL		(MSM_CLK_CTL_BASE + 0x2C60)
+#define GSS_RESET		(MSM_CLK_CTL_BASE + 0x2C64)
+#define GSS_CLAMP_ENA		(MSM_CLK_CTL_BASE + 0x2C68)
+#define GSS_CXO_SRC_CTL		(MSM_CLK_CTL_BASE + 0x2C74)
+
+#define PLL5_MODE		(MSM_CLK_CTL_BASE + 0x30E0)
+#define PLL5_L_VAL		(MSM_CLK_CTL_BASE + 0x30E4)
+#define PLL5_M_VAL		(MSM_CLK_CTL_BASE + 0x30E8)
+#define PLL5_N_VAL		(MSM_CLK_CTL_BASE + 0x30EC)
+#define PLL5_CONFIG		(MSM_CLK_CTL_BASE + 0x30F4)
+#define PLL5_STATUS		(MSM_CLK_CTL_BASE + 0x30F8)
+#define PLL_ENA_GSS		(MSM_CLK_CTL_BASE + 0x3480)
+#define PLL_ENA_RPM		(MSM_CLK_CTL_BASE + 0x34A0)
+
+#define PLL5_VOTE		BIT(5)
+#define PLL_STATUS		BIT(16)
+#define REMAP_ENABLE		BIT(16)
+#define A5_POWER_STATUS		BIT(4)
+#define A5_POWER_ENA		BIT(0)
+#define NAV_POWER_ENA		BIT(1)
+#define XO_CLK_BRANCH_ENA	BIT(0)
+#define SLP_CLK_BRANCH_ENA	BIT(4)
+#define A5_RESET		BIT(0)
+
+#define PROXY_VOTE_TIMEOUT	10000
+
+struct gss_data {
+	void __iomem *base;
+	void __iomem *qgic2_base;
+	unsigned long start_addr;
+	struct delayed_work work;
+	struct clk *xo;
+};
+
+static int nop_verify_blob(struct pil_desc *pil, u32 phy_addr, size_t size)
+{
+	return 0;
+}
+
+static int pil_gss_init_image(struct pil_desc *pil, const u8 *metadata,
+		size_t size)
+{
+	const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
+	struct gss_data *drv = dev_get_drvdata(pil->dev);
+	drv->start_addr = ehdr->e_entry;
+	return 0;
+}
+
+static int make_gss_proxy_votes(struct device *dev)
+{
+	int ret;
+	struct gss_data *drv = dev_get_drvdata(dev);
+
+	ret = clk_prepare_enable(drv->xo);
+	if (ret) {
+		dev_err(dev, "Failed to enable XO\n");
+		return ret;
+	}
+	schedule_delayed_work(&drv->work, msecs_to_jiffies(PROXY_VOTE_TIMEOUT));
+	return 0;
+}
+
+static void remove_gss_proxy_votes(struct work_struct *work)
+{
+	struct gss_data *drv = container_of(work, struct gss_data, work.work);
+	clk_disable_unprepare(drv->xo);
+}
+
+static void remove_gss_proxy_votes_now(struct gss_data *drv)
+{
+	flush_delayed_work(&drv->work);
+}
+
+static void gss_init(struct gss_data *drv)
+{
+	void __iomem *base = drv->base;
+
+	/* Supply clocks to GSS. */
+	writel_relaxed(XO_CLK_BRANCH_ENA, GSS_CXO_SRC_CTL);
+	writel_relaxed(SLP_CLK_BRANCH_ENA, GSS_SLP_CLK_CTL);
+
+	/* Deassert GSS reset and clamps. */
+	writel_relaxed(0x0, GSS_RESET);
+	writel_relaxed(0x0, GSS_CLAMP_ENA);
+	mb();
+
+	/*
+	 * Configure clock source and dividers for 288MHz core, 144MHz AXI and
+	 * 72MHz AHB, all derived from the 288MHz PLL.
+	 */
+	writel_relaxed(0x341, base + GSS_CSR_CLK_BLK_CONFIG);
+	writel_relaxed(0x1, base + GSS_CSR_AHB_CLK_SEL);
+
+	/* Assert all GSS resets. */
+	writel_relaxed(0x7F, base + GSS_CSR_RESET);
+
+	/* Enable all bus clocks and wait for resets to propagate. */
+	writel_relaxed(0x1F, base + GSS_CSR_CLK_ENABLE);
+	mb();
+	udelay(1);
+
+	/* Release subsystem from reset, but leave A5 in reset. */
+	writel_relaxed(A5_RESET, base + GSS_CSR_RESET);
+}
+
+static void setup_qgic2_bus_access(void *data)
+{
+	struct gss_data *drv = data;
+	void __iomem *base = drv->base;
+	int i;
+
+	writel_relaxed(0x2, base + GSS_CSR_CFG_HID);
+	for (i = 0; i <= 3; i++)
+		readl_relaxed(drv->qgic2_base);
+}
+
+static int pil_gss_shutdown(struct pil_desc *pil)
+{
+	struct gss_data *drv = dev_get_drvdata(pil->dev);
+	void __iomem *base = drv->base;
+	u32 regval;
+	int ret;
+
+	ret = clk_prepare_enable(drv->xo);
+	if (ret) {
+		dev_err(pil->dev, "Failed to enable XO\n");
+		return ret;
+	}
+
+	/*
+	 * Vote PLL on in GSS's voting register and wait for it to enable.
+	 * The PLL must be enable to switch the GFMUX to a low-power source.
+	 */
+	writel_relaxed(PLL5_VOTE, PLL_ENA_GSS);
+	while ((readl_relaxed(PLL5_STATUS) & PLL_STATUS) == 0)
+		cpu_relax();
+
+	/* Perform one-time GSS initialization. */
+	gss_init(drv);
+
+	/* Assert A5 reset. */
+	regval = readl_relaxed(base + GSS_CSR_RESET);
+	regval |= A5_RESET;
+	writel_relaxed(regval, base + GSS_CSR_RESET);
+
+	/* Power down A5 and NAV. */
+	regval = readl_relaxed(base + GSS_CSR_POWER_UP_DOWN);
+	regval &= ~(A5_POWER_ENA|NAV_POWER_ENA);
+	writel_relaxed(regval, base + GSS_CSR_POWER_UP_DOWN);
+
+	/* Select XO clock source and increase dividers to save power. */
+	regval = readl_relaxed(base + GSS_CSR_CLK_BLK_CONFIG);
+	regval |= 0x3FF;
+	writel_relaxed(regval, base + GSS_CSR_CLK_BLK_CONFIG);
+
+	/* Disable bus clocks. */
+	writel_relaxed(0x1F, base + GSS_CSR_CLK_ENABLE);
+
+	/* Clear GSS PLL votes. */
+	writel_relaxed(0, PLL_ENA_GSS);
+	mb();
+
+	clk_disable_unprepare(drv->xo);
+	remove_gss_proxy_votes_now(drv);
+
+	return 0;
+}
+
+static int pil_gss_reset(struct pil_desc *pil)
+{
+	struct gss_data *drv = dev_get_drvdata(pil->dev);
+	void __iomem *base = drv->base;
+	unsigned long start_addr = drv->start_addr;
+	int ret;
+
+	ret = make_gss_proxy_votes(pil->dev);
+	if (ret)
+		return ret;
+
+	/* Vote PLL on in GSS's voting register and wait for it to enable. */
+	writel_relaxed(PLL5_VOTE, PLL_ENA_GSS);
+	while ((readl_relaxed(PLL5_STATUS) & PLL_STATUS) == 0)
+		cpu_relax();
+
+	/* Perform GSS initialization. */
+	gss_init(drv);
+
+	/* Configure boot address and enable remap. */
+	writel_relaxed(REMAP_ENABLE | (start_addr >> 16),
+			base + GSS_CSR_BOOT_REMAP);
+
+	/* Power up A5 core. */
+	writel_relaxed(A5_POWER_ENA, base + GSS_CSR_POWER_UP_DOWN);
+	while (!(readl_relaxed(base + GSS_CSR_POWER_UP_DOWN) & A5_POWER_STATUS))
+		cpu_relax();
+
+	/*
+	 * Apply a 8064 v1.0 workaround to configure QGIC bus access. This must
+	 * be done from Krait 0 to configure the Master ID correctly.
+	 */
+	ret = smp_call_function_single(0, setup_qgic2_bus_access, drv, 1);
+	if (ret) {
+		pr_err("Failed to configure QGIC2 bus access\n");
+		pil_gss_shutdown(pil);
+		return ret;
+	}
+
+	/* Release A5 from reset. */
+	writel_relaxed(0x0, base + GSS_CSR_RESET);
+
+	return 0;
+}
+
+static struct pil_reset_ops pil_gss_ops = {
+	.init_image = pil_gss_init_image,
+	.verify_blob = nop_verify_blob,
+	.auth_and_reset = pil_gss_reset,
+	.shutdown = pil_gss_shutdown,
+};
+
+static void configure_gss_pll(struct gss_data *drv)
+{
+	u32 regval, is_pll_enabled;
+
+	/* Check if PLL5 is enabled by FSM. */
+	is_pll_enabled = readl_relaxed(PLL5_STATUS) & PLL_STATUS;
+	if (!is_pll_enabled) {
+		/* Enable XO reference for PLL5 */
+		clk_prepare_enable(drv->xo);
+
+		/*
+		 * Assert a vote to hold PLL5 on in RPM register until other
+		 * voters are in place.
+		 */
+		regval = readl_relaxed(PLL_ENA_RPM);
+		regval |= PLL5_VOTE;
+		writel_relaxed(regval, PLL_ENA_RPM);
+
+		/* Ref clk = 27MHz and program pll5 to 288MHz */
+		writel_relaxed(0xF, PLL5_L_VAL);
+		writel_relaxed(0x0, PLL5_M_VAL);
+		writel_relaxed(0x1, PLL5_N_VAL);
+
+		regval = readl_relaxed(PLL5_CONFIG);
+		/* Disable the MN accumulator and enable the main output. */
+		regval &= ~BIT(22);
+		regval |= BIT(23);
+
+		/* Set pre-divider and post-divider values to 1 and 1 */
+		regval &= ~BIT(19);
+		regval &= ~(BIT(21)|BIT(20));
+
+		/* Set VCO frequency */
+		regval &= ~(BIT(17)|BIT(16));
+		writel_relaxed(regval, PLL5_CONFIG);
+
+		regval = readl_relaxed(PLL5_MODE);
+		/* De-assert reset to FSM */
+		regval &= ~BIT(21);
+		writel_relaxed(regval, PLL5_MODE);
+
+		/* Program bias count */
+		regval &= ~(0x3F << 14);
+		regval |= (0x1 << 14);
+		writel_relaxed(regval, PLL5_MODE);
+
+		/* Program lock count */
+		regval &= ~(0x3F << 8);
+		regval |= (0x8 << 8);
+		writel_relaxed(regval, PLL5_MODE);
+
+		/* Enable PLL FSM voting */
+		regval |= BIT(20);
+		writel_relaxed(regval, PLL5_MODE);
+	}
+}
+
+static int __devinit pil_gss_probe(struct platform_device *pdev)
+{
+	struct gss_data *drv;
+	struct resource *res;
+	struct pil_desc *desc;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+	if (!drv)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, drv);
+
+	drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!drv->base)
+		return -ENOMEM;
+
+	desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res)
+		return -EINVAL;
+
+	drv->qgic2_base = devm_ioremap(&pdev->dev, res->start,
+					resource_size(res));
+	if (!drv->qgic2_base)
+		return -ENOMEM;
+
+	drv->xo = clk_get(&pdev->dev, "xo");
+	if (IS_ERR(drv->xo))
+		return PTR_ERR(drv->xo);
+
+	desc->name = "gss";
+	desc->dev = &pdev->dev;
+
+	desc->ops = &pil_gss_ops;
+	dev_info(&pdev->dev, "using non-secure boot\n");
+
+	INIT_DELAYED_WORK(&drv->work, remove_gss_proxy_votes);
+
+	/* FIXME: Remove when PLL is configured by bootloaders. */
+	configure_gss_pll(drv);
+
+	ret = msm_pil_register(desc);
+	if (ret) {
+		flush_delayed_work_sync(&drv->work);
+		clk_put(drv->xo);
+	}
+	return ret;
+}
+
+static int __devexit pil_gss_remove(struct platform_device *pdev)
+{
+	struct gss_data *drv = platform_get_drvdata(pdev);
+	flush_delayed_work_sync(&drv->work);
+	clk_put(drv->xo);
+	return 0;
+}
+
+static struct platform_driver pil_gss_driver = {
+	.probe = pil_gss_probe,
+	.remove = __devexit_p(pil_gss_remove),
+	.driver = {
+		.name = "pil_gss",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init pil_gss_init(void)
+{
+	return platform_driver_register(&pil_gss_driver);
+}
+module_init(pil_gss_init);
+
+static void __exit pil_gss_exit(void)
+{
+	platform_driver_unregister(&pil_gss_driver);
+}
+module_exit(pil_gss_exit);
+
+MODULE_DESCRIPTION("Support for booting the GSS processor");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pil-modem.c b/arch/arm/mach-msm/pil-modem.c
index 5aa3834..1d13508 100644
--- a/arch/arm/mach-msm/pil-modem.c
+++ b/arch/arm/mach-msm/pil-modem.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
@@ -18,9 +18,10 @@
 #include <linux/elf.h>
 #include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/workqueue.h>
+#include <linux/clk.h>
 
 #include <mach/msm_iomap.h>
-#include <mach/msm_xo.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
@@ -52,8 +53,8 @@
 struct modem_data {
 	void __iomem *base;
 	unsigned long start_addr;
-	struct msm_xo_voter *pxo;
-	struct timer_list timer;
+	struct clk *xo;
+	struct delayed_work work;
 };
 
 static int nop_verify_blob(struct pil_desc *pil, u32 phy_addr, size_t size)
@@ -61,28 +62,30 @@
 	return 0;
 }
 
-static void remove_proxy_votes(unsigned long data)
-{
-	struct modem_data *drv = (struct modem_data *)data;
-	msm_xo_mode_vote(drv->pxo, MSM_XO_MODE_OFF);
-}
-
-static void make_modem_proxy_votes(struct device *dev)
+static int make_modem_proxy_votes(struct device *dev)
 {
 	int ret;
 	struct modem_data *drv = dev_get_drvdata(dev);
 
-	ret = msm_xo_mode_vote(drv->pxo, MSM_XO_MODE_ON);
-	if (ret)
-		dev_err(dev, "Failed to enable PXO\n");
-	mod_timer(&drv->timer, jiffies + msecs_to_jiffies(PROXY_VOTE_TIMEOUT));
+	ret = clk_prepare_enable(drv->xo);
+	if (ret) {
+		dev_err(dev, "Failed to enable XO\n");
+		return ret;
+	}
+	schedule_delayed_work(&drv->work, msecs_to_jiffies(PROXY_VOTE_TIMEOUT));
+	return 0;
+}
+
+static void remove_modem_proxy_votes(struct work_struct *work)
+{
+	struct modem_data *drv;
+	drv = container_of(work, struct modem_data, work.work);
+	clk_disable_unprepare(drv->xo);
 }
 
 static void remove_modem_proxy_votes_now(struct modem_data *drv)
 {
-	/* If the proxy vote hasn't been removed yet, remove it immediately. */
-	if (del_timer(&drv->timer))
-		remove_proxy_votes((unsigned long)drv);
+	flush_delayed_work(&drv->work);
 }
 
 static int modem_init_image(struct pil_desc *pil, const u8 *metadata,
@@ -97,9 +100,12 @@
 static int modem_reset(struct pil_desc *pil)
 {
 	u32 reg;
+	int ret;
 	const struct modem_data *drv = dev_get_drvdata(pil->dev);
 
-	make_modem_proxy_votes(pil->dev);
+	ret = make_modem_proxy_votes(pil->dev);
+	if (ret)
+		return ret;
 
 	/* Put modem AHB0,1,2 clocks into reset */
 	writel_relaxed(BIT(0) | BIT(1), MAHB0_SFAB_PORT_RESET);
@@ -235,7 +241,9 @@
 	int ret;
 	struct modem_data *drv = dev_get_drvdata(pil->dev);
 
-	make_modem_proxy_votes(pil->dev);
+	ret = make_modem_proxy_votes(pil->dev);
+	if (ret)
+		return ret;
 
 	ret = pas_auth_and_reset(PAS_MODEM);
 	if (ret)
@@ -269,6 +277,7 @@
 	struct modem_data *drv;
 	struct resource *res;
 	struct pil_desc *desc;
+	int ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
@@ -283,15 +292,14 @@
 	if (!drv->base)
 		return -ENOMEM;
 
-	drv->pxo = msm_xo_get(MSM_XO_PXO, dev_name(&pdev->dev));
-	if (IS_ERR(drv->pxo))
-		return PTR_ERR(drv->pxo);
+	drv->xo = clk_get(&pdev->dev, "xo");
+	if (IS_ERR(drv->xo))
+		return PTR_ERR(drv->xo);
 
 	desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
 	if (!desc)
 		return -ENOMEM;
 
-	setup_timer(&drv->timer, remove_proxy_votes, (unsigned long)drv);
 	desc->name = "modem";
 	desc->depends_on = "q6";
 	desc->dev = &pdev->dev;
@@ -303,19 +311,21 @@
 		desc->ops = &pil_modem_ops;
 		dev_info(&pdev->dev, "using non-secure boot\n");
 	}
+	INIT_DELAYED_WORK(&drv->work, remove_modem_proxy_votes);
 
-	if (msm_pil_register(desc)) {
-		msm_xo_put(drv->pxo);
-		return -EINVAL;
+	ret = msm_pil_register(desc);
+	if (ret) {
+		flush_delayed_work_sync(&drv->work);
+		clk_put(drv->xo);
 	}
-	return 0;
+	return ret;
 }
 
 static int __devexit pil_modem_driver_exit(struct platform_device *pdev)
 {
 	struct modem_data *drv = platform_get_drvdata(pdev);
-	del_timer_sync(&drv->timer);
-	msm_xo_put(drv->pxo);
+	flush_delayed_work_sync(&drv->work);
+	clk_put(drv->xo);
 	return 0;
 }
 
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-q6v4.c b/arch/arm/mach-msm/pil-q6v4.c
index d8ebab5..511377d 100644
--- a/arch/arm/mach-msm/pil-q6v4.c
+++ b/arch/arm/mach-msm/pil-q6v4.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
@@ -19,10 +19,11 @@
 #include <linux/elf.h>
 #include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/workqueue.h>
+#include <linux/clk.h>
 
 #include <mach/msm_bus.h>
 #include <mach/msm_iomap.h>
-#include <mach/msm_xo.h>
 
 #include "peripheral-loader.h"
 #include "pil-q6v4.h"
@@ -68,9 +69,10 @@
 	void __iomem *modem_base;
 	unsigned long start_addr;
 	struct regulator *vreg;
+	struct regulator *pll_supply;
 	bool vreg_enabled;
-	struct msm_xo_voter *xo;
-	struct timer_list xo_timer;
+	struct clk *xo;
+	struct delayed_work work;
 };
 
 static int pil_q6v4_init_image(struct pil_desc *pil, const u8 *metadata,
@@ -87,27 +89,43 @@
 	return 0;
 }
 
-static void pil_q6v4_make_xo_proxy_votes(struct device *dev)
+static int pil_q6v4_make_proxy_votes(struct device *dev)
 {
 	struct q6v4_data *drv = dev_get_drvdata(dev);
+	int ret;
 
-	msm_xo_mode_vote(drv->xo, MSM_XO_MODE_ON);
-	mod_timer(&drv->xo_timer, jiffies+msecs_to_jiffies(PROXY_VOTE_TIMEOUT));
+	ret = clk_prepare_enable(drv->xo);
+	if (ret) {
+		dev_err(dev, "Failed to enable XO\n");
+		goto err;
+	}
+	if (drv->pll_supply) {
+		ret = regulator_enable(drv->pll_supply);
+		if (ret) {
+			dev_err(dev, "Failed to enable pll supply\n");
+			goto err_regulator;
+		}
+	}
+	schedule_delayed_work(&drv->work, msecs_to_jiffies(PROXY_VOTE_TIMEOUT));
+	return 0;
+err_regulator:
+	clk_disable_unprepare(drv->xo);
+err:
+	return ret;
 }
 
-static void pil_q6v4_remove_xo_proxy_votes(unsigned long data)
+static void pil_q6v4_remove_proxy_votes(struct work_struct *work)
 {
-	struct q6v4_data *drv = (struct q6v4_data *)data;
-
-	msm_xo_mode_vote(drv->xo, MSM_XO_MODE_OFF);
+	struct q6v4_data *drv = container_of(work, struct q6v4_data, work.work);
+	if (drv->pll_supply)
+		regulator_disable(drv->pll_supply);
+	clk_disable_unprepare(drv->xo);
 }
 
-static void pil_q6v4_remove_xo_proxy_votes_now(struct device *dev)
+static void pil_q6v4_remove_proxy_votes_now(struct device *dev)
 {
 	struct q6v4_data *drv = dev_get_drvdata(dev);
-
-	if (del_timer(&drv->xo_timer))
-		pil_q6v4_remove_xo_proxy_votes((unsigned long)drv);
+	flush_delayed_work(&drv->work);
 }
 
 static int pil_q6v4_power_up(struct device *dev)
@@ -184,7 +202,9 @@
 	const struct q6v4_data *drv = dev_get_drvdata(pil->dev);
 	const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;
 
-	pil_q6v4_make_xo_proxy_votes(pil->dev);
+	err = pil_q6v4_make_proxy_votes(pil->dev);
+	if (err)
+		return err;
 
 	err = pil_q6v4_power_up(pil->dev);
 	if (err)
@@ -300,7 +320,7 @@
 		drv->vreg_enabled = false;
 	}
 
-	pil_q6v4_remove_xo_proxy_votes_now(pil->dev);
+	pil_q6v4_remove_proxy_votes_now(pil->dev);
 
 	return 0;
 }
@@ -324,7 +344,9 @@
 	const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;
 	int err;
 
-	pil_q6v4_make_xo_proxy_votes(pil->dev);
+	err = pil_q6v4_make_proxy_votes(pil->dev);
+	if (err)
+		return err;
 
 	err = pil_q6v4_power_up(pil->dev);
 	if (err)
@@ -355,7 +377,7 @@
 		drv->vreg_enabled = false;
 	}
 
-	pil_q6v4_remove_xo_proxy_votes_now(pil->dev);
+	pil_q6v4_remove_proxy_votes_now(pil->dev);
 
 	return ret;
 }
@@ -373,6 +395,7 @@
 	struct q6v4_data *drv;
 	struct resource *res;
 	struct pil_desc *desc;
+	int ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
@@ -396,9 +419,26 @@
 	}
 
 	desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
-	if (!drv)
+	if (!desc)
 		return -ENOMEM;
 
+	drv->pll_supply = regulator_get(&pdev->dev, "pll_vdd");
+	if (IS_ERR(drv->pll_supply)) {
+		drv->pll_supply = NULL;
+	} else {
+		ret = regulator_set_voltage(drv->pll_supply, 1800000, 1800000);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to set pll voltage\n");
+			goto err;
+		}
+
+		ret = regulator_set_optimum_mode(drv->pll_supply, 100000);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "failed to set pll optimum mode\n");
+			goto err;
+		}
+	}
+
 	desc->name = pdata->name;
 	desc->depends_on = pdata->depends;
 	desc->dev = &pdev->dev;
@@ -412,26 +452,39 @@
 	}
 
 	drv->vreg = regulator_get(&pdev->dev, "core_vdd");
-	if (IS_ERR(drv->vreg))
-		return PTR_ERR(drv->vreg);
-
-	setup_timer(&drv->xo_timer, pil_q6v4_remove_xo_proxy_votes,
-		    (unsigned long)drv);
-	drv->xo = msm_xo_get(pdata->xo_id, pdata->name);
-	if (IS_ERR(drv->xo))
-		return PTR_ERR(drv->xo);
-
-	if (msm_pil_register(desc)) {
-		regulator_put(drv->vreg);
-		return -EINVAL;
+	if (IS_ERR(drv->vreg)) {
+		ret = PTR_ERR(drv->vreg);
+		goto err;
 	}
+
+	drv->xo = clk_get(&pdev->dev, "xo");
+	if (IS_ERR(drv->xo)) {
+		ret = PTR_ERR(drv->xo);
+		goto err_xo;
+	}
+	INIT_DELAYED_WORK(&drv->work, pil_q6v4_remove_proxy_votes);
+
+	ret = msm_pil_register(desc);
+	if (ret)
+		goto err_pil;
 	return 0;
+err_pil:
+	flush_delayed_work_sync(&drv->work);
+	clk_put(drv->xo);
+err_xo:
+	regulator_put(drv->vreg);
+err:
+	regulator_put(drv->pll_supply);
+	return ret;
 }
 
 static int __devexit pil_q6v4_driver_exit(struct platform_device *pdev)
 {
 	struct q6v4_data *drv = platform_get_drvdata(pdev);
+	flush_delayed_work_sync(&drv->work);
+	clk_put(drv->xo);
 	regulator_put(drv->vreg);
+	regulator_put(drv->pll_supply);
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/pil-q6v4.h b/arch/arm/mach-msm/pil-q6v4.h
index 54bdf88..b0b97d0 100644
--- a/arch/arm/mach-msm/pil-q6v4.h
+++ b/arch/arm/mach-msm/pil-q6v4.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
@@ -18,7 +18,6 @@
 	const unsigned long strap_ahb_lower;
 	void __iomem *aclk_reg;
 	void __iomem *jtag_clk_reg;
-	const int xo_id;
 	const char *name;
 	const char *depends;
 	const unsigned pas_id;
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index 6848c59..bd49fc0 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -18,9 +18,11 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/workqueue.h>
+#include <linux/clk.h>
 
 #include <mach/msm_iomap.h>
-#include <mach/msm_xo.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
@@ -80,38 +82,49 @@
 struct riva_data {
 	void __iomem *base;
 	unsigned long start_addr;
-	struct msm_xo_voter *xo;
-	struct timer_list xo_timer;
+	struct clk *xo;
+	bool use_cxo;
+	struct delayed_work work;
+	struct regulator *pll_supply;
 };
 
-static void pil_riva_make_xo_proxy_votes(struct device *dev)
+static int pil_riva_make_proxy_votes(struct device *dev)
 {
 	struct riva_data *drv = dev_get_drvdata(dev);
+	int ret;
 
-	msm_xo_mode_vote(drv->xo, MSM_XO_MODE_ON);
-	mod_timer(&drv->xo_timer, jiffies+msecs_to_jiffies(PROXY_VOTE_TIMEOUT));
+	ret = regulator_enable(drv->pll_supply);
+	if (ret) {
+		dev_err(dev, "failed to enable pll supply\n");
+		goto err;
+	}
+	if (drv->use_cxo) {
+		ret = clk_prepare_enable(drv->xo);
+		if (ret) {
+			dev_err(dev, "failed to enable xo\n");
+			goto err_clk;
+		}
+	}
+	schedule_delayed_work(&drv->work, msecs_to_jiffies(PROXY_VOTE_TIMEOUT));
+	return 0;
+err_clk:
+	regulator_disable(drv->pll_supply);
+err:
+	return ret;
 }
 
-static void pil_riva_remove_xo_proxy_votes(unsigned long data)
+static void pil_riva_remove_proxy_votes(struct work_struct *work)
 {
-	struct riva_data *drv = (struct riva_data *)data;
-
-	msm_xo_mode_vote(drv->xo, MSM_XO_MODE_OFF);
+	struct riva_data *drv = container_of(work, struct riva_data, work.work);
+	regulator_disable(drv->pll_supply);
+	if (drv->use_cxo)
+		clk_disable_unprepare(drv->xo);
 }
 
-static void pil_riva_remove_xo_proxy_votes_now(struct device *dev)
+static void pil_riva_remove_proxy_votes_now(struct device *dev)
 {
 	struct riva_data *drv = dev_get_drvdata(dev);
-
-	if (del_timer(&drv->xo_timer))
-		pil_riva_remove_xo_proxy_votes((unsigned long)drv);
-}
-
-static bool cxo_is_needed(struct riva_data *drv)
-{
-	u32 reg = readl_relaxed(drv->base + RIVA_PMU_CFG);
-	return (reg & RIVA_PMU_CFG_IRIS_XO_MODE)
-		!= RIVA_PMU_CFG_IRIS_XO_MODE_48;
+	flush_delayed_work(&drv->work);
 }
 
 static int nop_verify_blob(struct pil_desc *pil, u32 phy_addr, size_t size)
@@ -128,30 +141,45 @@
 	return 0;
 }
 
+static bool cxo_is_needed(struct riva_data *drv)
+{
+	u32 reg = readl_relaxed(drv->base + RIVA_PMU_CFG);
+	return (reg & RIVA_PMU_CFG_IRIS_XO_MODE)
+		!= RIVA_PMU_CFG_IRIS_XO_MODE_48;
+}
+
 static int pil_riva_reset(struct pil_desc *pil)
 {
 	u32 reg, sel;
-	bool use_cxo;
 	struct riva_data *drv = dev_get_drvdata(pil->dev);
 	void __iomem *base = drv->base;
 	unsigned long start_addr = drv->start_addr;
+	int ret;
 
+	ret = clk_prepare_enable(drv->xo);
+	if (ret)
+		return ret;
 	/* Enable A2XB bridge */
 	reg = readl_relaxed(base + RIVA_PMU_A2XB_CFG);
 	reg |= RIVA_PMU_A2XB_CFG_EN;
 	writel_relaxed(reg, base + RIVA_PMU_A2XB_CFG);
 
-	/* Proxy-vote for CXO if it's needed */
-	use_cxo = cxo_is_needed(drv);
-	if (use_cxo)
-		pil_riva_make_xo_proxy_votes(pil->dev);
+	drv->use_cxo = cxo_is_needed(drv);
+	ret = pil_riva_make_proxy_votes(pil->dev);
+	if (ret) {
+		reg &= ~RIVA_PMU_A2XB_CFG_EN;
+		writel_relaxed(reg, base + RIVA_PMU_A2XB_CFG);
+		mb();
+		clk_disable_unprepare(drv->xo);
+		return ret;
+	}
 
 	/* Program PLL 13 to 960 MHz */
 	reg = readl_relaxed(RIVA_PLL_MODE);
 	reg &= ~(PLL_MODE_BYPASSNL | PLL_MODE_OUTCTRL | PLL_MODE_RESET_N);
 	writel_relaxed(reg, RIVA_PLL_MODE);
 
-	if (use_cxo)
+	if (drv->use_cxo)
 		writel_relaxed(0x40000C00 | 50, RIVA_PLL_L_VAL);
 	else
 		writel_relaxed(0x40000C00 | 40, RIVA_PLL_L_VAL);
@@ -161,7 +189,7 @@
 
 	reg = readl_relaxed(RIVA_PLL_MODE);
 	reg &= ~(PLL_MODE_REF_XO_SEL);
-	reg |= use_cxo ? PLL_MODE_REF_XO_SEL_CXO : PLL_MODE_REF_XO_SEL_RF;
+	reg |= drv->use_cxo ? PLL_MODE_REF_XO_SEL_CXO : PLL_MODE_REF_XO_SEL_RF;
 	writel_relaxed(reg, RIVA_PLL_MODE);
 
 	/* Enable PLL 13 */
@@ -226,6 +254,7 @@
 	/* Take cCPU out of reset */
 	reg |= RIVA_PMU_OVRD_VAL_CCPU_RESET;
 	writel_relaxed(reg, base + RIVA_PMU_OVRD_VAL);
+	clk_disable_unprepare(drv->xo);
 
 	return 0;
 }
@@ -234,7 +263,11 @@
 {
 	struct riva_data *drv = dev_get_drvdata(pil->dev);
 	u32 reg;
+	int ret;
 
+	ret = clk_prepare_enable(drv->xo);
+	if (ret)
+		return ret;
 	/* Put cCPU and cCPU clock into reset */
 	reg = readl_relaxed(drv->base + RIVA_PMU_OVRD_VAL);
 	reg &= ~(RIVA_PMU_OVRD_VAL_CCPU_RESET | RIVA_PMU_OVRD_VAL_CCPU_CLK);
@@ -253,7 +286,8 @@
 	writel_relaxed(0, RIVA_RESET);
 	mb();
 
-	pil_riva_remove_xo_proxy_votes_now(pil->dev);
+	clk_disable_unprepare(drv->xo);
+	pil_riva_remove_proxy_votes_now(pil->dev);
 
 	return 0;
 }
@@ -274,19 +308,30 @@
 static int pil_riva_reset_trusted(struct pil_desc *pil)
 {
 	struct riva_data *drv = dev_get_drvdata(pil->dev);
+	int ret;
 
-	/* Proxy-vote for CXO if it's needed */
-	if (cxo_is_needed(drv))
-		pil_riva_make_xo_proxy_votes(pil->dev);
-
-	return pas_auth_and_reset(PAS_RIVA);
+	ret = clk_prepare_enable(drv->xo);
+	if (ret)
+		return ret;
+	/* Proxy-vote for resources RIVA needs */
+	ret = pil_riva_make_proxy_votes(pil->dev);
+	if (!ret)
+		ret = pas_auth_and_reset(PAS_RIVA);
+	clk_disable_unprepare(drv->xo);
+	return ret;
 }
 
 static int pil_riva_shutdown_trusted(struct pil_desc *pil)
 {
-	int ret = pas_shutdown(PAS_RIVA);
+	int ret;
+	struct riva_data *drv = dev_get_drvdata(pil->dev);
 
-	pil_riva_remove_xo_proxy_votes_now(pil->dev);
+	ret = clk_prepare_enable(drv->xo);
+	if (ret)
+		return ret;
+	ret = pas_shutdown(PAS_RIVA);
+	pil_riva_remove_proxy_votes_now(pil->dev);
+	clk_disable_unprepare(drv->xo);
 
 	return ret;
 }
@@ -303,6 +348,7 @@
 	struct riva_data *drv;
 	struct resource *res;
 	struct pil_desc *desc;
+	int ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
@@ -321,6 +367,27 @@
 	if (!desc)
 		return -ENOMEM;
 
+	drv->pll_supply = regulator_get(&pdev->dev, "pll_vdd");
+	if (IS_ERR(drv->pll_supply)) {
+		dev_err(&pdev->dev, "failed to get pll supply\n");
+		return PTR_ERR(drv->pll_supply);
+	}
+	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;
+		}
+	}
+
 	desc->name = "wcnss";
 	desc->dev = &pdev->dev;
 
@@ -332,17 +399,31 @@
 		dev_info(&pdev->dev, "using non-secure boot\n");
 	}
 
-	setup_timer(&drv->xo_timer, pil_riva_remove_xo_proxy_votes,
-		    (unsigned long)drv);
-	drv->xo = msm_xo_get(MSM_XO_CXO, desc->name);
-	if (IS_ERR(drv->xo))
-		return PTR_ERR(drv->xo);
+	drv->xo = clk_get(&pdev->dev, "cxo");
+	if (IS_ERR(drv->xo)) {
+		ret = PTR_ERR(drv->xo);
+		goto err;
+	}
+	INIT_DELAYED_WORK(&drv->work, pil_riva_remove_proxy_votes);
 
-	return msm_pil_register(desc);
+	ret = msm_pil_register(desc);
+	if (ret)
+		goto err_register;
+	return 0;
+err_register:
+	flush_delayed_work_sync(&drv->work);
+	clk_put(drv->xo);
+err:
+	regulator_put(drv->pll_supply);
+	return ret;
 }
 
 static int __devexit pil_riva_remove(struct platform_device *pdev)
 {
+	struct riva_data *drv = platform_get_drvdata(pdev);
+	flush_delayed_work_sync(&drv->work);
+	clk_put(drv->xo);
+	regulator_put(drv->pll_supply);
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index f1c6c48..6b48d57 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -25,7 +25,7 @@
 #include <mach/hardware.h>
 #include <mach/msm_iomap.h>
 
-#include <mach/pm.h>
+#include "pm.h"
 #include "scm-boot.h"
 #include "spm.h"
 
@@ -198,14 +198,5 @@
 
 	trace_hardirqs_off();
 
-	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-	writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
-	/* RUMI does not adhere to GIC spec by enabling STIs by default.
-	 * Enable/clear is supposed to be RO for STIs, but is RW on RUMI.
-	 */
-	if (!machine_is_msm8x60_sim())
-		writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-
 	gic_secondary_init(0);
 }
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 754d76f..b3c6d1e 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.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
@@ -44,7 +44,7 @@
 #include "avs.h"
 #include <mach/cpuidle.h>
 #include "idle.h"
-#include <mach/pm.h>
+#include "pm.h"
 #include "rpm_resources.h"
 #include "scm-boot.h"
 #include "spm.h"
@@ -63,6 +63,7 @@
 	MSM_PM_DEBUG_SUSPEND_LIMITS = BIT(2),
 	MSM_PM_DEBUG_CLOCK = BIT(3),
 	MSM_PM_DEBUG_RESET_VECTOR = BIT(4),
+	MSM_PM_DEBUG_IDLE_CLK = BIT(5),
 	MSM_PM_DEBUG_IDLE = BIT(6),
 	MSM_PM_DEBUG_IDLE_LIMITS = BIT(7),
 	MSM_PM_DEBUG_HOTPLUG = BIT(8),
@@ -921,6 +922,9 @@
 		if (sleep_delay == 0) /* 0 would mean infinite time */
 			sleep_delay = 1;
 
+		if (MSM_PM_DEBUG_IDLE_CLK & msm_pm_debug_mask)
+			clock_debug_print_enabled();
+
 		ret = msm_rpmrs_enter_sleep(
 			sleep_delay, msm_pm_idle_rs_limits, true, notify_rpm);
 		if (!ret) {
diff --git a/arch/arm/mach-msm/pm.c b/arch/arm/mach-msm/pm.c
index 3dcbfb3..d684a5a 100644
--- a/arch/arm/mach-msm/pm.c
+++ b/arch/arm/mach-msm/pm.c
@@ -44,7 +44,7 @@
 #include "irq.h"
 #include "gpio.h"
 #include "timer.h"
-#include <mach/pm.h>
+#include "pm.h"
 #include "pm-boot.h"
 
 enum {
diff --git a/arch/arm/mach-msm/include/mach/pm.h b/arch/arm/mach-msm/pm.h
similarity index 88%
rename from arch/arm/mach-msm/include/mach/pm.h
rename to arch/arm/mach-msm/pm.h
index 689cd17..892472b 100644
--- a/arch/arm/mach-msm/include/mach/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -1,7 +1,7 @@
 /* arch/arm/mach-msm/pm.h
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  * Author: San Mehat <san@android.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -64,10 +64,14 @@
 
 void __init msm_pm_init_sleep_status_data(
 		struct msm_pm_sleep_status_data *sleep_data);
-#ifdef CONFIG_PM
+#ifdef CONFIG_MSM_PM8X60
 void msm_pm_set_rpm_wakeup_irq(unsigned int irq);
+int msm_pm_wait_cpu_shutdown(unsigned int cpu);
+bool msm_pm_verify_cpu_pc(unsigned int cpu);
 #else
 static inline void msm_pm_set_rpm_wakeup_irq(unsigned int irq) {}
+static inline int msm_pm_wait_cpu_shutdown(unsigned int cpu) { return 0; }
+static inline bool msm_pm_verify_cpu_pc(unsigned int cpu) { return true; }
 #endif
 
 #ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index 0518ea2..4cdd7ae 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -58,7 +58,7 @@
 #include "irq.h"
 #include "gpio.h"
 #include "timer.h"
-#include <mach/pm.h>
+#include "pm.h"
 #include "spm.h"
 #include "sirc.h"
 #include "pm-boot.h"
diff --git a/arch/arm/mach-msm/qdsp5/adsp_info.c b/arch/arm/mach-msm/qdsp5/adsp_info.c
index 62e385d..dea52bb 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_info.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_info.c
@@ -1,6 +1,6 @@
 /* arch/arm/mach-msm/adsp_info.c
  *
- * Copyright (c) 2008-2009, 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2011-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
@@ -89,7 +89,7 @@
 	QDSP_MODULE(RMTASK, NULL, 0, NULL, NULL),
 #if !defined(CONFIG_ARCH_MSM7X30)
 	QDSP_MODULE(AUDRECTASK, NULL, 0, NULL, NULL),
-	QDSP_MODULE(VFETASK, "vfe_clk", 0, adsp_vfe_verify_cmd,
+	QDSP_MODULE(VFETASK, NULL, 0, adsp_vfe_verify_cmd,
 		adsp_vfe_patch_event),
 	QDSP_MODULE(QCAMTASK, NULL, 0, NULL, NULL),
 	QDSP_MODULE(LPMTASK, NULL, 0, adsp_lpm_verify_cmd, NULL),
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c b/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
index 0ddba89..4b8b7a6 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * Based on the mp3 native driver in arch/arm/mach-msm/qdsp5v2/audio_mp3.c
  *
@@ -196,8 +196,10 @@
 static void audplay_config_hostpcm(struct audio *audio);
 static void audplay_buffer_refresh(struct audio *audio);
 static void audio_dsp_event(void *private, unsigned id, uint16_t *msg);
+#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audadpcm_post_event(struct audio *audio, int type,
 		union msm_audio_event_payload payload);
+#endif
 
 /* must be called with audio->lock held */
 static int audio_enable(struct audio *audio)
@@ -1433,6 +1435,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audadpcm_post_event(struct audio *audio, int type,
 		union msm_audio_event_payload payload)
 {
@@ -1461,7 +1464,6 @@
 	wake_up(&audio->event_wait);
 }
 
-#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audadpcm_suspend(struct early_suspend *h)
 {
 	struct audadpcm_suspend_ctl *ctl =
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c b/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
index 85a3daa..a09b71b 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
@@ -1,7 +1,7 @@
 /*
  * amrnb audio decoder device
  *
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
  *
  * Based on the mp3 native driver in arch/arm/mach-msm/qdsp5/audio_mp3.c
  *
@@ -194,8 +194,10 @@
 static void audamrnb_config_hostpcm(struct audio *audio);
 static void audamrnb_buffer_refresh(struct audio *audio);
 static void audamrnb_dsp_event(void *private, unsigned id, uint16_t *msg);
+#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audamrnb_post_event(struct audio *audio, int type,
 		union msm_audio_event_payload payload);
+#endif
 
 /* must be called with audio->lock held */
 static int audamrnb_enable(struct audio *audio)
@@ -1330,6 +1332,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audamrnb_post_event(struct audio *audio, int type,
 		union msm_audio_event_payload payload)
 {
@@ -1358,7 +1361,6 @@
 	wake_up(&audio->event_wait);
 }
 
-#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audamrnb_suspend(struct early_suspend *h)
 {
 	struct audamrnb_suspend_ctl *ctl =
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c b/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
index d6cf21d..48e9a9f 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
@@ -1,6 +1,6 @@
 /* amrwb audio decoder device
  *
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
  *
  * Based on the mp3 native driver in arch/arm/mach-msm/qdsp5v2/audio_mp3.c
  *
@@ -195,8 +195,10 @@
 static void audamrwb_config_hostpcm(struct audio *audio);
 static void audamrwb_buffer_refresh(struct audio *audio);
 static void audamrwb_dsp_event(void *private, unsigned id, uint16_t *msg);
+#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audamrwb_post_event(struct audio *audio, int type,
 		union msm_audio_event_payload payload);
+#endif
 
 /* must be called with audio->lock held */
 static int audamrwb_enable(struct audio *audio)
@@ -1414,6 +1416,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audamrwb_post_event(struct audio *audio, int type,
 		union msm_audio_event_payload payload)
 {
@@ -1442,7 +1445,6 @@
 	wake_up(&audio->event_wait);
 }
 
-#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audamrwb_suspend(struct early_suspend *h)
 {
 	struct audamrwb_suspend_ctl *ctl =
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_evrc.c b/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
index e5261b5..9b5694d 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
  *
  * This code also borrows from audio_aac.c, which is
  * Copyright (C) 2008 Google, Inc.
@@ -189,8 +189,10 @@
 static void audevrc_dsp_event(void *private, unsigned id, uint16_t *msg);
 static void audevrc_config_hostpcm(struct audio *audio);
 static void audevrc_buffer_refresh(struct audio *audio);
+#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audevrc_post_event(struct audio *audio, int type,
 		union msm_audio_event_payload payload);
+#endif
 
 /* must be called with audio->lock held */
 static int audevrc_enable(struct audio *audio)
@@ -1324,6 +1326,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audevrc_post_event(struct audio *audio, int type,
 		union msm_audio_event_payload payload)
 {
@@ -1352,7 +1355,6 @@
 	wake_up(&audio->event_wait);
 }
 
-#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audevrc_suspend(struct early_suspend *h)
 {
 	struct audevrc_suspend_ctl *ctl =
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_mp3.c b/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
index 0e61e84..c639833 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -112,6 +112,7 @@
 	int res = (IN_RANGE(__r1, __v) || IN_RANGE(__r1, __e));	\
 	res;							\
 })
+struct audio;
 
 struct buffer {
 	void *data;
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_pcm.c b/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
index 139c16c..b22820b 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -101,6 +101,8 @@
 	res;							\
 })
 
+struct audio;
+
 struct buffer {
 	void *data;
 	unsigned size;
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c b/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
index f3f0619..ce5d421 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
@@ -1,7 +1,7 @@
 /*
  * qcelp 13k audio decoder device
  *
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
  *
  * This code is based in part on audio_mp3.c, which is
  * Copyright (C) 2008 Google, Inc.
@@ -184,8 +184,10 @@
 static void audqcelp_config_hostpcm(struct audio *audio);
 static void audqcelp_buffer_refresh(struct audio *audio);
 static void audqcelp_dsp_event(void *private, unsigned id, uint16_t *msg);
+#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audqcelp_post_event(struct audio *audio, int type,
 		union msm_audio_event_payload payload);
+#endif
 
 /* must be called with audio->lock held */
 static int audqcelp_enable(struct audio *audio)
@@ -1326,6 +1328,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audqcelp_post_event(struct audio *audio, int type,
 		union msm_audio_event_payload payload)
 {
@@ -1354,7 +1357,6 @@
 	wake_up(&audio->event_wait);
 }
 
-#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audqcelp_suspend(struct early_suspend *h)
 {
 	struct audqcelp_suspend_ctl *ctl =
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_wma.c b/arch/arm/mach-msm/qdsp5v2/audio_wma.c
index 464f66e..f29b078 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_wma.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_wma.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * Based on the mp3 native driver in arch/arm/mach-msm/qdsp5v2/audio_mp3.c
  *
@@ -200,9 +200,10 @@
 static void audplay_config_hostpcm(struct audio *audio);
 static void audplay_buffer_refresh(struct audio *audio);
 static void audio_dsp_event(void *private, unsigned id, uint16_t *msg);
+#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audwma_post_event(struct audio *audio, int type,
 		union msm_audio_event_payload payload);
-
+#endif
 /* must be called with audio->lock held */
 static int audio_enable(struct audio *audio)
 {
@@ -1472,6 +1473,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audwma_post_event(struct audio *audio, int type,
 		union msm_audio_event_payload payload)
 {
@@ -1500,7 +1502,6 @@
 	wake_up(&audio->event_wait);
 }
 
-#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audwma_suspend(struct early_suspend *h)
 {
 	struct audwma_suspend_ctl *ctl =
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c b/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
index 878237e..cf25359 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * Based on the mp3 native driver in arch/arm/mach-msm/qdsp5v2/audio_mp3.c
  *
@@ -200,8 +200,10 @@
 static void audplay_config_hostpcm(struct audio *audio);
 static void audplay_buffer_refresh(struct audio *audio);
 static void audio_dsp_event(void *private, unsigned id, uint16_t *msg);
+#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audwmapro_post_event(struct audio *audio, int type,
 		union msm_audio_event_payload payload);
+#endif
 
 /* must be called with audio->lock held */
 static int audio_enable(struct audio *audio)
@@ -1484,6 +1486,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audwmapro_post_event(struct audio *audio, int type,
 		union msm_audio_event_payload payload)
 {
@@ -1512,7 +1515,6 @@
 	wake_up(&audio->event_wait);
 }
 
-#ifdef CONFIG_HAS_EARLYSUSPEND
 static void audwmapro_suspend(struct early_suspend *h)
 {
 	struct audwmapro_suspend_ctl *ctl =
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index 13d92d1..37428da 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.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
@@ -27,6 +27,7 @@
 #include <linux/sysfs.h>
 #include <linux/device.h>
 #include <linux/slab.h>
+#include <asm/mach-types.h>
 #include <mach/peripheral-loader.h>
 #include <mach/msm_smd.h>
 #include <mach/qdsp6v2/apr.h>
@@ -373,7 +374,11 @@
 		if (!q6.pil) {
 			pr_err("APR: Unable to load q6 image\n");
 			mutex_unlock(&q6.lock);
-			return svc;
+			/* Return failure if not intended for simulator */
+			if (!machine_is_apq8064_sim()) {
+				pr_debug("APR: Not apq8064 sim\n");
+				return svc;
+			}
 		}
 		q6.state = APR_Q6_LOADED;
 	}
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
index 37a6900..ce5d084 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
@@ -22,43 +22,52 @@
 
 #define MAX_NETWORKS		12
 
+struct sidetone_atomic_cal {
+	atomic_t	enable;
+	atomic_t	gain;
+};
+
+
 struct acdb_data {
 	struct mutex		acdb_mutex;
 
 	/* ANC Cal */
-	struct acdb_cal_block	anc_cal;
+	struct acdb_atomic_cal_block	anc_cal;
 
 	/* AudProc Cal */
-	uint32_t		asm_topology;
-	uint32_t		adm_topology[MAX_AUDPROC_TYPES];
-	struct acdb_cal_block	audproc_cal[MAX_AUDPROC_TYPES];
-	struct acdb_cal_block	audstrm_cal[MAX_AUDPROC_TYPES];
-	struct acdb_cal_block	audvol_cal[MAX_AUDPROC_TYPES];
+	atomic_t			asm_topology;
+	atomic_t			adm_topology[MAX_AUDPROC_TYPES];
+	struct acdb_atomic_cal_block	audproc_cal[MAX_AUDPROC_TYPES];
+	struct acdb_atomic_cal_block	audstrm_cal[MAX_AUDPROC_TYPES];
+	struct acdb_atomic_cal_block	audvol_cal[MAX_AUDPROC_TYPES];
 
 	/* VocProc Cal */
-	uint32_t                voice_rx_topology;
-	uint32_t                voice_tx_topology;
-	struct acdb_cal_block	vocproc_cal[MAX_NETWORKS];
-	struct acdb_cal_block	vocstrm_cal[MAX_NETWORKS];
-	struct acdb_cal_block	vocvol_cal[MAX_NETWORKS];
+	atomic_t			voice_rx_topology;
+	atomic_t			voice_tx_topology;
+	struct acdb_atomic_cal_block	vocproc_cal[MAX_NETWORKS];
+	struct acdb_atomic_cal_block	vocstrm_cal[MAX_NETWORKS];
+	struct acdb_atomic_cal_block	vocvol_cal[MAX_NETWORKS];
 	/* size of cal block tables above*/
-	uint32_t		vocproc_cal_size;
-	uint32_t		vocstrm_cal_size;
-	uint32_t		vocvol_cal_size;
+	atomic_t			vocproc_cal_size;
+	atomic_t			vocstrm_cal_size;
+	atomic_t			vocvol_cal_size;
 	/* Total size of cal data for all networks */
-	uint32_t		vocproc_total_cal_size;
-	uint32_t		vocstrm_total_cal_size;
-	uint32_t		vocvol_total_cal_size;
+	atomic_t			vocproc_total_cal_size;
+	atomic_t			vocstrm_total_cal_size;
+	atomic_t			vocvol_total_cal_size;
+
+	/* AFE cal */
+	struct acdb_atomic_cal_block	afe_cal[MAX_AUDPROC_TYPES];
 
 	/* Sidetone Cal */
-	struct sidetone_cal	sidetone_cal;
+	struct sidetone_atomic_cal	sidetone_cal;
 
 	/* PMEM information */
-	int			pmem_fd;
-	unsigned long		paddr;
-	unsigned long		kvaddr;
-	unsigned long		pmem_len;
-	struct file		*file;
+	atomic_t			pmem_fd;
+	atomic64_t			paddr;
+	atomic64_t			kvaddr;
+	atomic64_t			pmem_len;
+	struct file			*file;
 
 };
 
@@ -67,90 +76,105 @@
 
 uint32_t get_voice_rx_topology(void)
 {
-	return acdb_data.voice_rx_topology;
+	return atomic_read(&acdb_data.voice_rx_topology);
 }
 
 void store_voice_rx_topology(uint32_t topology)
 {
-	acdb_data.voice_rx_topology = topology;
+	atomic_set(&acdb_data.voice_rx_topology, topology);
 }
 
 uint32_t get_voice_tx_topology(void)
 {
-	return acdb_data.voice_tx_topology;
+	return atomic_read(&acdb_data.voice_tx_topology);
 }
 
 void store_voice_tx_topology(uint32_t topology)
 {
-	acdb_data.voice_tx_topology = topology;
+	atomic_set(&acdb_data.voice_tx_topology, topology);
 }
 
 uint32_t get_adm_rx_topology(void)
 {
-	return acdb_data.adm_topology[RX_CAL];
+	return atomic_read(&acdb_data.adm_topology[RX_CAL]);
 }
 
 void store_adm_rx_topology(uint32_t topology)
 {
-	acdb_data.adm_topology[RX_CAL] = topology;
+	atomic_set(&acdb_data.adm_topology[RX_CAL], topology);
 }
 
 uint32_t get_adm_tx_topology(void)
 {
-	return acdb_data.adm_topology[TX_CAL];
+	return atomic_read(&acdb_data.adm_topology[TX_CAL]);
 }
 
 void store_adm_tx_topology(uint32_t topology)
 {
-	acdb_data.adm_topology[TX_CAL] = topology;
+	atomic_set(&acdb_data.adm_topology[TX_CAL], topology);
 }
 
 uint32_t get_asm_topology(void)
 {
-	return acdb_data.asm_topology;
+	return atomic_read(&acdb_data.asm_topology);
 }
 
 void store_asm_topology(uint32_t topology)
 {
-	acdb_data.asm_topology = topology;
+	atomic_set(&acdb_data.asm_topology, topology);
 }
 
 void get_all_voice_cal(struct acdb_cal_block *cal_block)
 {
-	cal_block->cal_kvaddr = acdb_data.vocproc_cal[0].cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.vocproc_cal[0].cal_paddr;
-	cal_block->cal_size = acdb_data.vocproc_total_cal_size +
-				acdb_data.vocstrm_total_cal_size +
-				acdb_data.vocvol_total_cal_size;
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocproc_cal[0].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocproc_cal[0].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.vocproc_total_cal_size) +
+		atomic_read(&acdb_data.vocstrm_total_cal_size) +
+		atomic_read(&acdb_data.vocvol_total_cal_size);
 }
 
 void get_all_cvp_cal(struct acdb_cal_block *cal_block)
 {
-	cal_block->cal_kvaddr = acdb_data.vocproc_cal[0].cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.vocproc_cal[0].cal_paddr;
-	cal_block->cal_size = acdb_data.vocproc_total_cal_size +
-				acdb_data.vocvol_total_cal_size;
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocproc_cal[0].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocproc_cal[0].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.vocproc_total_cal_size) +
+		atomic_read(&acdb_data.vocvol_total_cal_size);
 }
 
 void get_all_vocproc_cal(struct acdb_cal_block *cal_block)
 {
-	cal_block->cal_kvaddr = acdb_data.vocproc_cal[0].cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.vocproc_cal[0].cal_paddr;
-	cal_block->cal_size = acdb_data.vocproc_total_cal_size;
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocproc_cal[0].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocproc_cal[0].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.vocproc_total_cal_size);
 }
 
 void get_all_vocstrm_cal(struct acdb_cal_block *cal_block)
 {
-	cal_block->cal_kvaddr = acdb_data.vocstrm_cal[0].cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.vocstrm_cal[0].cal_paddr;
-	cal_block->cal_size = acdb_data.vocstrm_total_cal_size;
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocstrm_cal[0].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocstrm_cal[0].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.vocstrm_total_cal_size);
 }
 
 void get_all_vocvol_cal(struct acdb_cal_block *cal_block)
 {
-	cal_block->cal_kvaddr = acdb_data.vocvol_cal[0].cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.vocvol_cal[0].cal_paddr;
-	cal_block->cal_size = acdb_data.vocvol_total_cal_size;
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocvol_cal[0].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocvol_cal[0].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.vocvol_total_cal_size);
 }
 
 void get_anc_cal(struct acdb_cal_block *cal_block)
@@ -162,13 +186,12 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	cal_block->cal_kvaddr = acdb_data.anc_cal.cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.anc_cal.cal_paddr;
-	cal_block->cal_size = acdb_data.anc_cal.cal_size;
-
-	mutex_unlock(&acdb_data.acdb_mutex);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.anc_cal.cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.anc_cal.cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.anc_cal.cal_size);
 done:
 	return;
 }
@@ -177,23 +200,69 @@
 {
 	pr_debug("%s,\n", __func__);
 
-	if (cal_block->cal_offset > acdb_data.pmem_len) {
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
 		pr_err("%s: offset %d is > pmem_len %ld\n",
 			__func__, cal_block->cal_offset,
-			acdb_data.pmem_len);
+			(long)atomic64_read(&acdb_data.pmem_len));
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
+	atomic_set(&acdb_data.anc_cal.cal_kvaddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	atomic_set(&acdb_data.anc_cal.cal_paddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.anc_cal.cal_size,
+		cal_block->cal_size);
+done:
+	return;
+}
 
-	acdb_data.anc_cal.cal_kvaddr =
-		cal_block->cal_offset + acdb_data.kvaddr;
-	acdb_data.anc_cal.cal_paddr =
-		cal_block->cal_offset + acdb_data.paddr;
-	acdb_data.anc_cal.cal_size =
-		cal_block->cal_size;
+void store_afe_cal(int32_t path, struct cal_block *cal_block)
+{
+	pr_debug("%s, path = %d\n", __func__, path);
 
-	mutex_unlock(&acdb_data.acdb_mutex);
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
+		pr_err("%s: offset %d is > pmem_len %ld\n",
+			__func__, cal_block->cal_offset,
+			(long)atomic64_read(&acdb_data.pmem_len));
+		goto done;
+	}
+	if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
+		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
+			__func__, path);
+		goto done;
+	}
+
+	atomic_set(&acdb_data.afe_cal[path].cal_kvaddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	atomic_set(&acdb_data.afe_cal[path].cal_paddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.afe_cal[path].cal_size,
+		cal_block->cal_size);
+done:
+	return;
+}
+
+void get_afe_cal(int32_t path, struct acdb_cal_block *cal_block)
+{
+	pr_debug("%s, path = %d\n", __func__, path);
+
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		goto done;
+	}
+	if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
+		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
+			__func__, path);
+		goto done;
+	}
+
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.afe_cal[path].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.afe_cal[path].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.afe_cal[path].cal_size);
 done:
 	return;
 }
@@ -202,12 +271,10 @@
 {
 	pr_debug("%s, path = %d\n", __func__, path);
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	if (cal_block->cal_offset > acdb_data.pmem_len) {
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
 		pr_err("%s: offset %d is > pmem_len %ld\n",
 			__func__, cal_block->cal_offset,
-			acdb_data.pmem_len);
+			(long)atomic64_read(&acdb_data.pmem_len));
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
@@ -216,15 +283,13 @@
 		goto done;
 	}
 
-	acdb_data.audproc_cal[path].cal_kvaddr =
-		cal_block->cal_offset + acdb_data.kvaddr;
-	acdb_data.audproc_cal[path].cal_paddr =
-		cal_block->cal_offset + acdb_data.paddr;
-	acdb_data.audproc_cal[path].cal_size =
-		cal_block->cal_size;
-
+	atomic_set(&acdb_data.audproc_cal[path].cal_kvaddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	atomic_set(&acdb_data.audproc_cal[path].cal_paddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.audproc_cal[path].cal_size,
+		cal_block->cal_size);
 done:
-	mutex_unlock(&acdb_data.acdb_mutex);
 	return;
 }
 
@@ -242,13 +307,12 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	cal_block->cal_kvaddr = acdb_data.audproc_cal[path].cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.audproc_cal[path].cal_paddr;
-	cal_block->cal_size = acdb_data.audproc_cal[path].cal_size;
-
-	mutex_unlock(&acdb_data.acdb_mutex);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.audproc_cal[path].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.audproc_cal[path].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.audproc_cal[path].cal_size);
 done:
 	return;
 }
@@ -257,12 +321,10 @@
 {
 	pr_debug("%s, path = %d\n", __func__, path);
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	if (cal_block->cal_offset > acdb_data.pmem_len) {
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
 		pr_err("%s: offset %d is > pmem_len %ld\n",
 			__func__, cal_block->cal_offset,
-			acdb_data.pmem_len);
+			(long)atomic64_read(&acdb_data.pmem_len));
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
@@ -271,15 +333,13 @@
 		goto done;
 	}
 
-	acdb_data.audstrm_cal[path].cal_kvaddr =
-		cal_block->cal_offset + acdb_data.kvaddr;
-	acdb_data.audstrm_cal[path].cal_paddr =
-		cal_block->cal_offset + acdb_data.paddr;
-	acdb_data.audstrm_cal[path].cal_size =
-		cal_block->cal_size;
-
+	atomic_set(&acdb_data.audstrm_cal[path].cal_kvaddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	atomic_set(&acdb_data.audstrm_cal[path].cal_paddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.audstrm_cal[path].cal_size,
+		cal_block->cal_size);
 done:
-	mutex_unlock(&acdb_data.acdb_mutex);
 	return;
 }
 
@@ -297,13 +357,12 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	cal_block->cal_kvaddr = acdb_data.audstrm_cal[path].cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.audstrm_cal[path].cal_paddr;
-	cal_block->cal_size = acdb_data.audstrm_cal[path].cal_size;
-
-	mutex_unlock(&acdb_data.acdb_mutex);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.audstrm_cal[path].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.audstrm_cal[path].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.audstrm_cal[path].cal_size);
 done:
 	return;
 }
@@ -312,12 +371,10 @@
 {
 	pr_debug("%s, path = %d\n", __func__, path);
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	if (cal_block->cal_offset > acdb_data.pmem_len) {
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
 		pr_err("%s: offset %d is > pmem_len %ld\n",
 			__func__, cal_block->cal_offset,
-			acdb_data.pmem_len);
+			(long)atomic64_read(&acdb_data.pmem_len));
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
@@ -326,15 +383,13 @@
 		goto done;
 	}
 
-	acdb_data.audvol_cal[path].cal_kvaddr =
-		cal_block->cal_offset + acdb_data.kvaddr;
-	acdb_data.audvol_cal[path].cal_paddr =
-		cal_block->cal_offset + acdb_data.paddr;
-	acdb_data.audvol_cal[path].cal_size =
-		cal_block->cal_size;
-
+	atomic_set(&acdb_data.audvol_cal[path].cal_kvaddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+	atomic_set(&acdb_data.audvol_cal[path].cal_paddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.audvol_cal[path].cal_size,
+		cal_block->cal_size);
 done:
-	mutex_unlock(&acdb_data.acdb_mutex);
 	return;
 }
 
@@ -352,13 +407,12 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	cal_block->cal_kvaddr = acdb_data.audvol_cal[path].cal_kvaddr;
-	cal_block->cal_paddr = acdb_data.audvol_cal[path].cal_paddr;
-	cal_block->cal_size = acdb_data.audvol_cal[path].cal_size;
-
-	mutex_unlock(&acdb_data.acdb_mutex);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.audvol_cal[path].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.audvol_cal[path].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.audvol_cal[path].cal_size);
 done:
 	return;
 }
@@ -375,31 +429,28 @@
 		goto done;
 	}
 
-
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	acdb_data.vocproc_total_cal_size = 0;
+	atomic_set(&acdb_data.vocproc_total_cal_size, 0);
 	for (i = 0; i < len; i++) {
-		if (cal_blocks[i].cal_offset > acdb_data.pmem_len) {
+		if (cal_blocks[i].cal_offset >
+					atomic64_read(&acdb_data.pmem_len)) {
 			pr_err("%s: offset %d is > pmem_len %ld\n",
 				__func__, cal_blocks[i].cal_offset,
-				acdb_data.pmem_len);
-			acdb_data.vocproc_cal[i].cal_size = 0;
+				(long)atomic64_read(&acdb_data.pmem_len));
+			atomic_set(&acdb_data.vocproc_cal[i].cal_size, 0);
 		} else {
-			acdb_data.vocproc_total_cal_size +=
-				cal_blocks[i].cal_size;
-			acdb_data.vocproc_cal[i].cal_size =
-				cal_blocks[i].cal_size;
-			acdb_data.vocproc_cal[i].cal_paddr =
+			atomic_add(cal_blocks[i].cal_size,
+				&acdb_data.vocproc_total_cal_size);
+			atomic_set(&acdb_data.vocproc_cal[i].cal_size,
+				cal_blocks[i].cal_size);
+			atomic_set(&acdb_data.vocproc_cal[i].cal_paddr,
 				cal_blocks[i].cal_offset +
-				acdb_data.paddr;
-			acdb_data.vocproc_cal[i].cal_kvaddr =
+				atomic64_read(&acdb_data.paddr));
+			atomic_set(&acdb_data.vocproc_cal[i].cal_kvaddr,
 				cal_blocks[i].cal_offset +
-				acdb_data.kvaddr;
+				atomic64_read(&acdb_data.kvaddr));
 		}
 	}
-	acdb_data.vocproc_cal_size = len;
-	mutex_unlock(&acdb_data.acdb_mutex);
+	atomic_set(&acdb_data.vocproc_cal_size, len);
 done:
 	return;
 }
@@ -413,12 +464,8 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	cal_data->num_cal_blocks = acdb_data.vocproc_cal_size;
+	cal_data->num_cal_blocks = atomic_read(&acdb_data.vocproc_cal_size);
 	cal_data->cal_blocks = &acdb_data.vocproc_cal[0];
-
-	mutex_unlock(&acdb_data.acdb_mutex);
 done:
 	return;
 }
@@ -434,30 +481,28 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	acdb_data.vocstrm_total_cal_size = 0;
+	atomic_set(&acdb_data.vocstrm_total_cal_size, 0);
 	for (i = 0; i < len; i++) {
-		if (cal_blocks[i].cal_offset > acdb_data.pmem_len) {
+		if (cal_blocks[i].cal_offset >
+					atomic64_read(&acdb_data.pmem_len)) {
 			pr_err("%s: offset %d is > pmem_len %ld\n",
 				__func__, cal_blocks[i].cal_offset,
-				acdb_data.pmem_len);
-			acdb_data.vocstrm_cal[i].cal_size = 0;
+				(long)atomic64_read(&acdb_data.pmem_len));
+			atomic_set(&acdb_data.vocstrm_cal[i].cal_size, 0);
 		} else {
-			acdb_data.vocstrm_total_cal_size +=
-				cal_blocks[i].cal_size;
-			acdb_data.vocstrm_cal[i].cal_size =
-				cal_blocks[i].cal_size;
-			acdb_data.vocstrm_cal[i].cal_paddr =
+			atomic_add(cal_blocks[i].cal_size,
+				&acdb_data.vocstrm_total_cal_size);
+			atomic_set(&acdb_data.vocstrm_cal[i].cal_size,
+				cal_blocks[i].cal_size);
+			atomic_set(&acdb_data.vocstrm_cal[i].cal_paddr,
 				cal_blocks[i].cal_offset +
-				acdb_data.paddr;
-			acdb_data.vocstrm_cal[i].cal_kvaddr =
+				atomic64_read(&acdb_data.paddr));
+			atomic_set(&acdb_data.vocstrm_cal[i].cal_kvaddr,
 				cal_blocks[i].cal_offset +
-				acdb_data.kvaddr;
+				atomic64_read(&acdb_data.kvaddr));
 		}
 	}
-	acdb_data.vocstrm_cal_size = len;
-	mutex_unlock(&acdb_data.acdb_mutex);
+	atomic_set(&acdb_data.vocstrm_cal_size, len);
 done:
 	return;
 }
@@ -471,12 +516,8 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	cal_data->num_cal_blocks = acdb_data.vocstrm_cal_size;
+	cal_data->num_cal_blocks = atomic_read(&acdb_data.vocstrm_cal_size);
 	cal_data->cal_blocks = &acdb_data.vocstrm_cal[0];
-
-	mutex_unlock(&acdb_data.acdb_mutex);
 done:
 	return;
 }
@@ -492,30 +533,28 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	acdb_data.vocvol_total_cal_size = 0;
+	atomic_set(&acdb_data.vocvol_total_cal_size, 0);
 	for (i = 0; i < len; i++) {
-		if (cal_blocks[i].cal_offset > acdb_data.pmem_len) {
+		if (cal_blocks[i].cal_offset >
+					atomic64_read(&acdb_data.pmem_len)) {
 			pr_err("%s: offset %d is > pmem_len %ld\n",
 				__func__, cal_blocks[i].cal_offset,
-				acdb_data.pmem_len);
-			acdb_data.vocvol_cal[i].cal_size = 0;
+				(long)atomic64_read(&acdb_data.pmem_len));
+			atomic_set(&acdb_data.vocvol_cal[i].cal_size, 0);
 		} else {
-			acdb_data.vocvol_total_cal_size +=
-				cal_blocks[i].cal_size;
-			acdb_data.vocvol_cal[i].cal_size =
-				cal_blocks[i].cal_size;
-			acdb_data.vocvol_cal[i].cal_paddr =
+			atomic_add(cal_blocks[i].cal_size,
+				&acdb_data.vocvol_total_cal_size);
+			atomic_set(&acdb_data.vocvol_cal[i].cal_size,
+				cal_blocks[i].cal_size);
+			atomic_set(&acdb_data.vocvol_cal[i].cal_paddr,
 				cal_blocks[i].cal_offset +
-				acdb_data.paddr;
-			acdb_data.vocvol_cal[i].cal_kvaddr =
+				atomic64_read(&acdb_data.paddr));
+			atomic_set(&acdb_data.vocvol_cal[i].cal_kvaddr,
 				cal_blocks[i].cal_offset +
-				acdb_data.kvaddr;
+				atomic64_read(&acdb_data.kvaddr));
 		}
 	}
-	acdb_data.vocvol_cal_size = len;
-	mutex_unlock(&acdb_data.acdb_mutex);
+	atomic_set(&acdb_data.vocvol_cal_size, len);
 done:
 	return;
 }
@@ -529,12 +568,8 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	cal_data->num_cal_blocks = acdb_data.vocvol_cal_size;
+	cal_data->num_cal_blocks = atomic_read(&acdb_data.vocvol_cal_size);
 	cal_data->cal_blocks = &acdb_data.vocvol_cal[0];
-
-	mutex_unlock(&acdb_data.acdb_mutex);
 done:
 	return;
 }
@@ -543,12 +578,8 @@
 {
 	pr_debug("%s\n", __func__);
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	acdb_data.sidetone_cal.enable = cal_data->enable;
-	acdb_data.sidetone_cal.gain = cal_data->gain;
-
-	mutex_unlock(&acdb_data.acdb_mutex);
+	atomic_set(&acdb_data.sidetone_cal.enable, cal_data->enable);
+	atomic_set(&acdb_data.sidetone_cal.gain, cal_data->gain);
 }
 
 
@@ -561,12 +592,8 @@
 		goto done;
 	}
 
-	mutex_lock(&acdb_data.acdb_mutex);
-
-	cal_data->enable = acdb_data.sidetone_cal.enable;
-	cal_data->gain = acdb_data.sidetone_cal.gain;
-
-	mutex_unlock(&acdb_data.acdb_mutex);
+	cal_data->enable = atomic_read(&acdb_data.sidetone_cal.enable);
+	cal_data->gain = atomic_read(&acdb_data.sidetone_cal.gain);
 done:
 	return;
 }
@@ -574,14 +601,12 @@
 static int acdb_open(struct inode *inode, struct file *f)
 {
 	s32 result = 0;
-	pr_info("%s\n", __func__);
+	pr_debug("%s\n", __func__);
 
-	mutex_lock(&acdb_data.acdb_mutex);
-	if (acdb_data.pmem_fd) {
-		pr_info("%s: ACDB opened but PMEM allocated, using existing PMEM!\n",
+	if (atomic_read(&acdb_data.pmem_fd)) {
+		pr_debug("%s: ACDB opened but PMEM allocated, using existing PMEM!\n",
 			__func__);
 	}
-	mutex_unlock(&acdb_data.acdb_mutex);
 
 	atomic_inc(&usage_count);
 	return result;
@@ -589,9 +614,11 @@
 
 static int deregister_pmem(void)
 {
-	if (acdb_data.pmem_fd) {
+	if (atomic_read(&acdb_data.pmem_fd)) {
+		mutex_lock(&acdb_data.acdb_mutex);
 		put_pmem_file(acdb_data.file);
-		acdb_data.pmem_fd = 0;
+		mutex_unlock(&acdb_data.acdb_mutex);
+		atomic_set(&acdb_data.pmem_fd, 0);
 	}
 	return 0;
 }
@@ -599,19 +626,30 @@
 static int register_pmem(void)
 {
 	int result;
+	unsigned long paddr;
+	unsigned long kvaddr;
+	unsigned long pmem_len;
 
-	result = get_pmem_file(acdb_data.pmem_fd, &acdb_data.paddr,
-				&acdb_data.kvaddr, &acdb_data.pmem_len,
+	mutex_lock(&acdb_data.acdb_mutex);
+	result = get_pmem_file(atomic_read(&acdb_data.pmem_fd),
+				&paddr, &kvaddr, &pmem_len,
 				&acdb_data.file);
+	mutex_unlock(&acdb_data.acdb_mutex);
 	if (result != 0) {
-		acdb_data.pmem_fd = 0;
+		atomic_set(&acdb_data.pmem_fd, 0);
+		atomic64_set(&acdb_data.pmem_len, 0);
 		pr_err("%s: Could not register PMEM!!!\n", __func__);
 		goto done;
 	}
 
+	atomic64_set(&acdb_data.paddr, paddr);
+	atomic64_set(&acdb_data.kvaddr, kvaddr);
+	atomic64_set(&acdb_data.pmem_len, pmem_len);
 	pr_debug("AUDIO_REGISTER_PMEM done! paddr = 0x%lx, "
-		"kvaddr = 0x%lx, len = x%lx\n", acdb_data.paddr,
-		acdb_data.kvaddr, acdb_data.pmem_len);
+		"kvaddr = 0x%lx, len = x%lx\n",
+		(long)atomic64_read(&acdb_data.paddr),
+		(long)atomic64_read(&acdb_data.kvaddr),
+		(long)atomic64_read(&acdb_data.pmem_len));
 
 done:
 	return result;
@@ -619,37 +657,33 @@
 static long acdb_ioctl(struct file *f,
 		unsigned int cmd, unsigned long arg)
 {
-	s32			result = 0;
-	s32			audproc_path;
-	s32			size;
-	u32			topology;
+	int32_t			result = 0;
+	int32_t			size;
+	int32_t			pmem_fd;
+	uint32_t		topology;
 	struct cal_block	data[MAX_NETWORKS];
 	pr_debug("%s\n", __func__);
 
 	switch (cmd) {
 	case AUDIO_REGISTER_PMEM:
 		pr_debug("AUDIO_REGISTER_PMEM\n");
-		mutex_lock(&acdb_data.acdb_mutex);
-		if (acdb_data.pmem_fd) {
+		if (atomic_read(&acdb_data.pmem_fd)) {
 			deregister_pmem();
-			pr_info("Remove the existing PMEM\n");
+			pr_debug("Remove the existing PMEM\n");
 		}
 
-		if (copy_from_user(&acdb_data.pmem_fd, (void *)arg,
-					sizeof(acdb_data.pmem_fd))) {
+		if (copy_from_user(&pmem_fd, (void *)arg, sizeof(pmem_fd))) {
 			pr_err("%s: fail to copy pmem handle!\n", __func__);
 			result = -EFAULT;
 		} else {
+			atomic_set(&acdb_data.pmem_fd, pmem_fd);
 			result = register_pmem();
 		}
-		mutex_unlock(&acdb_data.acdb_mutex);
 		goto done;
 
 	case AUDIO_DEREGISTER_PMEM:
 		pr_debug("AUDIO_DEREGISTER_PMEM\n");
-		mutex_lock(&acdb_data.acdb_mutex);
 		deregister_pmem();
-		mutex_unlock(&acdb_data.acdb_mutex);
 		goto done;
 	case AUDIO_SET_VOICE_RX_TOPOLOGY:
 		if (copy_from_user(&topology, (void *)arg,
@@ -721,45 +755,52 @@
 
 	switch (cmd) {
 	case AUDIO_SET_AUDPROC_TX_CAL:
-		audproc_path = TX_CAL;
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audproc_cal(audproc_path, data);
+		store_audproc_cal(TX_CAL, data);
 		break;
 	case AUDIO_SET_AUDPROC_RX_CAL:
-		audproc_path = RX_CAL;
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audproc_cal(audproc_path, data);
+		store_audproc_cal(RX_CAL, data);
 		break;
 	case AUDIO_SET_AUDPROC_TX_STREAM_CAL:
-		audproc_path = TX_CAL;
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audstrm_cal(audproc_path, data);
+		store_audstrm_cal(TX_CAL, data);
 		break;
 	case AUDIO_SET_AUDPROC_RX_STREAM_CAL:
-		audproc_path = RX_CAL;
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audstrm_cal(audproc_path, data);
+		store_audstrm_cal(RX_CAL, data);
 		break;
 	case AUDIO_SET_AUDPROC_TX_VOL_CAL:
-		audproc_path = TX_CAL;
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audvol_cal(audproc_path, data);
+		store_audvol_cal(TX_CAL, data);
+		break;
 	case AUDIO_SET_AUDPROC_RX_VOL_CAL:
-		audproc_path = RX_CAL;
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audvol_cal(audproc_path, data);
+		store_audvol_cal(RX_CAL, data);
+		break;
+	case AUDIO_SET_AFE_TX_CAL:
+		if (size > sizeof(struct cal_block))
+			pr_err("%s: More AFE Cal then expected, "
+				"size received: %d\n", __func__, size);
+		store_afe_cal(TX_CAL, data);
+		break;
+	case AUDIO_SET_AFE_RX_CAL:
+		if (size > sizeof(struct cal_block))
+			pr_err("%s: More AFE Cal then expected, "
+				"size received: %d\n", __func__, size);
+		store_afe_cal(RX_CAL, data);
 		break;
 	case AUDIO_SET_VOCPROC_CAL:
 		store_vocproc_cal(size / sizeof(struct cal_block), data);
@@ -794,14 +835,13 @@
 
 	pr_debug("%s\n", __func__);
 
-	mutex_lock(&acdb_data.acdb_mutex);
-	if (acdb_data.pmem_fd) {
-		if (size <= acdb_data.pmem_len) {
+	if (atomic_read(&acdb_data.pmem_fd)) {
+		if (size <= atomic64_read(&acdb_data.pmem_len)) {
 			vma->vm_page_prot = pgprot_noncached(
 						vma->vm_page_prot);
 			result = remap_pfn_range(vma,
 				vma->vm_start,
-				acdb_data.paddr >> PAGE_SHIFT,
+				atomic64_read(&acdb_data.paddr) >> PAGE_SHIFT,
 				size,
 				vma->vm_page_prot);
 		} else {
@@ -812,7 +852,6 @@
 		pr_err("%s: PMEM is not allocated, yet!\n", __func__);
 		result = -ENODEV;
 	}
-	mutex_unlock(&acdb_data.acdb_mutex);
 
 	return result;
 }
@@ -824,16 +863,13 @@
 	atomic_dec(&usage_count);
 	atomic_read(&usage_count);
 
-	pr_info("%s: ref count %d!\n", __func__,
+	pr_debug("%s: ref count %d!\n", __func__,
 		atomic_read(&usage_count));
 
-	if (atomic_read(&usage_count) >= 1) {
+	if (atomic_read(&usage_count) >= 1)
 		result = -EBUSY;
-	} else {
-		mutex_lock(&acdb_data.acdb_mutex);
+	else
 		result = deregister_pmem();
-		mutex_unlock(&acdb_data.acdb_mutex);
-	}
 
 	return result;
 }
diff --git a/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c b/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c
index 51a209d..0181cb5 100644
--- a/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c
+++ b/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.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
@@ -2229,7 +2229,7 @@
 };
 
 static struct adie_codec_action_unit ftm_spkr_r_adie_lp_rx_actions[] =
-	FTM_SPKR_RX_LB;
+	SPKR_R_RX;
 
 static struct adie_codec_hwsetting_entry ftm_spkr_r_adie_lp_rx_settings[] = {
 	{
@@ -2699,7 +2699,10 @@
 
 		platform_add_devices(snd_devices_fluid,
 		ARRAY_SIZE(snd_devices_fluid));
-	} else if (machine_is_msm8x60_surf()) {
+	}
+	if (machine_is_msm8x60_surf() || machine_is_msm8x60_ffa()
+		|| machine_is_msm8x60_fusion()
+		|| machine_is_msm8x60_fusn_ffa()) {
 		for (i = 0; i < ARRAY_SIZE(snd_devices_ftm); i++)
 			snd_devices_ftm[i]->id = dev_id++;
 
diff --git a/arch/arm/mach-msm/qdsp6v2/q6voice.c b/arch/arm/mach-msm/qdsp6v2/q6voice.c
index 34169c0..12a02c5 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6voice.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6voice.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
@@ -791,7 +791,7 @@
 	struct apr_hdr cvs_cal_cmd_hdr;
 	uint32_t *cmd_buf;
 	struct acdb_cal_data cal_data;
-	struct acdb_cal_block *cal_blk;
+	struct acdb_atomic_cal_block *cal_blk;
 	int32_t cal_size_per_network;
 	uint32_t *cal_data_per_network;
 	int index = 0;
@@ -830,11 +830,12 @@
 	pr_debug("cal_blk =%x\n", (uint32_t)cal_data.cal_blocks);
 
 	for (; index < cal_data.num_cal_blocks; index++) {
-		cal_size_per_network = cal_blk[index].cal_size;
+		cal_size_per_network = atomic_read(&cal_blk[index].cal_size);
 		pr_debug(" cal size =%d\n", cal_size_per_network);
 		if (cal_size_per_network >= BUFFER_PAYLOAD_SIZE)
 			pr_err("Cal size is too big\n");
-		cal_data_per_network = (u32 *)cal_blk[index].cal_kvaddr;
+		cal_data_per_network =
+			(u32 *)atomic_read(&cal_blk[index].cal_kvaddr);
 		pr_debug(" cal data=%x\n", (uint32_t)cal_data_per_network);
 		cvs_cal_cmd_hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
 			cal_size_per_network);
@@ -868,7 +869,7 @@
 	struct apr_hdr cvp_cal_cmd_hdr;
 	uint32_t *cmd_buf;
 	struct acdb_cal_data cal_data;
-	struct acdb_cal_block *cal_blk;
+	struct acdb_atomic_cal_block *cal_blk;
 	int32_t cal_size_per_network;
 	uint32_t *cal_data_per_network;
 	int index = 0;
@@ -907,11 +908,12 @@
 	pr_debug(" cal_blk =%x\n", (uint32_t)cal_data.cal_blocks);
 
 	for (; index < cal_data.num_cal_blocks; index++) {
-		cal_size_per_network = cal_blk[index].cal_size;
+		cal_size_per_network = atomic_read(&cal_blk[index].cal_size);
 		if (cal_size_per_network >= BUFFER_PAYLOAD_SIZE)
 			pr_err("Cal size is too big\n");
 		pr_debug(" cal size =%d\n", cal_size_per_network);
-		cal_data_per_network = (u32 *)cal_blk[index].cal_kvaddr;
+		cal_data_per_network =
+			(u32 *)atomic_read(&cal_blk[index].cal_kvaddr);
 		pr_debug(" cal data=%x\n", (uint32_t)cal_data_per_network);
 
 		cvp_cal_cmd_hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
@@ -945,11 +947,9 @@
 	struct apr_hdr cvp_vol_cal_cmd_hdr;
 	uint32_t *cmd_buf;
 	struct acdb_cal_data cal_data;
-	struct acdb_cal_block *cal_blk;
+	struct acdb_atomic_cal_block *cal_blk;
 	int32_t cal_size_per_network;
 	uint32_t *cal_data_per_network;
-	uint32_t num_volume_steps;
-	int offset = 0;
 	int index = 0;
 	int ret = 0;
 	void *apr_cvp = voice_get_apr_cvp();
@@ -986,27 +986,18 @@
 	pr_debug("Cal_blk =%x\n", (uint32_t)cal_data.cal_blocks);
 
 	for (; index < cal_data.num_cal_blocks; index++) {
-		cal_size_per_network = cal_blk[index].cal_size;
-		cal_data_per_network = (u32 *)cal_blk[index].cal_kvaddr;
-
-		/* Number of volume steps are only included in the */
-		/* first block, need to be inserted into the rest */
-		if (index != 0) {
-			offset = sizeof(num_volume_steps);
-			memcpy(cmd_buf + (APR_HDR_SIZE / sizeof(uint32_t)),
-				&num_volume_steps, offset);
-		} else {
-			num_volume_steps = *cal_data_per_network;
-		}
+		cal_size_per_network = atomic_read(&cal_blk[index].cal_size);
+		cal_data_per_network =
+			(u32 *)atomic_read(&cal_blk[index].cal_kvaddr);
 
 		pr_debug("Cal size =%d, index=%d\n", cal_size_per_network,
 			index);
 		pr_debug("Cal data=%x\n", (uint32_t)cal_data_per_network);
 		cvp_vol_cal_cmd_hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
-			cal_size_per_network + offset);
+			cal_size_per_network);
 		memcpy(cmd_buf, &cvp_vol_cal_cmd_hdr,  APR_HDR_SIZE);
-		memcpy(cmd_buf + (APR_HDR_SIZE / sizeof(uint32_t)) +
-			offset, cal_data_per_network, cal_size_per_network);
+		memcpy(cmd_buf + (APR_HDR_SIZE / sizeof(uint32_t)),
+			cal_data_per_network, cal_size_per_network);
 		pr_debug("Send vol table\n");
 
 		v->cvp_state = CMD_STATUS_FAIL;
diff --git a/arch/arm/mach-msm/qdsp6v2/timpani_profile_8x60.h b/arch/arm/mach-msm/qdsp6v2/timpani_profile_8x60.h
index e747957..f02e0a0 100644
--- a/arch/arm/mach-msm/qdsp6v2/timpani_profile_8x60.h
+++ b/arch/arm/mach-msm/qdsp6v2/timpani_profile_8x60.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -888,7 +888,7 @@
 	{ADIE_CODEC_ACTION_ENTRY, ADIE_CODEC_PACK_ENTRY(0x31, 0xFF, 0xC5)}, \
 	{ADIE_CODEC_ACTION_ENTRY, ADIE_CODEC_PACK_ENTRY(0x4C, 0xFF, 0x29)}, \
 	{ADIE_CODEC_ACTION_DELAY_WAIT, 0xBB8}, \
-	{ADIE_CODEC_ACTION_ENTRY, ADIE_CODEC_PACK_ENTRY(0x31, 0xFF, 0xF5)}, \
+	{ADIE_CODEC_ACTION_ENTRY, ADIE_CODEC_PACK_ENTRY(0x31, 0xFF, 0xC5)}, \
 	{ADIE_CODEC_ACTION_ENTRY, ADIE_CODEC_PACK_ENTRY(0xE2, 0xFE, 0xAC)}, \
 	{ADIE_CODEC_ACTION_ENTRY, ADIE_CODEC_PACK_ENTRY(0xE3, 0xFE, 0xAC)}, \
 	{ADIE_CODEC_ACTION_ENTRY, ADIE_CODEC_PACK_ENTRY(0x3C, 0x27, 0x20)}, \
@@ -1906,6 +1906,7 @@
 	{ADIE_CODEC_ACTION_ENTRY, ADIE_CODEC_PACK_ENTRY(0xE0, 0xFE, 0xAC)}, \
 	{ADIE_CODEC_ACTION_ENTRY, ADIE_CODEC_PACK_ENTRY(0xE1, 0xFE, 0xAC)}, \
 	{ADIE_CODEC_ACTION_ENTRY, ADIE_CODEC_PACK_ENTRY(0x3A, 0x24, 0x24)}, \
+	{ADIE_CODEC_ACTION_DELAY_WAIT, 0x4E1F}, \
 	{ADIE_CODEC_ACTION_ENTRY, ADIE_CODEC_PACK_ENTRY(0xE0, 0xFE, 0x3C)}, \
 	{ADIE_CODEC_ACTION_ENTRY, ADIE_CODEC_PACK_ENTRY(0xE1, 0xFE, 0x3C)}, \
 	{ADIE_CODEC_ACTION_ENTRY, ADIE_CODEC_PACK_ENTRY(0xE0, 0xFE, 0x1C)}, \
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/rpm-regulator-8930.c b/arch/arm/mach-msm/rpm-regulator-8930.c
new file mode 100644
index 0000000..22595ec
--- /dev/null
+++ b/arch/arm/mach-msm/rpm-regulator-8930.c
@@ -0,0 +1,269 @@
+/*
+ * 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.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include "rpm-regulator-private.h"
+
+/* RPM regulator request formats */
+static struct rpm_vreg_parts ldo_parts = {
+	.request_len	= 2,
+	.uV		= REQUEST_MEMBER(0, 0x007FFFFF,  0),
+	.pd		= REQUEST_MEMBER(0, 0x00800000, 23),
+	.pc		= REQUEST_MEMBER(0, 0x0F000000, 24),
+	.pf		= REQUEST_MEMBER(0, 0xF0000000, 28),
+	.ip		= REQUEST_MEMBER(1, 0x000003FF,  0),
+	.ia		= REQUEST_MEMBER(1, 0x000FFC00, 10),
+	.fm		= REQUEST_MEMBER(1, 0x00700000, 20),
+};
+
+static struct rpm_vreg_parts smps_parts = {
+	.request_len	= 2,
+	.uV		= REQUEST_MEMBER(0, 0x007FFFFF,  0),
+	.pd		= REQUEST_MEMBER(0, 0x00800000, 23),
+	.pc		= REQUEST_MEMBER(0, 0x0F000000, 24),
+	.pf		= REQUEST_MEMBER(0, 0xF0000000, 28),
+	.ip		= REQUEST_MEMBER(1, 0x000003FF,  0),
+	.ia		= REQUEST_MEMBER(1, 0x000FFC00, 10),
+	.fm		= REQUEST_MEMBER(1, 0x00700000, 20),
+	.pm		= REQUEST_MEMBER(1, 0x00800000, 23),
+	.freq		= REQUEST_MEMBER(1, 0x1F000000, 24),
+	.freq_clk_src	= REQUEST_MEMBER(1, 0x60000000, 29),
+};
+
+static struct rpm_vreg_parts switch_parts = {
+	.request_len	= 1,
+	.enable_state	= REQUEST_MEMBER(0, 0x00000001,  0),
+	.pd		= REQUEST_MEMBER(0, 0x00000002,  1),
+	.pc		= REQUEST_MEMBER(0, 0x0000003C,  2),
+	.pf		= REQUEST_MEMBER(0, 0x000003C0,  6),
+	.hpm		= REQUEST_MEMBER(0, 0x00000C00, 10),
+};
+
+/* Physically available PMIC regulator voltage setpoint ranges */
+static struct vreg_range pldo_ranges[] = {
+	VOLTAGE_RANGE( 750000, 1487500, 12500),
+	VOLTAGE_RANGE(1500000, 3075000, 25000),
+	VOLTAGE_RANGE(3100000, 4900000, 50000),
+};
+
+static struct vreg_range nldo_ranges[] = {
+	VOLTAGE_RANGE( 750000, 1537500, 12500),
+};
+
+static struct vreg_range nldo1200_ranges[] = {
+	VOLTAGE_RANGE( 375000,  743750,  6250),
+	VOLTAGE_RANGE( 750000, 1537500, 12500),
+};
+
+static struct vreg_range smps_ranges[] = {
+	VOLTAGE_RANGE( 375000,  737500, 12500),
+	VOLTAGE_RANGE( 750000, 1487500, 12500),
+	VOLTAGE_RANGE(1500000, 3075000, 25000),
+};
+
+static struct vreg_range ftsmps_ranges[] = {
+	VOLTAGE_RANGE( 350000,  650000, 50000),
+	VOLTAGE_RANGE( 700000, 1400000, 12500),
+	VOLTAGE_RANGE(1500000, 3300000, 50000),
+};
+
+static struct vreg_set_points pldo_set_points = SET_POINTS(pldo_ranges);
+static struct vreg_set_points nldo_set_points = SET_POINTS(nldo_ranges);
+static struct vreg_set_points nldo1200_set_points = SET_POINTS(nldo1200_ranges);
+static struct vreg_set_points smps_set_points = SET_POINTS(smps_ranges);
+static struct vreg_set_points ftsmps_set_points = SET_POINTS(ftsmps_ranges);
+
+static struct vreg_set_points *all_set_points[] = {
+	&pldo_set_points,
+	&nldo_set_points,
+	&nldo1200_set_points,
+	&smps_set_points,
+	&ftsmps_set_points,
+};
+
+#define LDO(_id, _name, _name_pc, _ranges, _hpm_min_load) \
+	[RPM_VREG_ID_PM8038_##_id] = { \
+		.req = { \
+			[0] = { .id = MSM_RPM_ID_PM8038_##_id##_0, }, \
+			[1] = { .id = MSM_RPM_ID_PM8038_##_id##_1, }, \
+		}, \
+		.hpm_min_load  = RPM_VREG_8930_##_hpm_min_load##_HPM_MIN_LOAD, \
+		.type		 = RPM_REGULATOR_TYPE_LDO, \
+		.set_points	 = &_ranges##_set_points, \
+		.part		 = &ldo_parts, \
+		.id		 = RPM_VREG_ID_PM8038_##_id, \
+		.rdesc.name	 = _name, \
+		.rdesc_pc.name	 = _name_pc, \
+	}
+
+#define SMPS(_id, _name, _name_pc, _ranges, _hpm_min_load) \
+	[RPM_VREG_ID_PM8038_##_id] = { \
+		.req = { \
+			[0] = { .id = MSM_RPM_ID_PM8038_##_id##_0, }, \
+			[1] = { .id = MSM_RPM_ID_PM8038_##_id##_1, }, \
+		}, \
+		.hpm_min_load  = RPM_VREG_8930_##_hpm_min_load##_HPM_MIN_LOAD, \
+		.type		 = RPM_REGULATOR_TYPE_SMPS, \
+		.set_points	 = &_ranges##_set_points, \
+		.part		 = &smps_parts, \
+		.id		 = RPM_VREG_ID_PM8038_##_id, \
+		.rdesc.name	 = _name, \
+		.rdesc_pc.name	 = _name_pc, \
+	}
+
+#define LVS(_id, _name, _name_pc) \
+	[RPM_VREG_ID_PM8038_##_id] = { \
+		.req = { \
+			[0] = { .id = MSM_RPM_ID_PM8038_##_id, }, \
+			[1] = { .id = -1, }, \
+		}, \
+		.type		 = RPM_REGULATOR_TYPE_VS, \
+		.part		 = &switch_parts, \
+		.id		 = RPM_VREG_ID_PM8038_##_id, \
+		.rdesc.name	 = _name, \
+		.rdesc_pc.name	 = _name_pc, \
+	}
+
+static struct vreg vregs[] = {
+	LDO(L1,   "8038_l1",   NULL,          nldo1200, LDO_1200),
+	LDO(L2,   "8038_l2",   "8038_l2_pc",  nldo,     LDO_150),
+	LDO(L3,   "8038_l3",   "8038_l3_pc",  pldo,     LDO_50),
+	LDO(L4,   "8038_l4",   "8038_l4_pc",  pldo,     LDO_50),
+	LDO(L5,   "8038_l5",   "8038_l5_pc",  pldo,     LDO_600),
+	LDO(L6,   "8038_l6",   "8038_l6_pc",  pldo,     LDO_600),
+	LDO(L7,   "8038_l7",   "8038_l7_pc",  pldo,     LDO_600),
+	LDO(L8,   "8038_l8",   "8038_l8_pc",  pldo,     LDO_300),
+	LDO(L9,   "8038_l9",   "8038_l9_pc",  pldo,     LDO_300),
+	LDO(L10,  "8038_l10",  "8038_l10_pc", pldo,     LDO_600),
+	LDO(L11,  "8038_l11",  "8038_l11_pc", pldo,     LDO_600),
+	LDO(L12,  "8038_l12",  "8038_l12_pc", nldo,     LDO_300),
+	LDO(L14,  "8038_l14",  "8038_l14_pc", pldo,     LDO_50),
+	LDO(L15,  "8038_l15",  "8038_l15_pc", pldo,     LDO_150),
+	LDO(L16,  "8038_l16",  NULL,          nldo1200, LDO_1200),
+	LDO(L17,  "8038_l17",  "8038_l17_pc", pldo,     LDO_150),
+	LDO(L18,  "8038_l18",  "8038_l18_pc", pldo,     LDO_50),
+	LDO(L19,  "8038_l19",  NULL,          nldo1200, LDO_1200),
+	LDO(L20,  "8038_l20",  NULL,          nldo1200, LDO_1200),
+	LDO(L21,  "8038_l21",  "8038_l21_pc", pldo,     LDO_150),
+	LDO(L22,  "8038_l22",  "8038_l22_pc", pldo,     LDO_50),
+	LDO(L23,  "8038_l23",  "8038_l23_pc", pldo,     LDO_50),
+	LDO(L24,  "8038_l24",  NULL,          nldo1200, LDO_1200),
+	LDO(L26,  "8038_l26",  "8038_l26_pc", nldo,     LDO_150),
+	LDO(L27,  "8038_l27",  NULL,          nldo1200, LDO_1200),
+
+	SMPS(S1,  "8038_s1",   "8038_s1_pc",  smps,     SMPS_1500),
+	SMPS(S2,  "8038_s2",   "8038_s2_pc",  smps,     SMPS_1500),
+	SMPS(S3,  "8038_s3",   "8038_s3_pc",  smps,     SMPS_1500),
+	SMPS(S4,  "8038_s4",   "8038_s4_pc",  smps,     SMPS_1500),
+	SMPS(S5,  "8038_s5",   NULL,          ftsmps,   SMPS_2000),
+	SMPS(S6,  "8038_s6",   NULL,          ftsmps,   SMPS_2000),
+
+	LVS(LVS1, "8038_lvs1", "8038_lvs1_pc"),
+	LVS(LVS2, "8038_lvs2", "8038_lvs2_pc"),
+};
+
+static const char *pin_func_label[] = {
+	[RPM_VREG_PIN_FN_8930_DONT_CARE]	= "don't care",
+	[RPM_VREG_PIN_FN_8930_ENABLE]		= "on/off",
+	[RPM_VREG_PIN_FN_8930_MODE]		= "HPM/LPM",
+	[RPM_VREG_PIN_FN_8930_SLEEP_B]		= "sleep_b",
+	[RPM_VREG_PIN_FN_8930_NONE]		= "none",
+};
+
+static const char *force_mode_label[] = {
+	[RPM_VREG_FORCE_MODE_8930_NONE]		= "none",
+	[RPM_VREG_FORCE_MODE_8930_LPM]		= "LPM",
+	[RPM_VREG_FORCE_MODE_8930_AUTO]		= "auto",
+	[RPM_VREG_FORCE_MODE_8930_HPM]		= "HPM",
+	[RPM_VREG_FORCE_MODE_8930_BYPASS]	= "BYP",
+};
+
+static const char *power_mode_label[] = {
+	[RPM_VREG_POWER_MODE_8930_HYSTERETIC]	= "HYS",
+	[RPM_VREG_POWER_MODE_8930_PWM]		= "PWM",
+};
+
+static const char *pin_control_label[] = {
+	" D1",
+	" A0",
+	" A1",
+	" A2",
+};
+
+static int is_real_id(int id)
+{
+	return (id >= 0) && (id <= RPM_VREG_ID_PM8038_MAX_REAL);
+}
+
+static int pc_id_to_real_id(int id)
+{
+	int real_id = 0;
+
+	if (id >= RPM_VREG_ID_PM8038_L2_PC && id <= RPM_VREG_ID_PM8038_L15_PC)
+		real_id = id - RPM_VREG_ID_PM8038_L2_PC;
+	else if (id >= RPM_VREG_ID_PM8038_L17_PC
+			&& id <= RPM_VREG_ID_PM8038_L18_PC)
+		real_id = id - RPM_VREG_ID_PM8038_L17_PC
+				+ RPM_VREG_ID_PM8038_L17;
+	else if (id >= RPM_VREG_ID_PM8038_L21_PC
+			&& id <= RPM_VREG_ID_PM8038_L23_PC)
+		real_id = id - RPM_VREG_ID_PM8038_L21_PC
+				+ RPM_VREG_ID_PM8038_L21;
+	else if (id == RPM_VREG_ID_PM8038_L26_PC)
+		real_id = RPM_VREG_ID_PM8038_L26;
+	else if (id >= RPM_VREG_ID_PM8038_S1_PC
+			&& id <= RPM_VREG_ID_PM8038_S4_PC)
+		real_id = id - RPM_VREG_ID_PM8038_S1_PC
+				+ RPM_VREG_ID_PM8038_S1;
+	else if (id >= RPM_VREG_ID_PM8038_LVS1_PC
+			&& id <= RPM_VREG_ID_PM8038_LVS2_PC)
+		real_id = id - RPM_VREG_ID_PM8038_LVS1_PC
+				+ RPM_VREG_ID_PM8038_LVS1;
+
+	return real_id;
+}
+
+static struct vreg_config config = {
+	.vregs			= vregs,
+	.vregs_len		= ARRAY_SIZE(vregs),
+
+	.vreg_id_min		= RPM_VREG_ID_PM8038_L1,
+	.vreg_id_max		= RPM_VREG_ID_PM8038_MAX,
+
+	.pin_func_none		= RPM_VREG_PIN_FN_8930_NONE,
+	.pin_func_sleep_b	= RPM_VREG_PIN_FN_8930_SLEEP_B,
+
+	.mode_lpm		= REGULATOR_MODE_IDLE,
+	.mode_hpm		= REGULATOR_MODE_NORMAL,
+
+	.set_points		= all_set_points,
+	.set_points_len		= ARRAY_SIZE(all_set_points),
+
+	.label_pin_ctrl		= pin_control_label,
+	.label_pin_ctrl_len	= ARRAY_SIZE(pin_control_label),
+	.label_pin_func		= pin_func_label,
+	.label_pin_func_len	= ARRAY_SIZE(pin_func_label),
+	.label_force_mode	= force_mode_label,
+	.label_force_mode_len	= ARRAY_SIZE(force_mode_label),
+	.label_power_mode	= power_mode_label,
+	.label_power_mode_len	= ARRAY_SIZE(power_mode_label),
+
+	.is_real_id		= is_real_id,
+	.pc_id_to_real_id	= pc_id_to_real_id,
+};
+
+struct vreg_config *get_config_8930(void)
+{
+	return &config;
+}
diff --git a/arch/arm/mach-msm/rpm-regulator-private.h b/arch/arm/mach-msm/rpm-regulator-private.h
index ff127d9..88b52ea 100644
--- a/arch/arm/mach-msm/rpm-regulator-private.h
+++ b/arch/arm/mach-msm/rpm-regulator-private.h
@@ -144,7 +144,7 @@
 #define MICRO_TO_MILLI(uV)			((uV) / 1000)
 #define MILLI_TO_MICRO(mV)			((mV) * 1000)
 
-#if defined(CONFIG_ARCH_MSM8X60)
+#if defined(CONFIG_MSM_RPM_REGULATOR) && defined(CONFIG_ARCH_MSM8X60)
 struct vreg_config *get_config_8660(void);
 #else
 static inline struct vreg_config *get_config_8660(void)
@@ -153,7 +153,8 @@
 }
 #endif
 
-#if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064)
+#if defined(CONFIG_MSM_RPM_REGULATOR) && \
+	(defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064))
 struct vreg_config *get_config_8960(void);
 #else
 static inline struct vreg_config *get_config_8960(void)
@@ -162,7 +163,7 @@
 }
 #endif
 
-#if defined(CONFIG_ARCH_MSM9615)
+#if defined(CONFIG_MSM_RPM_REGULATOR) && defined(CONFIG_ARCH_MSM9615)
 struct vreg_config *get_config_9615(void);
 #else
 static inline struct vreg_config *get_config_9615(void)
@@ -171,4 +172,13 @@
 }
 #endif
 
+#if defined(CONFIG_MSM_RPM_REGULATOR) && defined(CONFIG_ARCH_MSM8930)
+struct vreg_config *get_config_8930(void);
+#else
+static inline struct vreg_config *get_config_8930(void)
+{
+	return NULL;
+}
+#endif
+
 #endif
diff --git a/arch/arm/mach-msm/rpm-regulator.c b/arch/arm/mach-msm/rpm-regulator.c
index e2ebbd4..946d31b 100644
--- a/arch/arm/mach-msm/rpm-regulator.c
+++ b/arch/arm/mach-msm/rpm-regulator.c
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -46,6 +46,7 @@
 	[RPM_VREG_VERSION_8660] = get_config_8660,
 	[RPM_VREG_VERSION_8960] = get_config_8960,
 	[RPM_VREG_VERSION_9615] = get_config_9615,
+	[RPM_VREG_VERSION_8930] = get_config_8930,
 };
 
 #define SET_PART(_vreg, _part, _val) \
diff --git a/arch/arm/mach-msm/rpm.c b/arch/arm/mach-msm/rpm.c
index a8d787a..05b2953 100644
--- a/arch/arm/mach-msm/rpm.c
+++ b/arch/arm/mach-msm/rpm.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
@@ -27,10 +27,10 @@
 #include <linux/spinlock.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 #include <asm/hardware/gic.h>
 #include <mach/msm_iomap.h>
 #include <mach/rpm.h>
-#include <mach/socinfo.h>
 
 /******************************************************************************
  * Data type and structure definitions
@@ -45,14 +45,15 @@
 };
 
 struct msm_rpm_notif_config {
-	struct msm_rpm_iv_pair iv[MSM_RPM_SEL_MASK_SIZE * 2];
+	struct msm_rpm_iv_pair iv[SEL_MASK_SIZE * 2];
 };
 
 #define configured_iv(notif_cfg) ((notif_cfg)->iv)
-#define registered_iv(notif_cfg) ((notif_cfg)->iv + MSM_RPM_SEL_MASK_SIZE)
+#define registered_iv(notif_cfg) ((notif_cfg)->iv + msm_rpm_sel_mask_size)
 
-static struct msm_rpm_platform_data *msm_rpm_platform;
-static uint32_t msm_rpm_map[MSM_RPM_ID_LAST + 1];
+static uint32_t msm_rpm_sel_mask_size;
+static struct msm_rpm_platform_data msm_rpm_data;
+
 
 static DEFINE_MUTEX(msm_rpm_mutex);
 static DEFINE_SPINLOCK(msm_rpm_lock);
@@ -69,15 +70,34 @@
  * Internal functions
  *****************************************************************************/
 
+static inline unsigned int target_enum(unsigned int id)
+{
+	BUG_ON(id >= MSM_RPM_ID_LAST);
+	return msm_rpm_data.target_id[id].id;
+}
+
+static inline unsigned int target_status(unsigned int id)
+{
+	BUG_ON(id >= MSM_RPM_STATUS_ID_LAST);
+	return msm_rpm_data.target_status[id];
+}
+
+static inline unsigned int target_ctrl(unsigned int id)
+{
+	BUG_ON(id >= MSM_RPM_CTRL_LAST);
+	return msm_rpm_data.target_ctrl_id[id];
+}
+
 static inline uint32_t msm_rpm_read(unsigned int page, unsigned int reg)
 {
-	return __raw_readl(msm_rpm_platform->reg_base_addrs[page] + reg * 4);
+	return __raw_readl(msm_rpm_data.reg_base_addrs[page] + reg * 4);
 }
 
 static inline void msm_rpm_write(
 	unsigned int page, unsigned int reg, uint32_t value)
 {
-	__raw_writel(value, msm_rpm_platform->reg_base_addrs[page] + reg * 4);
+	__raw_writel(value,
+		msm_rpm_data.reg_base_addrs[page] + reg * 4);
 }
 
 static inline void msm_rpm_read_contiguous(
@@ -109,7 +129,8 @@
 
 static inline uint32_t msm_rpm_map_id_to_sel(uint32_t id)
 {
-	return (id > MSM_RPM_ID_LAST) ? MSM_RPM_SEL_LAST + 1 : msm_rpm_map[id];
+	return (id >= MSM_RPM_ID_LAST) ? msm_rpm_data.sel_last + 1 :
+		msm_rpm_data.target_id[id].sel;
 }
 
 /*
@@ -128,8 +149,11 @@
 	for (i = 0; i < count; i++) {
 		sel = msm_rpm_map_id_to_sel(req[i].id);
 
-		if (sel > MSM_RPM_SEL_LAST)
+		if (sel > msm_rpm_data.sel_last) {
+			pr_err("%s(): RPM ID %d not defined for target\n",
+					__func__, req[i].id);
 			return -EINVAL;
+		}
 
 		sel_masks[msm_rpm_get_sel_mask_reg(sel)] |=
 			msm_rpm_get_sel_mask(sel);
@@ -140,8 +164,8 @@
 
 static inline void msm_rpm_send_req_interrupt(void)
 {
-	__raw_writel(msm_rpm_platform->msm_apps_ipc_rpm_val,
-			msm_rpm_platform->msm_apps_ipc_rpm_reg);
+	__raw_writel(msm_rpm_data.ipc_rpm_val,
+			msm_rpm_data.ipc_rpm_reg);
 }
 
 /*
@@ -155,26 +179,30 @@
 static int msm_rpm_process_ack_interrupt(void)
 {
 	uint32_t ctx_mask_ack;
-	uint32_t sel_masks_ack[MSM_RPM_SEL_MASK_SIZE];
+	uint32_t sel_masks_ack[SEL_MASK_SIZE] = {0};
 
-	ctx_mask_ack = msm_rpm_read(MSM_RPM_PAGE_CTRL, MSM_RPM_CTRL_ACK_CTX_0);
+	ctx_mask_ack = msm_rpm_read(MSM_RPM_PAGE_CTRL,
+			target_ctrl(MSM_RPM_CTRL_ACK_CTX_0));
 	msm_rpm_read_contiguous(MSM_RPM_PAGE_CTRL,
-		MSM_RPM_CTRL_ACK_SEL_0, sel_masks_ack, MSM_RPM_SEL_MASK_SIZE);
+		target_ctrl(MSM_RPM_CTRL_ACK_SEL_0),
+		sel_masks_ack, msm_rpm_sel_mask_size);
 
 	if (ctx_mask_ack & msm_rpm_get_ctx_mask(MSM_RPM_CTX_NOTIFICATION)) {
 		struct msm_rpm_notification *n;
 		int i;
 
 		list_for_each_entry(n, &msm_rpm_notifications, list)
-			for (i = 0; i < MSM_RPM_SEL_MASK_SIZE; i++)
+			for (i = 0; i < msm_rpm_sel_mask_size; i++)
 				if (sel_masks_ack[i] & n->sel_masks[i]) {
 					up(&n->sem);
 					break;
 				}
 
 		msm_rpm_write_contiguous_zeros(MSM_RPM_PAGE_CTRL,
-			MSM_RPM_CTRL_ACK_SEL_0, MSM_RPM_SEL_MASK_SIZE);
-		msm_rpm_write(MSM_RPM_PAGE_CTRL, MSM_RPM_CTRL_ACK_CTX_0, 0);
+			target_ctrl(MSM_RPM_CTRL_ACK_SEL_0),
+			msm_rpm_sel_mask_size);
+		msm_rpm_write(MSM_RPM_PAGE_CTRL,
+			target_ctrl(MSM_RPM_CTRL_ACK_CTX_0), 0);
 		/* Ensure the write is complete before return */
 		mb();
 
@@ -191,11 +219,13 @@
 		for (i = 0; i < msm_rpm_request->count; i++)
 			msm_rpm_request->req[i].value =
 				msm_rpm_read(MSM_RPM_PAGE_ACK,
-						msm_rpm_request->req[i].id);
+				target_enum(msm_rpm_request->req[i].id));
 
 		msm_rpm_write_contiguous_zeros(MSM_RPM_PAGE_CTRL,
-			MSM_RPM_CTRL_ACK_SEL_0, MSM_RPM_SEL_MASK_SIZE);
-		msm_rpm_write(MSM_RPM_PAGE_CTRL, MSM_RPM_CTRL_ACK_CTX_0, 0);
+			target_ctrl(MSM_RPM_CTRL_ACK_SEL_0),
+			msm_rpm_sel_mask_size);
+		msm_rpm_write(MSM_RPM_PAGE_CTRL,
+			target_ctrl(MSM_RPM_CTRL_ACK_CTX_0), 0);
 		/* Ensure the write is complete before return */
 		mb();
 
@@ -233,7 +263,7 @@
 	int rc;
 
 	do {
-		while (!gic_is_spi_pending(msm_rpm_platform->irq_ack) &&
+		while (!gic_is_spi_pending(msm_rpm_data.irq_ack) &&
 				msm_rpm_request) {
 			if (allow_async_completion)
 				spin_unlock(&msm_rpm_irq_lock);
@@ -246,7 +276,7 @@
 			break;
 
 		rc = msm_rpm_process_ack_interrupt();
-		gic_clear_spi_pending(msm_rpm_platform->irq_ack);
+		gic_clear_spi_pending(msm_rpm_data.irq_ack);
 	} while (rc);
 }
 
@@ -265,7 +295,7 @@
 	unsigned long flags;
 	uint32_t ctx_mask = msm_rpm_get_ctx_mask(ctx);
 	uint32_t ctx_mask_ack = 0;
-	uint32_t sel_masks_ack[MSM_RPM_SEL_MASK_SIZE];
+	uint32_t sel_masks_ack[SEL_MASK_SIZE];
 	int i;
 
 	msm_rpm_request_irq_mode.req = req;
@@ -281,13 +311,16 @@
 	msm_rpm_request = &msm_rpm_request_irq_mode;
 
 	for (i = 0; i < count; i++) {
-		BUG_ON(req[i].id > MSM_RPM_ID_LAST);
-		msm_rpm_write(MSM_RPM_PAGE_REQ, req[i].id, req[i].value);
+		BUG_ON(target_enum(req[i].id) >= MSM_RPM_ID_LAST);
+		msm_rpm_write(MSM_RPM_PAGE_REQ,
+				target_enum(req[i].id), req[i].value);
 	}
 
 	msm_rpm_write_contiguous(MSM_RPM_PAGE_CTRL,
-		MSM_RPM_CTRL_REQ_SEL_0, sel_masks, MSM_RPM_SEL_MASK_SIZE);
-	msm_rpm_write(MSM_RPM_PAGE_CTRL, MSM_RPM_CTRL_REQ_CTX_0, ctx_mask);
+		target_ctrl(MSM_RPM_CTRL_REQ_SEL_0),
+		sel_masks, msm_rpm_sel_mask_size);
+	msm_rpm_write(MSM_RPM_PAGE_CTRL,
+		target_ctrl(MSM_RPM_CTRL_REQ_CTX_0), ctx_mask);
 
 	/* Ensure RPM data is written before sending the interrupt */
 	mb();
@@ -317,11 +350,11 @@
 static int msm_rpm_set_exclusive_noirq(int ctx,
 	uint32_t *sel_masks, struct msm_rpm_iv_pair *req, int count)
 {
-	unsigned int irq = msm_rpm_platform->irq_ack;
+	unsigned int irq = msm_rpm_data.irq_ack;
 	unsigned long flags;
 	uint32_t ctx_mask = msm_rpm_get_ctx_mask(ctx);
 	uint32_t ctx_mask_ack = 0;
-	uint32_t sel_masks_ack[MSM_RPM_SEL_MASK_SIZE];
+	uint32_t sel_masks_ack[SEL_MASK_SIZE];
 	struct irq_chip *irq_chip = NULL;
 	int i;
 
@@ -347,13 +380,16 @@
 	msm_rpm_request = &msm_rpm_request_poll_mode;
 
 	for (i = 0; i < count; i++) {
-		BUG_ON(req[i].id > MSM_RPM_ID_LAST);
-		msm_rpm_write(MSM_RPM_PAGE_REQ, req[i].id, req[i].value);
+		BUG_ON(target_enum(req[i].id) >= MSM_RPM_ID_LAST);
+		msm_rpm_write(MSM_RPM_PAGE_REQ,
+				target_enum(req[i].id), req[i].value);
 	}
 
 	msm_rpm_write_contiguous(MSM_RPM_PAGE_CTRL,
-		MSM_RPM_CTRL_REQ_SEL_0, sel_masks, MSM_RPM_SEL_MASK_SIZE);
-	msm_rpm_write(MSM_RPM_PAGE_CTRL, MSM_RPM_CTRL_REQ_CTX_0, ctx_mask);
+		target_ctrl(MSM_RPM_CTRL_REQ_SEL_0),
+		sel_masks, msm_rpm_sel_mask_size);
+	msm_rpm_write(MSM_RPM_PAGE_CTRL,
+		target_ctrl(MSM_RPM_CTRL_REQ_CTX_0), ctx_mask);
 
 	/* Ensure RPM data is written before sending the interrupt */
 	mb();
@@ -385,16 +421,9 @@
 static int msm_rpm_set_common(
 	int ctx, struct msm_rpm_iv_pair *req, int count, bool noirq)
 {
-	uint32_t sel_masks[MSM_RPM_SEL_MASK_SIZE] = {};
+	uint32_t sel_masks[SEL_MASK_SIZE] = {};
 	int rc;
 
-	if (!msm_rpm_platform) {
-		if (cpu_is_apq8064())
-			return 0;
-		else
-			return -ENODEV;
-	}
-
 	if (ctx >= MSM_RPM_CTX_SET_COUNT) {
 		rc = -EINVAL;
 		goto set_common_exit;
@@ -433,18 +462,11 @@
 static int msm_rpm_clear_common(
 	int ctx, struct msm_rpm_iv_pair *req, int count, bool noirq)
 {
-	uint32_t sel_masks[MSM_RPM_SEL_MASK_SIZE] = {};
-	struct msm_rpm_iv_pair r[MSM_RPM_SEL_MASK_SIZE];
+	uint32_t sel_masks[SEL_MASK_SIZE] = {};
+	struct msm_rpm_iv_pair r[SEL_MASK_SIZE];
 	int rc;
 	int i;
 
-	if (!msm_rpm_platform) {
-		if (cpu_is_apq8064())
-			return 0;
-		else
-			return -ENODEV;
-	}
-
 	if (ctx >= MSM_RPM_CTX_SET_COUNT) {
 		rc = -EINVAL;
 		goto clear_common_exit;
@@ -460,8 +482,8 @@
 	}
 
 	memset(sel_masks, 0, sizeof(sel_masks));
-	sel_masks[msm_rpm_get_sel_mask_reg(MSM_RPM_SEL_INVALIDATE)] |=
-		msm_rpm_get_sel_mask(MSM_RPM_SEL_INVALIDATE);
+	sel_masks[msm_rpm_get_sel_mask_reg(msm_rpm_data.sel_invalidate)] |=
+		msm_rpm_get_sel_mask(msm_rpm_data.sel_invalidate);
 
 	if (noirq) {
 		unsigned long flags;
@@ -492,12 +514,14 @@
 	struct msm_rpm_notif_config *curr_cfg,
 	struct msm_rpm_notif_config *new_cfg)
 {
+	unsigned int sel_notif = msm_rpm_data.sel_notification;
+
 	if (memcmp(curr_cfg, new_cfg, sizeof(*new_cfg))) {
-		uint32_t sel_masks[MSM_RPM_SEL_MASK_SIZE] = {};
+		uint32_t sel_masks[SEL_MASK_SIZE] = {};
 		int rc;
 
-		sel_masks[msm_rpm_get_sel_mask_reg(MSM_RPM_SEL_NOTIFICATION)]
-			|= msm_rpm_get_sel_mask(MSM_RPM_SEL_NOTIFICATION);
+		sel_masks[msm_rpm_get_sel_mask_reg(sel_notif)]
+			|= msm_rpm_get_sel_mask(sel_notif);
 
 		rc = msm_rpm_set_exclusive(ctx,
 			sel_masks, new_cfg->iv, ARRAY_SIZE(new_cfg->iv));
@@ -519,7 +543,7 @@
 	for (ctx = MSM_RPM_CTX_SET_0; ctx <= MSM_RPM_CTX_SET_SLEEP; ctx++) {
 		cfg = msm_rpm_notif_cfgs[ctx];
 
-		for (i = 0; i < MSM_RPM_SEL_MASK_SIZE; i++) {
+		for (i = 0; i < msm_rpm_sel_mask_size; i++) {
 			configured_iv(&cfg)[i].id =
 				MSM_RPM_ID_NOTIFICATION_CONFIGURED_0 + i;
 			configured_iv(&cfg)[i].value = ~0UL;
@@ -581,28 +605,33 @@
 	int rc;
 	int i;
 
-	if (!msm_rpm_platform) {
-		if (cpu_is_apq8064())
-			return 0;
-		else
-			return -ENODEV;
-	}
-
 	seq_begin = msm_rpm_read(MSM_RPM_PAGE_STATUS,
-				MSM_RPM_STATUS_ID_SEQUENCE);
+				target_status(MSM_RPM_STATUS_ID_SEQUENCE));
 
 	for (i = 0; i < count; i++) {
-		if (status[i].id > MSM_RPM_STATUS_ID_LAST) {
+		int target_status_id;
+
+		if (status[i].id >= MSM_RPM_STATUS_ID_LAST) {
+			pr_err("%s(): Status ID beyond limits\n", __func__);
+			rc = -EINVAL;
+			goto get_status_exit;
+		}
+
+		target_status_id = target_status(status[i].id);
+		if (target_status_id >= MSM_RPM_STATUS_ID_LAST) {
+			pr_err("%s(): Status id %d not defined for target\n",
+					__func__,
+					target_status_id);
 			rc = -EINVAL;
 			goto get_status_exit;
 		}
 
 		status[i].value = msm_rpm_read(MSM_RPM_PAGE_STATUS,
-						status[i].id);
+				target_status_id);
 	}
 
 	seq_end = msm_rpm_read(MSM_RPM_PAGE_STATUS,
-				MSM_RPM_STATUS_ID_SEQUENCE);
+				target_status(MSM_RPM_STATUS_ID_SEQUENCE));
 
 	rc = (seq_begin != seq_end || (seq_begin & 0x01)) ? -EBUSY : 0;
 
@@ -729,13 +758,6 @@
 	int rc;
 	int i;
 
-	if (!msm_rpm_platform) {
-		if (cpu_is_apq8064())
-			return 0;
-		else
-			return -ENODEV;
-	}
-
 	INIT_LIST_HEAD(&n->list);
 	rc = msm_rpm_fill_sel_masks(n->sel_masks, req, count);
 	if (rc)
@@ -757,7 +779,7 @@
 	ctx = MSM_RPM_CTX_SET_0;
 	cfg = msm_rpm_notif_cfgs[ctx];
 
-	for (i = 0; i < MSM_RPM_SEL_MASK_SIZE; i++)
+	for (i = 0; i < msm_rpm_sel_mask_size; i++)
 		registered_iv(&cfg)[i].value |= n->sel_masks[i];
 
 	msm_rpm_update_notification(ctx, &msm_rpm_notif_cfgs[ctx], &cfg);
@@ -788,13 +810,6 @@
 	int rc;
 	int i;
 
-	if (!msm_rpm_platform) {
-		if (cpu_is_apq8064())
-			return 0;
-		else
-			return -ENODEV;
-	}
-
 	rc = mutex_lock_interruptible(&msm_rpm_mutex);
 	if (rc)
 		goto unregister_notification_exit;
@@ -802,13 +817,13 @@
 	ctx = MSM_RPM_CTX_SET_0;
 	cfg = msm_rpm_notif_cfgs[ctx];
 
-	for (i = 0; i < MSM_RPM_SEL_MASK_SIZE; i++)
+	for (i = 0; i < msm_rpm_sel_mask_size; i++)
 		registered_iv(&cfg)[i].value = 0;
 
 	spin_lock_irqsave(&msm_rpm_irq_lock, flags);
 	list_del(&n->list);
 	list_for_each_entry(n, &msm_rpm_notifications, list)
-		for (i = 0; i < MSM_RPM_SEL_MASK_SIZE; i++)
+		for (i = 0; i < msm_rpm_sel_mask_size; i++)
 			registered_iv(&cfg)[i].value |= n->sel_masks[i];
 	spin_unlock_irqrestore(&msm_rpm_irq_lock, flags);
 
@@ -826,7 +841,7 @@
 		struct kobj_attribute *attr, char *buf)
 {
 	return snprintf(buf, PAGE_SIZE, "%u.%u.%u\n",
-			RPM_MAJOR_VER, RPM_MINOR_VER, RPM_BUILD_VER);
+		msm_rpm_data.ver[0], msm_rpm_data.ver[1], msm_rpm_data.ver[2]);
 }
 
 static ssize_t fw_version_show(struct kobject *kobj,
@@ -869,18 +884,49 @@
 	},
 };
 
-static void __init msm_rpm_populate_map(void)
+static void __init msm_rpm_populate_map(struct msm_rpm_platform_data *data)
 {
-	int i, k;
+	int i, j;
+	struct msm_rpm_map_data *src = NULL;
+	struct msm_rpm_map_data *dst = NULL;
 
-	for (i = 0; i < ARRAY_SIZE(msm_rpm_map); i++)
-		msm_rpm_map[i] = MSM_RPM_SEL_LAST + 1;
+	for (i = 0; i < MSM_RPM_ID_LAST;) {
+		src = &data->target_id[i];
+		dst = &msm_rpm_data.target_id[i];
 
-	for (i = 0; i < rpm_map_data_size; i++) {
-		struct msm_rpm_map_data *raw_data = &rpm_map_data[i];
+		dst->id = MSM_RPM_ID_LAST;
+		dst->sel = msm_rpm_data.sel_last + 1;
 
-		for (k = 0; k < raw_data->count; k++)
-			msm_rpm_map[raw_data->id + k] = raw_data->sel;
+		/*
+		 * copy the target specific id of the current and also of
+		 * all the #count id's that follow the current.
+		 * [MSM_RPM_ID_PM8921_S1_0] = { MSM_RPM_8960_ID_PM8921_S1_0,
+		 *				MSM_RPM_8960_SEL_PM8921_S1,
+		 *				2},
+		 * [MSM_RPM_ID_PM8921_S1_1] = { 0, 0, 0 },
+		 * should translate to
+		 * [MSM_RPM_ID_PM8921_S1_0] = { MSM_RPM_8960_ID_PM8921_S1_0,
+		 *				MSM_RPM_8960_SEL_PM8921,
+		 *				2 },
+		 * [MSM_RPM_ID_PM8921_S1_1] = { MSM_RPM_8960_ID_PM8921_S1_0 + 1,
+		 *				MSM_RPM_8960_SEL_PM8921,
+		 *				0 },
+		 */
+		for (j = 0; j < src->count; j++) {
+			dst = &msm_rpm_data.target_id[i + j];
+			dst->id = src->id + j;
+			dst->sel = src->sel;
+		}
+
+		i += (src->count) ? src->count : 1;
+	}
+
+	for (i = 0; i < MSM_RPM_STATUS_ID_LAST; i++) {
+		if (data->target_status[i] & MSM_RPM_STATUS_ID_VALID)
+			msm_rpm_data.target_status[i] &=
+				~MSM_RPM_STATUS_ID_VALID;
+		else
+			msm_rpm_data.target_status[i] = MSM_RPM_STATUS_ID_LAST;
 	}
 }
 
@@ -889,36 +935,37 @@
 	unsigned int irq;
 	int rc;
 
-	if (cpu_is_apq8064())
-		return 0;
-
-	msm_rpm_platform = data;
+	memcpy(&msm_rpm_data, data, sizeof(struct msm_rpm_platform_data));
+	msm_rpm_sel_mask_size = msm_rpm_data.sel_last / 32 + 1;
+	BUG_ON(SEL_MASK_SIZE < msm_rpm_sel_mask_size);
 
 	fw_major = msm_rpm_read(MSM_RPM_PAGE_STATUS,
-					MSM_RPM_STATUS_ID_VERSION_MAJOR);
+				target_status(MSM_RPM_STATUS_ID_VERSION_MAJOR));
 	fw_minor = msm_rpm_read(MSM_RPM_PAGE_STATUS,
-					MSM_RPM_STATUS_ID_VERSION_MINOR);
+				target_status(MSM_RPM_STATUS_ID_VERSION_MINOR));
 	fw_build = msm_rpm_read(MSM_RPM_PAGE_STATUS,
-					MSM_RPM_STATUS_ID_VERSION_BUILD);
+				target_status(MSM_RPM_STATUS_ID_VERSION_BUILD));
 	pr_info("%s: RPM firmware %u.%u.%u\n", __func__,
 			fw_major, fw_minor, fw_build);
 
-	if (fw_major != RPM_MAJOR_VER) {
+	if (fw_major != msm_rpm_data.ver[0]) {
 		pr_err("%s: RPM version %u.%u.%u incompatible with "
 				"this driver version %u.%u.%u\n", __func__,
 				fw_major, fw_minor, fw_build,
-				RPM_MAJOR_VER, RPM_MINOR_VER, RPM_BUILD_VER);
+				msm_rpm_data.ver[0],
+				msm_rpm_data.ver[1],
+				msm_rpm_data.ver[2]);
 		return -EFAULT;
 	}
 
-	msm_rpm_write(MSM_RPM_PAGE_CTRL, MSM_RPM_CTRL_VERSION_MAJOR,
-			RPM_MAJOR_VER);
-	msm_rpm_write(MSM_RPM_PAGE_CTRL, MSM_RPM_CTRL_VERSION_MINOR,
-			RPM_MINOR_VER);
-	msm_rpm_write(MSM_RPM_PAGE_CTRL, MSM_RPM_CTRL_VERSION_BUILD,
-			RPM_BUILD_VER);
+	msm_rpm_write(MSM_RPM_PAGE_CTRL,
+		target_ctrl(MSM_RPM_CTRL_VERSION_MAJOR), msm_rpm_data.ver[0]);
+	msm_rpm_write(MSM_RPM_PAGE_CTRL,
+		target_ctrl(MSM_RPM_CTRL_VERSION_MINOR), msm_rpm_data.ver[1]);
+	msm_rpm_write(MSM_RPM_PAGE_CTRL,
+		target_ctrl(MSM_RPM_CTRL_VERSION_BUILD), msm_rpm_data.ver[2]);
 
-	irq = msm_rpm_platform->irq_ack;
+	irq = data->irq_ack;
 
 	rc = request_irq(irq, msm_rpm_ack_interrupt,
 			IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND,
@@ -936,7 +983,7 @@
 		return rc;
 	}
 
-	msm_rpm_populate_map();
+	msm_rpm_populate_map(data);
 
 	return platform_driver_register(&msm_rpm_platform_driver);
 }
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 3568070..546a917 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.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
@@ -65,6 +65,10 @@
 static ssize_t msm_rpmrs_resource_attr_store(struct kobject *kobj,
 	struct kobj_attribute *attr, const char *buf, size_t count);
 
+static int vdd_dig_vlevels[MSM_RPMRS_VDD_DIG_LAST];
+static int vdd_mem_vlevels[MSM_RPMRS_VDD_MEM_LAST];
+static int vdd_mask;
+
 #define MSM_RPMRS_MAX_RS_REGISTER_COUNT 2
 
 #define RPMRS_ATTR(_name) \
@@ -86,7 +90,6 @@
 };
 
 static struct msm_rpmrs_resource msm_rpmrs_pxo = {
-	.rs[0].id = MSM_RPMRS_ID_PXO_CLK,
 	.size = 1,
 	.name = "pxo",
 	.beyond_limits = msm_rpmrs_pxo_beyond_limits,
@@ -96,7 +99,6 @@
 };
 
 static struct msm_rpmrs_resource msm_rpmrs_l2_cache = {
-	.rs[0].id = MSM_RPMRS_ID_APPS_L2_CACHE_CTL,
 	.size = 1,
 	.name = "L2_cache",
 	.beyond_limits = msm_rpmrs_l2_cache_beyond_limits,
@@ -106,8 +108,6 @@
 };
 
 static struct msm_rpmrs_resource msm_rpmrs_vdd_mem = {
-	.rs[0].id = MSM_RPMRS_ID_VDD_MEM_0,
-	.rs[1].id = MSM_RPMRS_ID_VDD_MEM_1,
 	.size = 2,
 	.name = "vdd_mem",
 	.beyond_limits = msm_rpmrs_vdd_mem_beyond_limits,
@@ -117,8 +117,6 @@
 };
 
 static struct msm_rpmrs_resource msm_rpmrs_vdd_dig = {
-	.rs[0].id = MSM_RPMRS_ID_VDD_DIG_0,
-	.rs[1].id = MSM_RPMRS_ID_VDD_DIG_1,
 	.size = 2,
 	.name = "vdd_dig",
 	.beyond_limits = msm_rpmrs_vdd_dig_beyond_limits,
@@ -128,7 +126,6 @@
 };
 
 static struct msm_rpmrs_resource msm_rpmrs_rpm_ctl = {
-	.rs[0].id = MSM_RPMRS_ID_RPM_CTL,
 	.size = 1,
 	.name = "rpm_ctl",
 	.beyond_limits = NULL,
@@ -145,12 +142,12 @@
 	&msm_rpmrs_rpm_ctl,
 };
 
-static uint32_t msm_rpmrs_buffer[MSM_RPM_ID_LAST + 1];
-static DECLARE_BITMAP(msm_rpmrs_buffered, MSM_RPM_ID_LAST + 1);
-static DECLARE_BITMAP(msm_rpmrs_listed, MSM_RPM_ID_LAST + 1);
+static uint32_t msm_rpmrs_buffer[MSM_RPM_ID_LAST];
+static DECLARE_BITMAP(msm_rpmrs_buffered, MSM_RPM_ID_LAST);
+static DECLARE_BITMAP(msm_rpmrs_listed, MSM_RPM_ID_LAST);
 static DEFINE_SPINLOCK(msm_rpmrs_lock);
 
-#define MSM_RPMRS_VDD(v)  ((v) & (MSM_RPMRS_VDD_MASK))
+#define MSM_RPMRS_VDD(v)  ((v) & (vdd_mask))
 
 /******************************************************************************
  * Attribute Definitions
@@ -290,20 +287,19 @@
 		uint32_t buffered_value = msm_rpmrs_buffer[rs->rs[0].id];
 
 		if (rs->enable_low_power == 0)
-			vdd_mem = MSM_RPMRS_VDD_MEM_ACTIVE;
+			vdd_mem = vdd_mem_vlevels[MSM_RPMRS_VDD_MEM_ACTIVE];
 		else if (rs->enable_low_power == 1)
-			vdd_mem = MSM_RPMRS_VDD_MEM_RET_HIGH;
+			vdd_mem = vdd_mem_vlevels[MSM_RPMRS_VDD_MEM_RET_HIGH];
 		else
-			vdd_mem = MSM_RPMRS_VDD_MEM_RET_LOW;
+			vdd_mem = vdd_mem_vlevels[MSM_RPMRS_VDD_MEM_RET_LOW];
 
 		if (MSM_RPMRS_VDD(buffered_value) > MSM_RPMRS_VDD(vdd_mem))
-			vdd_mem = buffered_value;
+			vdd_mem = MSM_RPMRS_VDD(buffered_value);
 	} else {
-		vdd_mem = MSM_RPMRS_VDD_MEM_ACTIVE;
+		vdd_mem = vdd_mem_vlevels[MSM_RPMRS_VDD_MEM_ACTIVE];
 	}
 
-	return MSM_RPMRS_VDD(vdd_mem) >
-				MSM_RPMRS_VDD(limits->vdd_mem_upper_bound);
+	return vdd_mem > vdd_mem_vlevels[limits->vdd_mem_upper_bound];
 }
 
 static void msm_rpmrs_aggregate_vdd_mem(struct msm_rpmrs_limits *limits)
@@ -313,9 +309,9 @@
 
 	if (test_bit(rs->rs[0].id, msm_rpmrs_buffered)) {
 		rs->rs[0].value = *buf;
-		if (MSM_RPMRS_VDD(limits->vdd_mem) > MSM_RPMRS_VDD(*buf)) {
-			*buf &= ~MSM_RPMRS_VDD_MASK;
-			*buf |= MSM_RPMRS_VDD(limits->vdd_mem);
+		if (vdd_mem_vlevels[limits->vdd_mem] > MSM_RPMRS_VDD(*buf)) {
+			*buf &= ~vdd_mask;
+			*buf |= vdd_mem_vlevels[limits->vdd_mem];
 		}
 
 		if (MSM_RPMRS_DEBUG_OUTPUT & msm_rpmrs_debug_mask)
@@ -341,20 +337,19 @@
 		uint32_t buffered_value = msm_rpmrs_buffer[rs->rs[0].id];
 
 		if (rs->enable_low_power == 0)
-			vdd_dig = MSM_RPMRS_VDD_DIG_ACTIVE;
+			vdd_dig = vdd_dig_vlevels[MSM_RPMRS_VDD_DIG_ACTIVE];
 		else if (rs->enable_low_power == 1)
-			vdd_dig = MSM_RPMRS_VDD_DIG_RET_HIGH;
+			vdd_dig = vdd_dig_vlevels[MSM_RPMRS_VDD_DIG_RET_HIGH];
 		else
-			vdd_dig = MSM_RPMRS_VDD_DIG_RET_LOW;
+			vdd_dig = vdd_dig_vlevels[MSM_RPMRS_VDD_DIG_RET_LOW];
 
 		if (MSM_RPMRS_VDD(buffered_value) > MSM_RPMRS_VDD(vdd_dig))
-			vdd_dig = buffered_value;
+			vdd_dig = MSM_RPMRS_VDD(buffered_value);
 	} else {
-		vdd_dig = MSM_RPMRS_VDD_DIG_ACTIVE;
+		vdd_dig = vdd_dig_vlevels[MSM_RPMRS_VDD_DIG_ACTIVE];
 	}
 
-	return MSM_RPMRS_VDD(vdd_dig) >
-				MSM_RPMRS_VDD(limits->vdd_dig_upper_bound);
+	return vdd_dig > vdd_dig_vlevels[limits->vdd_dig_upper_bound];
 }
 
 static void msm_rpmrs_aggregate_vdd_dig(struct msm_rpmrs_limits *limits)
@@ -364,9 +359,9 @@
 
 	if (test_bit(rs->rs[0].id, msm_rpmrs_buffered)) {
 		rs->rs[0].value = *buf;
-		if (MSM_RPMRS_VDD(limits->vdd_dig) > MSM_RPMRS_VDD(*buf)) {
-			*buf &= ~MSM_RPMRS_VDD_MASK;
-			*buf |= MSM_RPMRS_VDD(limits->vdd_dig);
+		if (vdd_dig_vlevels[limits->vdd_dig] > MSM_RPMRS_VDD(*buf)) {
+			*buf &= ~vdd_mask;
+			*buf |= vdd_dig_vlevels[limits->vdd_dig];
 		}
 
 
@@ -392,7 +387,8 @@
 		bool irqs_detect, bool gpio_detect)
 {
 
-	if (limits->vdd_dig_upper_bound <= MSM_RPMRS_VDD_DIG_RET_HIGH)
+	if (vdd_dig_vlevels[limits->vdd_dig_upper_bound] <=
+			vdd_dig_vlevels[MSM_RPMRS_VDD_DIG_RET_HIGH])
 		return irqs_detect;
 
 	if (limits->pxo == MSM_RPMRS_PXO_OFF)
@@ -404,7 +400,8 @@
 static bool msm_rpmrs_use_mpm(struct msm_rpmrs_limits *limits)
 {
 	return (limits->pxo == MSM_RPMRS_PXO_OFF) ||
-		(limits->vdd_dig <= MSM_RPMRS_VDD_DIG_RET_HIGH);
+		(vdd_dig_vlevels[limits->vdd_dig] <=
+		 vdd_dig_vlevels[MSM_RPMRS_VDD_DIG_RET_HIGH]);
 }
 
 static void msm_rpmrs_update_levels(void)
@@ -428,6 +425,7 @@
 				break;
 			}
 		}
+
 	}
 }
 
@@ -443,7 +441,7 @@
 	int i;
 
 	for (i = 0; i < count; i++)
-		if (req[i].id > MSM_RPM_ID_LAST)
+		if (req[i].id >= MSM_RPM_ID_LAST)
 			return -EINVAL;
 
 	for (i = 0, listed = false; i < count; i++) {
@@ -476,7 +474,7 @@
 	int i;
 
 	for (i = 0; i < count; i++)
-		if (req[i].id > MSM_RPM_ID_LAST)
+		if (req[i].id >= MSM_RPM_ID_LAST)
 			return -EINVAL;
 
 	for (i = 0, listed = false; i < count; i++) {
@@ -557,7 +555,7 @@
 			msm_rpmrs_resources[i]->aggregate(limits);
 	}
 
-	count = bitmap_weight(msm_rpmrs_buffered, MSM_RPM_ID_LAST + 1);
+	count = bitmap_weight(msm_rpmrs_buffered, MSM_RPM_ID_LAST);
 
 	req = kmalloc(sizeof(*req) * count, GFP_ATOMIC);
 	if (!req) {
@@ -566,9 +564,9 @@
 	}
 
 	count = 0;
-	i = find_first_bit(msm_rpmrs_buffered, MSM_RPM_ID_LAST + 1);
+	i = find_first_bit(msm_rpmrs_buffered, MSM_RPM_ID_LAST);
 
-	while (i < MSM_RPM_ID_LAST + 1) {
+	while (i < MSM_RPM_ID_LAST) {
 		if (MSM_RPMRS_DEBUG_OUTPUT & msm_rpmrs_debug_mask)
 			pr_info("%s: reg %d: 0x%x\n",
 				__func__, i, msm_rpmrs_buffer[i]);
@@ -577,7 +575,7 @@
 		req[count].value = msm_rpmrs_buffer[i];
 		count++;
 
-		i = find_next_bit(msm_rpmrs_buffered, MSM_RPM_ID_LAST+1, i+1);
+		i = find_next_bit(msm_rpmrs_buffered, MSM_RPM_ID_LAST, i + 1);
 	}
 
 	rc = msm_rpm_set_noirq(MSM_RPM_CTX_SET_SLEEP, req, count);
@@ -587,7 +585,7 @@
 		goto flush_buffer_restore;
 
 	bitmap_and(msm_rpmrs_buffered,
-		msm_rpmrs_buffered, msm_rpmrs_listed, MSM_RPM_ID_LAST + 1);
+		msm_rpmrs_buffered, msm_rpmrs_listed, MSM_RPM_ID_LAST);
 
 flush_buffer_restore:
 	for (i = 0; i < ARRAY_SIZE(msm_rpmrs_resources); i++) {
@@ -664,7 +662,8 @@
 
 	spin_lock_irqsave(&msm_rpmrs_lock, flags);
 	/* special case active-set signal for MSM_RPMRS_ID_RPM_CTL */
-	if (GET_RS_FROM_ATTR(attr)->rs[0].id == MSM_RPMRS_ID_RPM_CTL)
+	if (GET_RS_FROM_ATTR(attr)->rs[0].id ==
+			msm_rpmrs_rpm_ctl.rs[0].id)
 		temp = GET_RS_FROM_ATTR(attr)->rs[0].value;
 	else
 		temp = GET_RS_FROM_ATTR(attr)->enable_low_power;
@@ -698,9 +697,10 @@
 	GET_RS_FROM_ATTR(attr)->enable_low_power = temp;
 
 	/* special case active-set signal for MSM_RPMRS_ID_RPM_CTL */
-	if (GET_RS_FROM_ATTR(attr)->rs[0].id == MSM_RPMRS_ID_RPM_CTL) {
+	if (GET_RS_FROM_ATTR(attr)->rs[0].id ==
+			msm_rpmrs_rpm_ctl.rs[0].id) {
 		struct msm_rpm_iv_pair req;
-		req.id = MSM_RPMRS_ID_RPM_CTL;
+		req.id = msm_rpmrs_rpm_ctl.rs[0].id;
 		req.value = GET_RS_FROM_ATTR(attr)->enable_low_power;
 		GET_RS_FROM_ATTR(attr)->rs[0].value = req.value;
 
@@ -855,7 +855,7 @@
 	spin_lock_irqsave(&msm_rpmrs_lock, flags);
 	for (i = 0; i < ARRAY_SIZE(msm_rpmrs_resources); i++) {
 		rs = msm_rpmrs_resources[i];
-		if (rs->rs[0].id < MSM_RPM_ID_LAST + 1)
+		if (rs->rs[0].id < MSM_RPM_ID_LAST)
 			pr_info("%s: resource %s: buffered %d, value 0x%x\n",
 				__func__, rs->name,
 				test_bit(rs->rs[0].id, msm_rpmrs_buffered),
@@ -978,14 +978,52 @@
 	.notifier_call = rpmrs_cpu_callback,
 };
 
-int __init msm_rpmrs_levels_init(struct msm_rpmrs_level *levels, int size)
+int __init msm_rpmrs_levels_init(struct msm_rpmrs_platform_data *data)
 {
-	msm_rpmrs_levels = kzalloc(sizeof(struct msm_rpmrs_level) * size,
-			GFP_KERNEL);
+	int i, k;
+	struct msm_rpmrs_level *levels = data->levels;
+
+	msm_rpmrs_level_count = data->num_levels;
+
+	msm_rpmrs_levels = kzalloc(sizeof(struct msm_rpmrs_level) *
+			msm_rpmrs_level_count, GFP_KERNEL);
 	if (!msm_rpmrs_levels)
 		return -ENOMEM;
-	msm_rpmrs_level_count = size;
-	memcpy(msm_rpmrs_levels, levels, size * sizeof(struct msm_rpmrs_level));
+
+	memcpy(msm_rpmrs_levels, levels,
+			msm_rpmrs_level_count * sizeof(struct msm_rpmrs_level));
+
+	memcpy(vdd_dig_vlevels, data->vdd_dig_levels,
+		(MSM_RPMRS_VDD_DIG_MAX + 1) * sizeof(vdd_dig_vlevels[0]));
+
+	memcpy(vdd_mem_vlevels, data->vdd_mem_levels,
+		(MSM_RPMRS_VDD_MEM_MAX + 1) * sizeof(vdd_mem_vlevels[0]));
+	vdd_mask = data->vdd_mask;
+
+	msm_rpmrs_pxo.rs[0].id = data->rpmrs_target_id[MSM_RPMRS_ID_PXO_CLK];
+	msm_rpmrs_l2_cache.rs[0].id =
+			data->rpmrs_target_id[MSM_RPMRS_ID_L2_CACHE_CTL];
+	msm_rpmrs_vdd_mem.rs[0].id =
+			data->rpmrs_target_id[MSM_RPMRS_ID_VDD_MEM_0];
+	msm_rpmrs_vdd_mem.rs[1].id =
+			data->rpmrs_target_id[MSM_RPMRS_ID_VDD_MEM_1];
+	msm_rpmrs_vdd_dig.rs[0].id =
+			data->rpmrs_target_id[MSM_RPMRS_ID_VDD_DIG_0];
+	msm_rpmrs_vdd_dig.rs[1].id =
+			data->rpmrs_target_id[MSM_RPMRS_ID_VDD_DIG_1];
+	msm_rpmrs_rpm_ctl.rs[0].id =
+			data->rpmrs_target_id[MSM_RPMRS_ID_RPM_CTL];
+
+	/* Initialize listed bitmap for valid resource IDs */
+	for (i = 0; i < ARRAY_SIZE(msm_rpmrs_resources); i++) {
+		for (k = 0; k < msm_rpmrs_resources[i]->size; k++) {
+			if (msm_rpmrs_resources[i]->rs[k].id >=
+					MSM_RPM_ID_LAST)
+				continue;
+			set_bit(msm_rpmrs_resources[i]->rs[k].id,
+				msm_rpmrs_listed);
+		}
+	}
 
 	return 0;
 }
@@ -995,13 +1033,10 @@
 	struct msm_rpm_iv_pair req;
 	int rc;
 
-	if (cpu_is_apq8064())
-		return -ENODEV;
-
 	BUG_ON(!msm_rpmrs_levels);
 
 	if (cpu_is_msm8x60()) {
-		req.id = MSM_RPMRS_ID_APPS_L2_CACHE_CTL;
+		req.id = msm_rpmrs_l2_cache.rs[0].id;
 		req.value = 1;
 
 		rc = msm_rpm_set(MSM_RPM_CTX_SET_0, &req, 1);
@@ -1011,7 +1046,7 @@
 			goto init_exit;
 		}
 
-		req.id = MSM_RPMRS_ID_APPS_L2_CACHE_CTL;
+		req.id = msm_rpmrs_l2_cache.rs[0].id;
 		req.value = 0;
 
 		rc = msm_rpmrs_set(MSM_RPM_CTX_SET_SLEEP, &req, 1);
@@ -1029,24 +1064,9 @@
 }
 device_initcall(msm_rpmrs_init);
 
-static int __init msm_rpmrs_early_init(void)
-{
-	int i, k;
-
-	/* Initialize listed bitmap for valid resource IDs */
-	for (i = 0; i < ARRAY_SIZE(msm_rpmrs_resources); i++) {
-		for (k = 0; k < msm_rpmrs_resources[i]->size; k++)
-			set_bit(msm_rpmrs_resources[i]->rs[k].id,
-				msm_rpmrs_listed);
-	}
-
-	return 0;
-}
-early_initcall(msm_rpmrs_early_init);
-
 static int __init msm_rpmrs_l2_init(void)
 {
-	if (cpu_is_msm8960() || cpu_is_msm8930()) {
+	if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_apq8064()) {
 
 		msm_pm_set_l2_flush_flag(0);
 
diff --git a/arch/arm/mach-msm/rpm_resources.h b/arch/arm/mach-msm/rpm_resources.h
index e849208..a5c61b2 100644
--- a/arch/arm/mach-msm/rpm_resources.h
+++ b/arch/arm/mach-msm/rpm_resources.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,19 +15,17 @@
 #define __ARCH_ARM_MACH_MSM_RPM_RESOURCES_H
 
 #include <mach/rpm.h>
-#include <mach/pm.h>
+#include "pm.h"
 
-
-struct msm_rpmrs_limits {
-	uint32_t pxo;
-	uint32_t l2_cache;
-	uint32_t vdd_mem_upper_bound;
-	uint32_t vdd_mem;
-	uint32_t vdd_dig_upper_bound;
-	uint32_t vdd_dig;
-
-	uint32_t latency_us[NR_CPUS];
-	uint32_t power[NR_CPUS];
+enum {
+	MSM_RPMRS_ID_PXO_CLK = 0,
+	MSM_RPMRS_ID_L2_CACHE_CTL = 1,
+	MSM_RPMRS_ID_VDD_DIG_0 = 2,
+	MSM_RPMRS_ID_VDD_DIG_1 = 3,
+	MSM_RPMRS_ID_VDD_MEM_0 = 4,
+	MSM_RPMRS_ID_VDD_MEM_1 = 5,
+	MSM_RPMRS_ID_RPM_CTL = 6,
+	MSM_RPMRS_ID_LAST,
 };
 
 enum {
@@ -47,6 +45,22 @@
 	MSM_RPMRS_MASK_RPM_CTL_MULTI_TIER = 2,
 };
 
+enum {
+	MSM_RPMRS_VDD_MEM_RET_LOW = 0,
+	MSM_RPMRS_VDD_MEM_RET_HIGH = 1,
+	MSM_RPMRS_VDD_MEM_ACTIVE = 2,
+	MSM_RPMRS_VDD_MEM_MAX = 3,
+	MSM_RPMRS_VDD_MEM_LAST,
+};
+
+enum {
+	MSM_RPMRS_VDD_DIG_RET_LOW = 0,
+	MSM_RPMRS_VDD_DIG_RET_HIGH = 1,
+	MSM_RPMRS_VDD_DIG_ACTIVE = 2,
+	MSM_RPMRS_VDD_DIG_MAX = 3,
+	MSM_RPMRS_VDD_DIG_LAST,
+};
+
 #define MSM_RPMRS_LIMITS(_pxo, _l2, _vdd_upper_b, _vdd) { \
 	MSM_RPMRS_PXO_##_pxo, \
 	MSM_RPMRS_L2_CACHE_##_l2, \
@@ -57,6 +71,18 @@
 	{0}, {0}, \
 }
 
+struct msm_rpmrs_limits {
+	uint32_t pxo;
+	uint32_t l2_cache;
+	uint32_t vdd_mem_upper_bound;
+	uint32_t vdd_mem;
+	uint32_t vdd_dig_upper_bound;
+	uint32_t vdd_dig;
+
+	uint32_t latency_us[NR_CPUS];
+	uint32_t power[NR_CPUS];
+};
+
 struct msm_rpmrs_level {
 	enum msm_pm_sleep_mode sleep_mode;
 	struct msm_rpmrs_limits rs_limits;
@@ -67,6 +93,15 @@
 	uint32_t time_overhead_us;
 };
 
+struct msm_rpmrs_platform_data {
+	struct msm_rpmrs_level *levels;
+	unsigned int num_levels;
+	unsigned int vdd_mem_levels[MSM_RPMRS_VDD_MEM_LAST];
+	unsigned int vdd_dig_levels[MSM_RPMRS_VDD_DIG_LAST];
+	unsigned int vdd_mask;
+	unsigned int rpmrs_target_id[MSM_RPMRS_ID_LAST];
+};
+
 int msm_rpmrs_set(int ctx, struct msm_rpm_iv_pair *req, int count);
 int msm_rpmrs_set_noirq(int ctx, struct msm_rpm_iv_pair *req, int count);
 int msm_rpmrs_set_bits_noirq(int ctx, struct msm_rpm_iv_pair *req, int count,
@@ -112,6 +147,6 @@
 void msm_rpmrs_exit_sleep(struct msm_rpmrs_limits *limits, bool from_idle,
 		bool notify_rpm, bool collapsed);
 
-int msm_rpmrs_levels_init(struct msm_rpmrs_level *levels, int size);
+int msm_rpmrs_levels_init(struct msm_rpmrs_platform_data *data);
 
 #endif /* __ARCH_ARM_MACH_MSM_RPM_RESOURCES_H */
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 514f817..b95c3aa 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -102,6 +102,45 @@
 	uint32_t last_value;
 };
 
+struct interrupt_config_item {
+	/* must be initialized */
+	irqreturn_t (*irq_handler)(int req, void *data);
+	/* outgoing interrupt config (set from platform data) */
+	uint32_t out_bit_pos;
+	void __iomem *out_base;
+	uint32_t out_offset;
+};
+
+struct interrupt_config {
+	struct interrupt_config_item smd;
+	struct interrupt_config_item smsm;
+};
+
+static irqreturn_t smd_modem_irq_handler(int irq, void *data);
+static irqreturn_t smd_dsp_irq_handler(int irq, void *data);
+static irqreturn_t smd_dsps_irq_handler(int irq, void *data);
+static irqreturn_t smd_wcnss_irq_handler(int irq, void *data);
+static irqreturn_t smsm_irq_handler(int irq, void *data);
+
+static struct interrupt_config private_intr_config[NUM_SMD_SUBSYSTEMS] = {
+	[SMD_MODEM] = {
+		.smd.irq_handler = smd_modem_irq_handler,
+		.smsm.irq_handler = smsm_irq_handler,
+	},
+	[SMD_Q6] = {
+		.smd.irq_handler = smd_dsp_irq_handler,
+		.smsm.irq_handler = smsm_irq_handler,
+	},
+	[SMD_DSPS] = {
+		.smd.irq_handler = smd_dsps_irq_handler,
+		.smsm.irq_handler = smsm_irq_handler,
+	},
+	[SMD_WCNSS] = {
+		.smd.irq_handler = smd_wcnss_irq_handler,
+		.smsm.irq_handler = smsm_irq_handler,
+	},
+};
+
 #define SMSM_STATE_ADDR(entry)           (smsm_info.state + entry)
 #define SMSM_INTR_MASK_ADDR(entry, host) (smsm_info.intr_mask + \
 					  entry * SMSM_NUM_HOSTS + host)
@@ -240,7 +279,6 @@
 static remote_spinlock_t remote_spinlock;
 
 static LIST_HEAD(smd_ch_list_loopback);
-static irqreturn_t smsm_irq_handler(int irq, void *data);
 static void smd_fake_irq_handler(unsigned long arg);
 static void smsm_cb_snapshot(void);
 
@@ -275,6 +313,98 @@
 static inline void wakeup_v1_riva(void) {}
 #endif
 
+static inline void notify_modem_smd(void)
+{
+	static const struct interrupt_config_item *intr
+	   = &private_intr_config[SMD_MODEM].smd;
+	if (intr->out_base)
+		smd_write_intr(intr->out_bit_pos,
+		intr->out_base + intr->out_offset);
+	else
+		MSM_TRIG_A2M_SMD_INT;
+}
+
+static inline void notify_dsp_smd(void)
+{
+	static const struct interrupt_config_item *intr
+		= &private_intr_config[SMD_Q6].smd;
+	if (intr->out_base)
+		smd_write_intr(intr->out_bit_pos,
+		intr->out_base + intr->out_offset);
+	else
+		MSM_TRIG_A2Q6_SMD_INT;
+}
+
+static inline void notify_dsps_smd(void)
+{
+	static const struct interrupt_config_item *intr
+		= &private_intr_config[SMD_DSPS].smd;
+	if (intr->out_base)
+		smd_write_intr(intr->out_bit_pos,
+		intr->out_base + intr->out_offset);
+	else
+		MSM_TRIG_A2DSPS_SMD_INT;
+}
+
+static inline void notify_wcnss_smd(void)
+{
+	static const struct interrupt_config_item *intr
+		= &private_intr_config[SMD_WCNSS].smd;
+	wakeup_v1_riva();
+
+	if (intr->out_base)
+		smd_write_intr(intr->out_bit_pos,
+		intr->out_base + intr->out_offset);
+	else
+		MSM_TRIG_A2WCNSS_SMD_INT;
+}
+
+static inline void notify_modem_smsm(void)
+{
+	static const struct interrupt_config_item *intr
+		= &private_intr_config[SMD_MODEM].smsm;
+	if (intr->out_base)
+		smd_write_intr(intr->out_bit_pos,
+		intr->out_base + intr->out_offset);
+	else
+		MSM_TRIG_A2M_SMSM_INT;
+}
+
+static inline void notify_dsp_smsm(void)
+{
+	static const struct interrupt_config_item *intr
+		= &private_intr_config[SMD_Q6].smsm;
+	if (intr->out_base)
+		smd_write_intr(intr->out_bit_pos,
+		intr->out_base + intr->out_offset);
+	else
+		MSM_TRIG_A2Q6_SMSM_INT;
+}
+
+static inline void notify_dsps_smsm(void)
+{
+	static const struct interrupt_config_item *intr
+		= &private_intr_config[SMD_DSPS].smsm;
+	if (intr->out_base)
+		smd_write_intr(intr->out_bit_pos,
+		intr->out_base + intr->out_offset);
+	else
+		MSM_TRIG_A2DSPS_SMSM_INT;
+}
+
+static inline void notify_wcnss_smsm(void)
+{
+	static const struct interrupt_config_item *intr
+		= &private_intr_config[SMD_WCNSS].smsm;
+	wakeup_v1_riva();
+
+	if (intr->out_base)
+		smd_write_intr(intr->out_bit_pos,
+		intr->out_base + intr->out_offset);
+	else
+		MSM_TRIG_A2WCNSS_SMSM_INT;
+}
+
 static void notify_other_smsm(uint32_t smsm_entry, uint32_t notify_mask)
 {
 	/* older protocol don't use smsm_intr_mask,
@@ -282,7 +412,7 @@
 	if (!smsm_info.intr_mask ||
 	    (__raw_readl(SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_MODEM))
 				& notify_mask))
-		MSM_TRIG_A2M_SMSM_INT;
+		notify_modem_smsm();
 
 	if (smsm_info.intr_mask &&
 	    (__raw_readl(SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_Q6))
@@ -296,46 +426,24 @@
 			__raw_writel(mux_val,
 					SMSM_INTR_MUX_ADDR(SMEM_APPS_Q6_SMSM));
 		}
-		MSM_TRIG_A2Q6_SMSM_INT;
+		notify_dsp_smsm();
 	}
 
 	if (smsm_info.intr_mask &&
 	    (__raw_readl(SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_WCNSS))
 				& notify_mask)) {
-		wakeup_v1_riva();
-		MSM_TRIG_A2WCNSS_SMSM_INT;
+		notify_wcnss_smsm();
 	}
 
 	if (smsm_info.intr_mask &&
 	    (__raw_readl(SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_DSPS))
 				& notify_mask)) {
-		MSM_TRIG_A2DSPS_SMSM_INT;
+		notify_dsps_smsm();
 	}
 
 	smsm_cb_snapshot();
 }
 
-static inline void notify_modem_smd(void)
-{
-	MSM_TRIG_A2M_SMD_INT;
-}
-
-static inline void notify_dsp_smd(void)
-{
-	MSM_TRIG_A2Q6_SMD_INT;
-}
-
-static inline void notify_dsps_smd(void)
-{
-	MSM_TRIG_A2DSPS_SMD_INT;
-}
-
-static inline void notify_wcnss_smd(void)
-{
-	wakeup_v1_riva();
-	MSM_TRIG_A2WCNSS_SMD_INT;
-}
-
 void smd_diag(void)
 {
 	char *x;
@@ -451,23 +559,6 @@
 	uint32_t	remote_pid;
 };
 
-/*
- * SMD Processor ID's.
- *
- * For all processors that have both SMSM and SMD clients,
- * the SMSM Processor ID and the SMD Processor ID will
- * be the same.  In cases where a processor only supports
- * SMD, the entry will only exist in this enum.
- */
-enum {
-	SMD_APPS = SMSM_APPS,
-	SMD_MODEM = SMSM_MODEM,
-	SMD_Q6 = SMSM_Q6,
-	SMD_WCNSS = SMSM_WCNSS,
-	SMD_DSPS = SMSM_DSPS,
-	SMD_MODEM_Q6_FW,
-};
-
 /**
  * Maps edge type to local and remote processor ID's.
  */
@@ -1008,32 +1099,26 @@
 	return IRQ_HANDLED;
 }
 
-#if defined(CONFIG_QDSP6)
 static irqreturn_t smd_dsp_irq_handler(int irq, void *data)
 {
 	handle_smd_irq(&smd_ch_list_dsp, notify_dsp_smd);
 	handle_smd_irq_closing_list();
 	return IRQ_HANDLED;
 }
-#endif
 
-#if defined(CONFIG_DSPS)
 static irqreturn_t smd_dsps_irq_handler(int irq, void *data)
 {
 	handle_smd_irq(&smd_ch_list_dsps, notify_dsps_smd);
 	handle_smd_irq_closing_list();
 	return IRQ_HANDLED;
 }
-#endif
 
-#if defined(CONFIG_WCNSS)
 static irqreturn_t smd_wcnss_irq_handler(int irq, void *data)
 {
 	handle_smd_irq(&smd_ch_list_wcnss, notify_wcnss_smd);
 	handle_smd_irq_closing_list();
 	return IRQ_HANDLED;
 }
-#endif
 
 static void smd_fake_irq_handler(unsigned long arg)
 {
@@ -1135,8 +1220,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) {
@@ -1459,18 +1546,16 @@
 	struct smd_channel *ch;
 	struct smd_channel *index;
 
+	mutex_lock(&smd_creation_mutex);
 	spin_lock_irqsave(&smd_lock, flags);
 	list_for_each_entry_safe(ch, index,  &smd_ch_to_close_list, ch_list) {
 		list_del(&ch->ch_list);
-		spin_unlock_irqrestore(&smd_lock, flags);
-		mutex_lock(&smd_creation_mutex);
 		list_add(&ch->ch_list, &smd_ch_closed_list);
-		mutex_unlock(&smd_creation_mutex);
 		ch->notify(ch->priv, SMD_EVENT_REOPEN_READY);
 		ch->notify = do_nothing_notify;
-		spin_lock_irqsave(&smd_lock, flags);
 	}
 	spin_unlock_irqrestore(&smd_lock, flags);
+	mutex_unlock(&smd_creation_mutex);
 }
 
 struct smd_channel *smd_get_channel(const char *name, uint32_t type)
@@ -1506,8 +1591,34 @@
 	SMD_DBG("smd_open('%s', %p, %p)\n", name, priv, notify);
 
 	ch = smd_get_channel(name, edge);
-	if (!ch)
-		return -ENODEV;
+	if (!ch) {
+		/* check closing list for port */
+		spin_lock_irqsave(&smd_lock, flags);
+		list_for_each_entry(ch, &smd_ch_closing_list, ch_list) {
+			if (!strncmp(name, ch->name, 20) &&
+				(edge == ch->type)) {
+				/* channel exists, but is being closed */
+				spin_unlock_irqrestore(&smd_lock, flags);
+				return -EAGAIN;
+			}
+		}
+
+		/* check closing workqueue list for port */
+		list_for_each_entry(ch, &smd_ch_to_close_list, ch_list) {
+			if (!strncmp(name, ch->name, 20) &&
+				(edge == ch->type)) {
+				/* channel exists, but is being closed */
+				spin_unlock_irqrestore(&smd_lock, flags);
+				return -EAGAIN;
+			}
+		}
+		spin_unlock_irqrestore(&smd_lock, flags);
+
+		/* one final check to handle closing->closed race condition */
+		ch = smd_get_channel(name, edge);
+		if (!ch)
+			return -ENODEV;
+	}
 
 	if (notify == 0)
 		notify = do_nothing_notify;
@@ -2541,22 +2652,121 @@
 		pr_err("smd_core_init: "
 		       "enable_irq_wake failed for INT_DSPS_A11_SMSM\n");
 #endif
-
-	/* we may have missed a signal while booting -- fake
-	 * an interrupt to make sure we process any existing
-	 * state
-	 */
-	smsm_irq_handler(0, 0);
-
 	SMD_INFO("smd_core_init() done\n");
 
 	return 0;
 }
 
+static int intr_init(struct interrupt_config_item *private_irq,
+			struct smd_irq_config *platform_irq,
+			struct platform_device *pdev
+			)
+{
+	int irq_id;
+	int ret;
+	int ret_wake;
+
+	private_irq->out_bit_pos = platform_irq->out_bit_pos;
+	private_irq->out_offset = platform_irq->out_offset;
+	private_irq->out_base = platform_irq->out_base;
+
+	irq_id = platform_get_irq_byname(
+					pdev,
+					platform_irq->irq_name
+				);
+	SMD_DBG("smd: %s: register irq: %s id: %d\n", __func__,
+				platform_irq->irq_name, irq_id);
+	ret = request_irq(irq_id,
+				private_irq->irq_handler,
+				platform_irq->flags,
+				platform_irq->device_name,
+				(void *)platform_irq->dev_id
+			);
+	if (ret < 0) {
+		platform_irq->irq_id = ret;
+	} else {
+		platform_irq->irq_id = irq_id;
+		ret_wake = enable_irq_wake(irq_id);
+		if (ret_wake < 0) {
+			pr_err("smd: enable_irq_wake failed on %s",
+					platform_irq->irq_name);
+		}
+	}
+
+	return ret;
+}
+
+int smd_core_platform_init(struct platform_device *pdev)
+{
+	int i;
+	int ret;
+	uint32_t num_ss;
+	struct smd_platform *smd_platform_data;
+	struct smd_subsystem_config *smd_ss_config_list;
+	struct smd_subsystem_config *cfg;
+	int err_ret = 0;
+
+	smd_platform_data = pdev->dev.platform_data;
+	num_ss = smd_platform_data->num_ss_configs;
+	smd_ss_config_list = smd_platform_data->smd_ss_configs;
+
+	for (i = 0; i < num_ss; i++) {
+		cfg = &smd_ss_config_list[i];
+
+		ret = intr_init(
+			&private_intr_config[cfg->irq_config_id].smd,
+			&cfg->smd_int,
+			pdev
+			);
+
+		if (ret < 0) {
+			err_ret = ret;
+			pr_err("smd: register irq failed on %s\n",
+				cfg->smd_int.irq_name);
+			break;
+		}
+
+		ret = intr_init(
+			&private_intr_config[cfg->irq_config_id].smsm,
+			&cfg->smsm_int,
+			pdev
+			);
+
+		if (ret < 0) {
+			err_ret = ret;
+			pr_err("smd: register irq failed on %s\n",
+				cfg->smsm_int.irq_name);
+			break;
+		}
+	}
+
+	if (err_ret < 0) {
+		pr_err("smd: deregistering IRQs\n");
+		for (i = 0; i < num_ss; ++i) {
+			cfg = &smd_ss_config_list[i];
+
+			if (cfg->smd_int.irq_id >= 0)
+				free_irq(cfg->smd_int.irq_id,
+					(void *)cfg->smd_int.dev_id
+					);
+			if (cfg->smsm_int.irq_id >= 0)
+				free_irq(cfg->smsm_int.irq_id,
+					(void *)cfg->smsm_int.dev_id
+					);
+		}
+		return err_ret;
+	}
+
+	SMD_INFO("smd_core_platform_init() done\n");
+	return 0;
+
+}
+
 static int __devinit msm_smd_probe(struct platform_device *pdev)
 {
-	SMD_INFO("smd probe\n");
+	int ret;
 
+	SMD_INFO("smd probe\n");
 	INIT_WORK(&probe_work, smd_channel_probe_worker);
 
 	channel_close_wq = create_singlethread_workqueue("smd_channel_close");
@@ -2570,9 +2780,27 @@
 		return -1;
 	}
 
-	if (smd_core_init()) {
-		pr_err("smd_core_init() failed\n");
-		return -1;
+	if (pdev) {
+		if (pdev->dev.of_node) {
+			pr_err("SMD: Device tree not currently supported\n");
+			return -ENODEV;
+		} else if (pdev->dev.platform_data) {
+			ret = smd_core_platform_init(pdev);
+			if (ret) {
+				pr_err(
+				"SMD: smd_core_platform_init() failed\n");
+				return -ENODEV;
+			}
+		} else {
+			ret = smd_core_init();
+			if (ret) {
+				pr_err("smd_core_init() failed\n");
+				return -ENODEV;
+			}
+		}
+	} else {
+		pr_err("SMD: PDEV not found\n");
+		return -ENODEV;
 	}
 
 	smd_initialized = 1;
@@ -2593,6 +2821,7 @@
 	{SMD_Q6, "lpass", .nb.notifier_call = restart_notifier_cb},
 	{SMD_WCNSS, "riva", .nb.notifier_call = restart_notifier_cb},
 	{SMD_DSPS, "dsps", .nb.notifier_call = restart_notifier_cb},
+	{SMD_MODEM, "gss", .nb.notifier_call = restart_notifier_cb},
 };
 
 static int restart_notifier_cb(struct notifier_block *this,
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 4744f1f..8023129 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.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
@@ -114,6 +114,11 @@
 		if (smd_pkt_devp[i]->devicep == d)
 			break;
 	}
+	if (i >= NUM_SMD_PKT_PORTS) {
+		pr_err("%s: unable to match device to valid smd_pkt port\n",
+			__func__);
+		return -EINVAL;
+	}
 	if (!strict_strtoul(buf, 10, &tmp)) {
 		smd_pkt_devp[i]->open_modem_wait = tmp;
 		return n;
@@ -133,6 +138,11 @@
 		if (smd_pkt_devp[i]->devicep == d)
 			break;
 	}
+	if (i >= NUM_SMD_PKT_PORTS) {
+		pr_err("%s: unable to match device to valid smd_pkt port\n",
+			__func__);
+		return -EINVAL;
+	}
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 			smd_pkt_devp[i]->open_modem_wait);
 }
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index c8248a7..4248be4 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -1,7 +1,7 @@
 /* arch/arm/mach-msm/smd_tty.c
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -552,8 +552,11 @@
 			legacy_ds |= cpu_is_msm7x01() || cpu_is_msm7x25();
 			legacy_ds |= cpu_is_msm7x27() || cpu_is_msm7x30();
 			legacy_ds |= cpu_is_qsd8x50() || cpu_is_msm8x55();
+			/*
+			 * use legacy mode for 8660 Standalone (subtype 0)
+			 */
 			legacy_ds |= cpu_is_msm8x60() &&
-					(socinfo_get_platform_subtype() == 0x1);
+					(socinfo_get_platform_subtype() == 0x0);
 
 			if (!legacy_ds)
 				continue;
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/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 9a8ab43..0ec88d5 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -241,6 +241,11 @@
 	/* Copper IDs */
 	[126] = MSM_CPU_COPPER,
 
+	/* 8625 IDs */
+	[127] = MSM_CPU_8625,
+	[128] = MSM_CPU_8625,
+	[129] = MSM_CPU_8625,
+
 	/* Uninitialized IDs are not known to run Linux.
 	   MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are
 	   considered as unknown CPU. */
@@ -609,6 +614,8 @@
 		dummy_socinfo.id = 104;
 	else if (early_machine_is_copper())
 		dummy_socinfo.id = 126;
+	else if (machine_is_msm8625_rumi3())
+		dummy_socinfo.id = 127;
 	return (void *) &dummy_socinfo;
 }
 
diff --git a/arch/arm/mach-msm/spm-v2.c b/arch/arm/mach-msm/spm-v2.c
index 021a216..4a7cf91 100644
--- a/arch/arm/mach-msm/spm-v2.c
+++ b/arch/arm/mach-msm/spm-v2.c
@@ -18,7 +18,6 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <mach/msm_iomap.h>
-#include <mach/socinfo.h>
 
 #include "spm_driver.h"
 
@@ -128,10 +127,6 @@
 {
 	uint32_t value = enable ? 0x01 : 0x00;
 
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return 0;
-
 	if (!dev)
 		return -EINVAL;
 
@@ -150,10 +145,6 @@
 	int i;
 	int num_spm_entry = msm_spm_drv_get_num_spm_entry(dev);
 
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return;
-
 	if (!dev) {
 		__WARN();
 		return;
@@ -174,10 +165,6 @@
 	uint32_t offset_w = offset / 4;
 	int ret = 0;
 
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return 0;
-
 	if (!cmd || !dev) {
 		__WARN();
 		goto failed_write_seq_data;
@@ -214,10 +201,6 @@
 		uint32_t addr)
 {
 
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return 0;
-
 	/* SPM is configured to reset start address to zero after end of Program
 	 */
 	if (!dev)
@@ -242,10 +225,6 @@
 {
 	uint32_t timeout_us;
 
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return 0;
-
 	if (!dev)
 		return -EINVAL;
 
@@ -299,10 +278,6 @@
 	int i;
 	int num_spm_entry;
 
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return 0;
-
 	BUG_ON(!dev || !data);
 
 	dev->reg_base_addr = data->reg_base_addr;
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index 326faef..883dec1 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -19,7 +19,6 @@
 #include <linux/slab.h>
 #include <mach/msm_iomap.h>
 #include <mach/socinfo.h>
-
 #include "spm.h"
 #include "spm_driver.h"
 
@@ -130,11 +129,6 @@
 int msm_spm_set_low_power_mode(unsigned int mode, bool notify_rpm)
 {
 	struct msm_spm_device *dev = &__get_cpu_var(msm_cpu_spm_device);
-
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return 0;
-
 	return msm_spm_dev_set_low_power_mode(dev, mode, notify_rpm);
 }
 
@@ -143,10 +137,6 @@
 	unsigned int cpu;
 	int ret = 0;
 
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return 0;
-
 	BUG_ON((nr_devs < num_possible_cpus()) || !data);
 
 	for_each_possible_cpu(cpu) {
@@ -167,23 +157,26 @@
 	uint32_t val = 0;
 	uint32_t timeout = 0;
 	void *reg = NULL;
+	void *saw_bases[] = {
+		0,
+		MSM_SAW1_BASE,
+		MSM_SAW2_BASE,
+		MSM_SAW3_BASE
+	};
 
-	if (cpu >= num_possible_cpus())
+	if (cpu == 0 || cpu >= num_possible_cpus())
 		return -EINVAL;
 
-	switch (cpu) {
-	case 1:
-		reg = MSM_SAW1_BASE;
-		break;
-	case 0:
-	default:
-		return -EFAULT;
-	}
+	reg = saw_bases[cpu];
 
 	if (cpu_is_msm8960() || cpu_is_msm8930()) {
 		val = 0xB0;
 		reg += 0x14;
 		timeout = 512;
+	} else if (cpu_is_apq8064()) {
+		val = 0xA4;
+		reg += 0x14;
+		timeout = 512;
 	} else {
 		return -ENOSYS;
 	}
@@ -207,10 +200,6 @@
 
 int __init msm_spm_l2_init(struct msm_spm_platform_data *data)
 {
-	/* TODO: Remove this after 8064 bring up */
-	if (cpu_is_apq8064())
-		return 0;
-
 	return msm_spm_dev_init(&msm_spm_l2_device, data);
 }
 #endif
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 67b1f7b..e566234 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 "
@@ -1081,7 +1087,8 @@
 			res = request_percpu_irq(ce->irq, msm_timer_interrupt,
 						 ce->name, clock->percpu_evt);
 			if (!res)
-				enable_percpu_irq(ce->irq, 0);
+				enable_percpu_irq(ce->irq,
+						 IRQ_TYPE_EDGE_RISING);
 		} else {
 			clock->evt = ce;
 			res = request_irq(ce->irq, msm_timer_interrupt,
@@ -1144,7 +1151,7 @@
 	*__this_cpu_ptr(clock->percpu_evt) = evt;
 
 	clockevents_register_device(evt);
-	enable_percpu_irq(evt->irq, 0);
+	enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING);
 
 	return 0;
 }
diff --git a/arch/arm/mach-msm/tz_log.c b/arch/arm/mach-msm/tz_log.c
index 8d7196b..7426bb2 100644
--- a/arch/arm/mach-msm/tz_log.c
+++ b/arch/arm/mach-msm/tz_log.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
@@ -53,8 +53,10 @@
  * Boot Info Table
  */
 struct tzdbg_boot_info_t {
-	uint32_t entry_cnt;	/* Warmboot entry CPU Counter */
-	uint32_t exit_cnt;	/* Warmboot exit CPU Counter */
+	uint32_t wb_entry_cnt;	/* Warmboot entry CPU Counter */
+	uint32_t wb_exit_cnt;	/* Warmboot exit CPU Counter */
+	uint32_t pc_entry_cnt;	/* Power Collapse entry CPU Counter */
+	uint32_t pc_exit_cnt;	/* Power Collapse exit CPU counter */
 	uint32_t warm_jmp_addr;	/* Last Warmboot Jump Address */
 	uint32_t spare;	/* Reserved for future use. */
 };
@@ -250,9 +252,12 @@
 				"  CPU #: %d\n"
 				"     Warmboot jump address     : 0x%x\n"
 				"     Warmboot entry CPU counter: 0x%x\n"
-				"     Warmboot exit CPU counter : 0x%x\n",
-				i, ptr->warm_jmp_addr, ptr->entry_cnt,
-				ptr->exit_cnt);
+				"     Warmboot exit CPU counter : 0x%x\n"
+				"     Power Collapse entry CPU counter: 0x%x\n"
+				"     Power Collapse exit CPU counter : 0x%x\n",
+				i, ptr->warm_jmp_addr, ptr->wb_entry_cnt,
+				ptr->wb_exit_cnt, ptr->pc_entry_cnt,
+				ptr->pc_exit_cnt);
 
 		if (len > (DEBUG_MAX_RW_BUF - 1)) {
 			pr_warn("%s: Cannot fit all info into the buffer\n",
@@ -555,5 +560,5 @@
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("TZ Log driver");
-MODULE_VERSION("1.0");
+MODULE_VERSION("1.1");
 MODULE_ALIAS("platform:tz_log");
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/base/genlock.c b/drivers/base/genlock.c
index 7e25684..1507915 100644
--- a/drivers/base/genlock.c
+++ b/drivers/base/genlock.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
@@ -110,6 +110,11 @@
 {
 	struct genlock *lock;
 
+	if (IS_ERR_OR_NULL(handle)) {
+		GENLOCK_LOG_ERR("Invalid handle\n");
+		return ERR_PTR(-EINVAL);
+	}
+
 	if (handle->lock != NULL) {
 		GENLOCK_LOG_ERR("Handle already has a lock attached\n");
 		return ERR_PTR(-EINVAL);
@@ -177,6 +182,11 @@
 	struct file *file;
 	struct genlock *lock;
 
+	if (IS_ERR_OR_NULL(handle)) {
+		GENLOCK_LOG_ERR("Invalid handle\n");
+		return ERR_PTR(-EINVAL);
+	}
+
 	if (handle->lock != NULL) {
 		GENLOCK_LOG_ERR("Handle already has a lock attached\n");
 		return ERR_PTR(-EINVAL);
@@ -392,9 +402,17 @@
 int genlock_lock(struct genlock_handle *handle, int op, int flags,
 	uint32_t timeout)
 {
-	struct genlock *lock = handle->lock;
+	struct genlock *lock;
+
 	int ret = 0;
 
+	if (IS_ERR_OR_NULL(handle)) {
+		GENLOCK_LOG_ERR("Invalid handle\n");
+		return -EINVAL;
+	}
+
+	lock = handle->lock;
+
 	if (lock == NULL) {
 		GENLOCK_LOG_ERR("Handle does not have a lock attached\n");
 		return -EINVAL;
@@ -426,11 +444,18 @@
 
 int genlock_wait(struct genlock_handle *handle, uint32_t timeout)
 {
-	struct genlock *lock = handle->lock;
+	struct genlock *lock;
 	unsigned long irqflags;
 	int ret = 0;
 	unsigned int ticks = msecs_to_jiffies(timeout);
 
+	if (IS_ERR_OR_NULL(handle)) {
+		GENLOCK_LOG_ERR("Invalid handle\n");
+		return -EINVAL;
+	}
+
+	lock = handle->lock;
+
 	if (lock == NULL) {
 		GENLOCK_LOG_ERR("Handle does not have a lock attached\n");
 		return -EINVAL;
@@ -471,12 +496,7 @@
 	return ret;
 }
 
-/**
- * genlock_release_lock - Release a lock attached to a handle
- * @handle - Pointer to the handle holding the lock
- */
-
-void genlock_release_lock(struct genlock_handle *handle)
+static void genlock_release_lock(struct genlock_handle *handle)
 {
 	unsigned long flags;
 
@@ -497,7 +517,6 @@
 	handle->lock = NULL;
 	handle->active = 0;
 }
-EXPORT_SYMBOL(genlock_release_lock);
 
 /*
  * Release function called when all references to a handle are released
@@ -589,6 +608,9 @@
 	struct genlock *lock;
 	int ret;
 
+	if (IS_ERR_OR_NULL(handle))
+		return -EINVAL;
+
 	switch (cmd) {
 	case GENLOCK_IOC_NEW: {
 		lock = genlock_create_lock(handle);
@@ -643,8 +665,13 @@
 		return genlock_wait(handle, param.timeout);
 	}
 	case GENLOCK_IOC_RELEASE: {
-		genlock_release_lock(handle);
-		return 0;
+		/*
+		 * Return error - this ioctl has been deprecated.
+		 * Locks should only be released when the handle is
+		 * destroyed
+		 */
+		GENLOCK_LOG_ERR("Deprecated RELEASE ioctl called\n");
+		return -EINVAL;
 	}
 	default:
 		GENLOCK_LOG_ERR("Invalid ioctl\n");
diff --git a/drivers/bluetooth/hci_smd.c b/drivers/bluetooth/hci_smd.c
index 101697f..332922e 100644
--- a/drivers/bluetooth/hci_smd.c
+++ b/drivers/bluetooth/hci_smd.c
@@ -2,7 +2,7 @@
  *  HCI_SMD (HCI Shared Memory Driver) is Qualcomm's Shared memory driver
  *  for the BT HCI protocol.
  *
- *  Copyright (c) 2000-2001, 2011 Code Aurora Forum. All rights reserved.
+ *  Copyright (c) 2000-2001, 2011-2012 Code Aurora Forum. All rights reserved.
  *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
  *  Copyright (C) 2004-2006  Marcel Holtmann <marcel@holtmann.org>
  *
@@ -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>
@@ -33,7 +34,12 @@
 
 #define EVENT_CHANNEL		"APPS_RIVA_BT_CMD"
 #define DATA_CHANNEL		"APPS_RIVA_BT_ACL"
-#define RX_Q_MONITOR		(1)	/* 1 milli second */
+/* release wakelock in 500ms, not immediately, because higher layers
+ * don't always take wakelocks when they should
+ * This is derived from the implementation for UART transport
+ */
+
+#define RX_Q_MONITOR		(500)	/* 500 milli second */
 
 
 static int hcismd_set;
@@ -42,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;
@@ -51,8 +58,7 @@
 	struct wake_lock wake_lock_tx;
 	struct wake_lock wake_lock_rx;
 	struct timer_list rx_q_timer;
-	struct tasklet_struct hci_event_task;
-	struct tasklet_struct hci_data_task;
+	struct tasklet_struct rx_task;
 };
 static struct hci_smd_data hs;
 
@@ -129,111 +135,95 @@
 		kfree(hdev->driver_data);
 }
 
-static void hci_smd_recv_data(unsigned long arg)
+static void hci_smd_recv_data(void)
 {
 	int len = 0;
 	int rc = 0;
 	struct sk_buff *skb = NULL;
-	unsigned  char *buf = NULL;
 	struct hci_smd_data *hsmd = &hs;
 	wake_lock(&hs.wake_lock_rx);
 
 	len = smd_read_avail(hsmd->data_channel);
 	if (len > HCI_MAX_FRAME_SIZE) {
-		BT_ERR("Frame larger than the allowed size");
+		BT_ERR("Frame larger than the allowed size, flushing frame");
+		smd_read(hsmd->data_channel, NULL, len);
 		goto out_data;
 	}
-	while (len > 0) {
-		skb = bt_skb_alloc(len, GFP_ATOMIC);
-		if (!skb) {
-			BT_ERR("Error in allocating  socket buffer");
-			goto out_data;
-		}
 
-		buf = kmalloc(len, GFP_ATOMIC);
-		if (!buf)  {
-			BT_ERR("Error in allocating  buffer");
-			rc = -ENOMEM;
-			goto out_data;
-		}
+	if (len <= 0)
+		goto out_data;
 
-		rc = smd_read(hsmd->data_channel, (void *)buf, len);
-		if (rc < len) {
-			BT_ERR("Error in reading from the channel");
-			goto out_data;
-		}
-
-		memcpy(skb_put(skb, len), buf, len);
-		skb->dev = (void *)hsmd->hdev;
-		bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
-
-		skb_orphan(skb);
-
-		rc = hci_recv_frame(skb);
-		if (rc < 0) {
-			BT_ERR("Error in passing the packet to HCI Layer");
-			/*
-			 * skb is getting freed in hci_recv_frame, making it
-			 * to null to avoid multiple access
-			 */
-			skb = NULL;
-			goto out_data;
-		}
-
-		kfree(buf);
-		buf = NULL;
-		len = smd_read_avail(hsmd->data_channel);
-		/*
-		 * Start the timer to monitor whether the Rx queue is
-		 * empty for releasing the Rx wake lock
-		 */
-		BT_DBG("Rx Timer is starting");
-		mod_timer(&hsmd->rx_q_timer,
-				jiffies + msecs_to_jiffies(RX_Q_MONITOR));
+	skb = bt_skb_alloc(len, GFP_ATOMIC);
+	if (!skb) {
+		BT_ERR("Error in allocating socket buffer");
+		smd_read(hsmd->data_channel, NULL, len);
+		goto out_data;
 	}
+
+	rc = smd_read(hsmd->data_channel, skb_put(skb, len), len);
+	if (rc < len) {
+		BT_ERR("Error in reading from the channel");
+		goto out_data;
+	}
+
+	skb->dev = (void *)hsmd->hdev;
+	bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
+	skb_orphan(skb);
+
+	rc = hci_recv_frame(skb);
+	if (rc < 0) {
+		BT_ERR("Error in passing the packet to HCI Layer");
+		/*
+		 * skb is getting freed in hci_recv_frame, making it
+		 * to null to avoid multiple access
+		 */
+		skb = NULL;
+		goto out_data;
+	}
+
+	/*
+	 * Start the timer to monitor whether the Rx queue is
+	 * empty for releasing the Rx wake lock
+	 */
+	BT_DBG("Rx Timer is starting");
+	mod_timer(&hsmd->rx_q_timer,
+			jiffies + msecs_to_jiffies(RX_Q_MONITOR));
+
 out_data:
 	release_lock();
-	if (rc) {
-		if (skb)
-			kfree_skb(skb);
-		kfree(buf);
-	}
+	if (rc)
+		kfree_skb(skb);
 }
 
-static void hci_smd_recv_event(unsigned long arg)
+static void hci_smd_recv_event(void)
 {
 	int len = 0;
 	int rc = 0;
 	struct sk_buff *skb = NULL;
-	unsigned  char *buf = NULL;
 	struct hci_smd_data *hsmd = &hs;
 	wake_lock(&hs.wake_lock_rx);
 
 	len = smd_read_avail(hsmd->event_channel);
 	if (len > HCI_MAX_FRAME_SIZE) {
-		BT_ERR("Frame larger than the allowed size");
+		BT_ERR("Frame larger than the allowed size, flushing frame");
+		rc = smd_read(hsmd->event_channel, NULL, len);
 		goto out_event;
 	}
 
 	while (len > 0) {
 		skb = bt_skb_alloc(len, GFP_ATOMIC);
 		if (!skb) {
-			BT_ERR("Error in allocating  socket buffer");
+			BT_ERR("Error in allocating socket buffer");
+			smd_read(hsmd->event_channel, NULL, len);
 			goto out_event;
 		}
-		buf = kmalloc(len, GFP_ATOMIC);
-		if (!buf) {
-			BT_ERR("Error in allocating  buffer");
-			rc = -ENOMEM;
-			goto out_event;
-		}
-		rc = smd_read(hsmd->event_channel, (void *)buf, len);
+
+		rc = smd_read(hsmd->event_channel, skb_put(skb, len), len);
 		if (rc < len) {
 			BT_ERR("Error in reading from the event channel");
 			goto out_event;
 		}
 
-		memcpy(skb_put(skb, len), buf, len);
 		skb->dev = (void *)hsmd->hdev;
 		bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
 
@@ -250,8 +240,6 @@
 			goto out_event;
 		}
 
-		kfree(buf);
-		buf = NULL;
 		len = smd_read_avail(hsmd->event_channel);
 		/*
 		 * Start the timer to monitor whether the Rx queue is
@@ -263,11 +251,8 @@
 	}
 out_event:
 	release_lock();
-	if (rc) {
-		if (skb)
-			kfree_skb(skb);
-		kfree(buf);
-	}
+	if (rc)
+		kfree_skb(skb);
 }
 
 static int hci_smd_send_frame(struct sk_buff *skb)
@@ -314,11 +299,22 @@
 	return ret;
 }
 
+static void hci_smd_rx(unsigned long arg)
+{
+	struct hci_smd_data *hsmd = &hs;
+
+	while ((smd_read_avail(hsmd->event_channel) > 0) ||
+				(smd_read_avail(hsmd->data_channel) > 0)) {
+		hci_smd_recv_event();
+		hci_smd_recv_data();
+	}
+}
 
 static void hci_smd_notify_event(void *data, unsigned int event)
 {
 	struct hci_dev *hdev = hs.hdev;
 	struct hci_smd_data *hsmd = &hs;
+	struct work_struct *reset_worker;
 	int len = 0;
 
 	if (!hdev) {
@@ -330,7 +326,7 @@
 	case SMD_EVENT_DATA:
 		len = smd_read_avail(hsmd->event_channel);
 		if (len > 0)
-			tasklet_hi_schedule(&hs.hci_event_task);
+			tasklet_hi_schedule(&hs.rx_task);
 		else if (len < 0)
 			BT_ERR("Failed to read event from smd %d", len);
 
@@ -342,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;
@@ -355,7 +358,7 @@
 	int len = 0;
 
 	if (!hdev) {
-		BT_ERR("HCI device (hdev=NULL)");
+		BT_ERR("Frame for unknown HCI device (hdev=NULL)");
 		return;
 	}
 
@@ -363,7 +366,7 @@
 	case SMD_EVENT_DATA:
 		len = smd_read_avail(hsmd->data_channel);
 		if (len > 0)
-			tasklet_hi_schedule(&hs.hci_data_task);
+			tasklet_hi_schedule(&hs.rx_task);
 		else if (len < 0)
 			BT_ERR("Failed to read data from smd %d", len);
 		break;
@@ -402,10 +405,9 @@
 	hdev->destruct = hci_smd_destruct;
 	hdev->owner = THIS_MODULE;
 
-	tasklet_init(&hsmd->hci_event_task,
-			hci_smd_recv_event, (unsigned long) hsmd);
-	tasklet_init(&hsmd->hci_data_task,
-			hci_smd_recv_data, (unsigned long) hsmd);
+
+	tasklet_init(&hsmd->rx_task,
+			hci_smd_rx, (unsigned long) hsmd);
 	/*
 	 * Setup the timer to monitor whether the Rx queue is empty,
 	 * to control the wake lock release
@@ -445,6 +447,8 @@
 
 static void hci_smd_deregister_dev(struct hci_smd_data *hsmd)
 {
+	tasklet_kill(&hs.rx_task);
+
 	if (hsmd->hdev) {
 		if (hci_unregister_dev(hsmd->hdev) < 0)
 			BT_ERR("Can't unregister HCI device %s",
@@ -468,9 +472,15 @@
 		hs.rx_q_timer.function = NULL;
 		hs.rx_q_timer.data = 0;
 	}
+}
 
-	tasklet_kill(&hs.hci_event_task);
-	tasklet_kill(&hs.hci_data_task);
+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)
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 6853654..7ceae89 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -80,11 +80,14 @@
 	case MSM8660_MACHINE_ID:
 		return APQ8060_TOOLS_ID;
 	case AO8960_MACHINE_ID:
+	case MSM8260A_MACHINE_ID:
 		return AO8960_TOOLS_ID;
 	case APQ8064_MACHINE_ID:
 		return APQ8064_TOOLS_ID;
 	case MSM8930_MACHINE_ID:
 		return MSM8930_TOOLS_ID;
+	case MSM8974_MACHINE_ID:
+		return MSM8974_TOOLS_ID;
 	default:
 		return 0;
 	}
@@ -105,12 +108,28 @@
 	case APQ8030_MACHINE_ID:
 	case MSM8627_MACHINE_ID:
 	case MSM8227_MACHINE_ID:
+	case MSM8974_MACHINE_ID:
+	case MDM9615_MACHINE_ID:
+	case MSM8260A_MACHINE_ID:
 		return 1;
 	default:
 		return 0;
 	}
 }
 
+/*
+ * This will return TRUE for targets which support apps as master.
+ * Thus, SW DLOAD and Mode Reset are supported on apps processor.
+ * This applies to 8960 and newer targets.
+ */
+int chk_apps_master(void)
+{
+	if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615())
+		return 1;
+	else
+		return 0;
+}
+
 void __diag_smd_send_req(void)
 {
 	void *buf = NULL;
@@ -532,8 +551,7 @@
 	} else {
 		if (len > 0) {
 			if (entry.client_id == MODEM_PROC && driver->ch) {
-				if ((cpu_is_msm8960() || cpu_is_msm8930() ||
-					cpu_is_msm9615()) &&
+				if (chk_apps_master() &&
 					 (int)(*(char *)buf) == MODE_CMD)
 					if ((int)(*(char *)(buf+1)) ==
 						RESET_ID)
@@ -573,8 +591,7 @@
 	temp += 2;
 	data_type = APPS_DATA;
 	/* Dont send any command other than mode reset */
-	if ((cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615()) &&
-		cmd_code == MODE_CMD) {
+	if (chk_apps_master() && cmd_code == MODE_CMD) {
 		if (subsys_id != RESET_ID)
 			data_type = MODEM_DATA;
 	}
@@ -858,8 +875,7 @@
 		return 0;
 	}
 	/* Check for download command */
-	else if ((cpu_is_msm8x60() || cpu_is_msm8960() || cpu_is_msm8930()
-		|| cpu_is_msm9615()) && (*buf == 0x3A)) {
+	else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
 		/* send response back */
 		driver->apps_rsp_buf[0] = *buf;
 		ENCODE_RSP_AND_SEND(0);
@@ -871,11 +887,12 @@
 		/* Not required, represents that command isnt sent to modem */
 		return 0;
 	}
-	 /* Check for ID for NO MODEM present */
-	else if (!(driver->ch)) {
-		/* Respond to polling for Apps only DIAG */
-		if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
-							 (*(buf+2) == 0x03)) {
+	/* Check for polling for Apps only DIAG */
+	else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
+		(*(buf+2) == 0x03)) {
+		/* If there is NO MODEM present */
+		if (!(driver->ch)) {
+			/* Respond to polling for Apps only DIAG */
 			for (i = 0; i < 3; i++)
 				driver->apps_rsp_buf[i] = *(buf+i);
 			for (i = 0; i < 13; i++)
@@ -883,9 +900,15 @@
 
 			ENCODE_RSP_AND_SEND(15);
 			return 0;
+		} else {
+			/* Since Modem is present, send error response */
+			return 1;
 		}
+	}
+	 /* Check for ID for NO MODEM present */
+	else if (!(driver->ch)) {
 		/* respond to 0x0 command */
-		else if (*buf == 0x00) {
+		if (*buf == 0x00) {
 			for (i = 0; i < 55; i++)
 				driver->apps_rsp_buf[i] = 0;
 
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 9730d4f..df2cd65 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.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
@@ -86,8 +86,8 @@
 				diagchar_ioctl(NULL, DIAG_IOCTL_COMMAND_REG,
 						 (unsigned long)pkt_params);
 				kfree(temp);
-				buf = buf + HDR_SIZ + data_len;
 			}
+			buf = buf + HDR_SIZ + data_len;
 		}
 	}
 	kfree(pkt_params);
@@ -135,7 +135,7 @@
 {
 	int r = 0;
 
-	/* open control ports only on 8960 */
+	/* open control ports only on 8960 & newer targets */
 	if (chk_apps_only()) {
 		if (pdev->id == SMD_APPS_MODEM)
 			r = smd_open("DIAG_CNTL", &driver->ch_cntl, driver,
diff --git a/drivers/char/hw_random/msm_rng.c b/drivers/char/hw_random/msm_rng.c
index b03a4ec..f5367ef 100644
--- a/drivers/char/hw_random/msm_rng.c
+++ b/drivers/char/hw_random/msm_rng.c
@@ -242,6 +242,9 @@
 
 static int __init msm_rng_init(void)
 {
+	if (cpu_is_apq8064())
+		return -ENODEV;
+
 	return platform_driver_register(&rng_driver);
 }
 
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 4079850..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:
@@ -808,6 +908,9 @@
 		mutex_lock(&dbs_mutex);
 		mutex_destroy(&this_dbs_info->timer_mutex);
 		dbs_enable--;
+		/* If device is being removed, policy is no longer
+		 * valid. */
+		this_dbs_info->cur_policy = NULL;
 		if (!cpu)
 			input_unregister_handler(&dbs_input_handler);
 		mutex_unlock(&dbs_mutex);
@@ -825,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.c b/drivers/gpu/ion/ion.c
index 386593f5..a6c36c8 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -151,7 +151,7 @@
 	rb_insert_color(&buffer->node, &dev->buffers);
 }
 
-void ion_iommu_add(struct ion_buffer *buffer,
+static void ion_iommu_add(struct ion_buffer *buffer,
 			  struct ion_iommu_map *iommu)
 {
 	struct rb_node **p = &buffer->iommu_maps.rb_node;
@@ -274,6 +274,7 @@
 	return handle;
 }
 
+/* Client lock must be locked when calling */
 static void ion_handle_destroy(struct kref *kref)
 {
 	struct ion_handle *handle = container_of(kref, struct ion_handle, ref);
@@ -282,10 +283,8 @@
 	 */
 	WARN_ON(handle->kmap_cnt || handle->dmap_cnt || handle->usermap_cnt);
 	ion_buffer_put(handle->buffer);
-	mutex_lock(&handle->client->lock);
 	if (!RB_EMPTY_NODE(&handle->node))
 		rb_erase(&handle->node, &handle->client->handles);
-	mutex_unlock(&handle->client->lock);
 	kfree(handle);
 }
 
@@ -438,6 +437,7 @@
 	ion_buffer_put(buffer);
 	return handle;
 }
+EXPORT_SYMBOL(ion_alloc);
 
 void ion_free(struct ion_client *client, struct ion_handle *handle)
 {
@@ -447,14 +447,15 @@
 
 	mutex_lock(&client->lock);
 	valid_handle = ion_handle_validate(client, handle);
-	mutex_unlock(&client->lock);
-
 	if (!valid_handle) {
+		mutex_unlock(&client->lock);
 		WARN("%s: invalid handle passed to free.\n", __func__);
 		return;
 	}
 	ion_handle_put(handle);
+	mutex_unlock(&client->lock);
 }
+EXPORT_SYMBOL(ion_free);
 
 static void ion_client_get(struct ion_client *client);
 static int ion_client_put(struct ion_client *client);
@@ -512,6 +513,7 @@
 	ret = buffer->heap->ops->phys(buffer->heap, buffer, addr, len);
 	return ret;
 }
+EXPORT_SYMBOL(ion_phys);
 
 void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle,
 			unsigned long flags)
@@ -558,8 +560,9 @@
 	mutex_unlock(&client->lock);
 	return vaddr;
 }
+EXPORT_SYMBOL(ion_map_kernel);
 
-int __ion_iommu_map(struct ion_buffer *buffer,
+static int __ion_iommu_map(struct ion_buffer *buffer,
 		int domain_num, int partition_num, unsigned long align,
 		unsigned long iova_length, unsigned long flags,
 		unsigned long *iova)
@@ -776,6 +779,7 @@
 	mutex_unlock(&client->lock);
 	return sglist;
 }
+EXPORT_SYMBOL(ion_map_dma);
 
 void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle)
 {
@@ -791,6 +795,7 @@
 	mutex_unlock(&buffer->lock);
 	mutex_unlock(&client->lock);
 }
+EXPORT_SYMBOL(ion_unmap_kernel);
 
 void ion_unmap_dma(struct ion_client *client, struct ion_handle *handle)
 {
@@ -806,7 +811,7 @@
 	mutex_unlock(&buffer->lock);
 	mutex_unlock(&client->lock);
 }
-
+EXPORT_SYMBOL(ion_unmap_dma);
 
 struct ion_buffer *ion_share(struct ion_client *client,
 				 struct ion_handle *handle)
@@ -828,6 +833,7 @@
 	 */
 	return handle->buffer;
 }
+EXPORT_SYMBOL(ion_share);
 
 struct ion_handle *ion_import(struct ion_client *client,
 			      struct ion_buffer *buffer)
@@ -849,6 +855,7 @@
 	mutex_unlock(&client->lock);
 	return handle;
 }
+EXPORT_SYMBOL(ion_import);
 
 static int check_vaddr_bounds(unsigned long start, unsigned long end)
 {
@@ -875,7 +882,7 @@
 	return ret;
 }
 
-int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
+static int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
 			void *uaddr, unsigned long offset, unsigned long len,
 			unsigned int cmd)
 {
@@ -937,6 +944,7 @@
 	fput(file);
 	return handle;
 }
+EXPORT_SYMBOL(ion_import_fd);
 
 static int ion_debug_client_show(struct seq_file *s, void *unused)
 {
@@ -1044,14 +1052,13 @@
 	client->handles = RB_ROOT;
 	mutex_init(&client->lock);
 
-	client->name = kzalloc(sizeof(name_len+1), GFP_KERNEL);
+	client->name = kzalloc(name_len+1, GFP_KERNEL);
 	if (!client->name) {
 		put_task_struct(current->group_leader);
 		kfree(client);
 		return ERR_PTR(-ENOMEM);
 	} else {
-		strncpy(client->name, name, name_len);
-		client->name[name_len] = '\0';
+		strlcpy(client->name, name, name_len+1);
 	}
 
 	client->heap_mask = heap_mask;
@@ -1138,6 +1145,7 @@
 	if (client)
 		ion_client_put(client);
 }
+EXPORT_SYMBOL(ion_client_destroy);
 
 int ion_handle_get_flags(struct ion_client *client, struct ion_handle *handle,
 			unsigned long *flags)
@@ -1245,7 +1253,9 @@
 		 atomic_read(&client->ref.refcount),
 		 atomic_read(&handle->ref.refcount),
 		 atomic_read(&buffer->ref.refcount));
+	mutex_lock(&client->lock);
 	ion_handle_put(handle);
+	mutex_unlock(&client->lock);
 	ion_client_put(client);
 	pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n",
 		 __func__, __LINE__,
@@ -1340,7 +1350,9 @@
 	mutex_unlock(&buffer->lock);
 	/* drop the reference to the handle */
 err1:
+	mutex_lock(&client->lock);
 	ion_handle_put(handle);
+	mutex_unlock(&client->lock);
 err:
 	/* drop the reference to the client */
 	ion_client_put(client);
@@ -1681,7 +1693,6 @@
 	mutex_unlock(&dev->lock);
 	return ret_val;
 }
-EXPORT_SYMBOL(ion_secure_heap);
 
 int ion_unsecure_heap(struct ion_device *dev, int heap_id)
 {
@@ -1708,7 +1719,6 @@
 	mutex_unlock(&dev->lock);
 	return ret_val;
 }
-EXPORT_SYMBOL(ion_unsecure_heap);
 
 static int ion_debug_leak_show(struct seq_file *s, void *unused)
 {
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 908b63d..5189388 100644
--- a/drivers/gpu/msm/Makefile
+++ b/drivers/gpu/msm/Makefile
@@ -8,7 +8,8 @@
 	kgsl_pwrscale.o \
 	kgsl_mmu.o \
 	kgsl_gpummu.o \
-	kgsl_iommu.o
+	kgsl_iommu.o \
+	kgsl_snapshot.o
 
 msm_kgsl_core-$(CONFIG_DEBUG_FS) += kgsl_debugfs.o
 msm_kgsl_core-$(CONFIG_MSM_KGSL_CFF_DUMP) += kgsl_cffdump.o
@@ -20,8 +21,12 @@
 	adreno_ringbuffer.o \
 	adreno_drawctxt.o \
 	adreno_postmortem.o \
+	adreno_snapshot.o \
 	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 5ffdea1..4c0bd19 100644
--- a/drivers/gpu/msm/a2xx_reg.h
+++ b/drivers/gpu/msm/a2xx_reg.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
@@ -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
@@ -416,4 +417,37 @@
 #define REG_A225_GRAS_UCP5W              0x2357
 #define REG_A225_GRAS_UCP_ENABLED        0x2360
 
+/* Debug registers used by snapshot */
+#define REG_PA_SU_DEBUG_CNTL            0x0C80
+#define REG_PA_SU_DEBUG_DATA            0x0C81
+#define REG_RB_DEBUG_CNTL               0x0F26
+#define REG_RB_DEBUG_DATA               0x0F27
+#define REG_PC_DEBUG_CNTL               0x0C38
+#define REG_PC_DEBUG_DATA               0x0C39
+#define REG_GRAS_DEBUG_CNTL             0x0C80
+#define REG_GRAS_DEBUG_DATA             0x0C81
+#define REG_SQ_DEBUG_MISC               0x0D05
+#define REG_SQ_DEBUG_INPUT_FSM          0x0DAE
+#define REG_SQ_DEBUG_CONST_MGR_FSM      0x0DAF
+#define REG_SQ_DEBUG_EXP_ALLOC          0x0DB3
+#define REG_SQ_DEBUG_FSM_ALU_0          0x0DB1
+#define REG_SQ_DEBUG_FSM_ALU_1          0x0DB2
+#define REG_SQ_DEBUG_PTR_BUFF           0x0DB4
+#define REG_SQ_DEBUG_GPR_VTX            0x0DB5
+#define REG_SQ_DEBUG_GPR_PIX            0x0DB6
+#define REG_SQ_DEBUG_TB_STATUS_SEL      0x0DB7
+#define REG_SQ_DEBUG_VTX_TB_0           0x0DB8
+#define REG_SQ_DEBUG_VTX_TB_1           0x0DB9
+#define REG_SQ_DEBUG_VTX_TB_STATE_MEM   0x0DBB
+#define REG_SQ_DEBUG_TP_FSM             0x0DB0
+#define REG_SQ_DEBUG_VTX_TB_STATUS_REG  0x0DBA
+#define REG_SQ_DEBUG_PIX_TB_0           0x0DBC
+#define REG_SQ_DEBUG_PIX_TB_STATUS_REG_0 0x0DBD
+#define REG_SQ_DEBUG_PIX_TB_STATUS_REG_1 0x0DBE
+#define REG_SQ_DEBUG_PIX_TB_STATUS_REG_2 0x0DBF
+#define REG_SQ_DEBUG_PIX_TB_STATUS_REG_3 0x0DC0
+#define REG_SQ_DEBUG_PIX_TB_STATE_MEM   0x0DC1
+#define REG_SQ_DEBUG_MISC_0             0x2309
+#define REG_SQ_DEBUG_MISC_1             0x230A
+
 #endif /* __A200_REG_H */
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 03e447b..805e2b6 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:
@@ -614,6 +565,7 @@
 	kgsl_mmu_stop(device);
 
 	device->ftbl->irqctrl(device, 0);
+	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
 
 	/* Power down the device */
 	kgsl_pwrctrl_disable(device);
@@ -728,8 +680,21 @@
 	} else {
 		kgsl_pwrctrl_set_state(device, KGSL_STATE_DUMP_AND_RECOVER);
 		INIT_COMPLETION(device->recovery_gate);
-		/* Detected a hang - trigger an automatic dump */
+		/* Detected a hang */
+
+
+		/*
+		 * Trigger an automatic dump of the state to
+		 * the console
+		 */
 		adreno_postmortem_dump(device, 0);
+
+		/*
+		 * Make a GPU snapshot.  For now, do it after the PM dump so we
+		 * can at least be sure the PM dump will work as it always has
+		 */
+		kgsl_device_snapshot(device, 1);
+
 		result = adreno_recover_hang(device);
 		if (result)
 			kgsl_pwrctrl_set_state(device, KGSL_STATE_HUNG);
@@ -856,7 +821,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
@@ -877,9 +843,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:
@@ -905,10 +877,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;
@@ -1094,7 +1073,8 @@
 			* get an interrupt */
 			cmds[0] = cp_type3_packet(CP_NOP, 1);
 			cmds[1] = 0;
-			adreno_ringbuffer_issuecmds(device, 0, &cmds[0], 2);
+			adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+				&cmds[0], 2);
 		}
 		mutex_unlock(&device->mutex);
 	}
@@ -1264,44 +1244,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)
@@ -1341,6 +1306,7 @@
 	.power_stats = adreno_power_stats,
 	.irqctrl = adreno_irqctrl,
 	.gpuid = adreno_gpuid,
+	.snapshot = adreno_snapshot,
 	/* Optional functions */
 	.setstate = adreno_setstate,
 	.drawctxt_create = adreno_drawctxt_create,
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index a3d2c00..9c2d704 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -24,6 +24,7 @@
 		KGSL_CONTAINER_OF(device, struct adreno_device, dev)
 
 /* Flags to control command packet settings */
+#define KGSL_CMD_FLAGS_NONE             0x00000000
 #define KGSL_CMD_FLAGS_PMODE		0x00000001
 #define KGSL_CMD_FLAGS_NO_TS_CMP	0x00000002
 #define KGSL_CMD_FLAGS_NOT_KERNEL_CMD	0x00000004
@@ -51,6 +52,7 @@
 	ADRENO_REV_A205 = 205,
 	ADRENO_REV_A220 = 220,
 	ADRENO_REV_A225 = 225,
+	ADRENO_REV_A320 = 320,
 };
 
 struct adreno_gpudev;
@@ -76,17 +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[];
@@ -94,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);
@@ -108,6 +125,9 @@
 uint8_t *adreno_convertaddr(struct kgsl_device *device,
 	unsigned int pt_base, unsigned int gpuaddr, unsigned int size);
 
+void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain,
+		int hang);
+
 static inline int adreno_is_a200(struct adreno_device *adreno_dev)
 {
 	return (adreno_dev->gpurev == ADRENO_REV_A200);
@@ -142,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 16402c3..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,46 +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 */
-	adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
 	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;
@@ -1363,11 +1346,10 @@
 		&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 */
-	/* Idle because we are reading PM override registers */
-	adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
 	drawctxt->context_gmem_shadow.gmem_save_commands = tmp_ctx.cmd;
 	tmp_ctx.cmd =
 	    build_gmem2sys_cmds(adreno_dev, drawctxt,
@@ -1388,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;
@@ -1401,24 +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, 0, context->reg_save, 3);
+		/* 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);
+		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, 0,
-			context->shader_fixup, 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;
+			context->flags |= CTXT_FLAGS_SHADER_RESTORE;
+		}
 	}
 
 	if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
@@ -1430,8 +1469,10 @@
 			context->context_gmem_shadow.gmem_save, 3);
 
 		/* Restore TP0_CHICKEN */
-		adreno_ringbuffer_issuecmds(device, 0,
-			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)) {
@@ -1461,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;
@@ -1481,7 +1522,7 @@
 	cmds[3] = device->memstore.gpuaddr +
 		KGSL_DEVICE_MEMSTORE_OFFSET(current_context);
 	cmds[4] = (unsigned int) context;
-	adreno_ringbuffer_issuecmds(device, 0, cmds, 5);
+	adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE, cmds, 5);
 	kgsl_mmu_setstate(device, context->pagetable);
 
 #ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
@@ -1497,27 +1538,34 @@
 		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
 			context->context_gmem_shadow.gmem_restore, 3);
 
-		/* Restore TP0_CHICKEN */
-		adreno_ringbuffer_issuecmds(device, 0,
-			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, 0,
-		context->reg_restore, 3);
+	if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
 
-	/* restore shader instructions & partitioning. */
-	if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
-		adreno_ringbuffer_issuecmds(device, 0,
-			context->shader_restore, 3);
+		/* restore registers and constants. */
+		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+			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)) {
 		cmds[0] = cp_type3_packet(CP_SET_BIN_BASE_OFFSET, 1);
 		cmds[1] = context->bin_base_offset;
-		adreno_ringbuffer_issuecmds(device, 0, cmds, 2);
+		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+			cmds, 2);
 	}
 }
 
@@ -1704,11 +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
new file mode 100644
index 0000000..091db22
--- /dev/null
+++ b/drivers/gpu/msm/adreno_a2xx_snapshot.c
@@ -0,0 +1,338 @@
+/* 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"
+
+#define DEBUG_SECTION_SZ(_dwords) (((_dwords) * sizeof(unsigned int)) \
+		+ sizeof(struct kgsl_snapshot_debug))
+
+/* Dump the SX debug registers into a GPU snapshot debug section */
+
+#define SXDEBUG_COUNT 0x1B
+
+static int a2xx_snapshot_sxdebug(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(SXDEBUG_COUNT)) {
+		SNAPSHOT_ERR_NOMEM(device, "SX DEBUG");
+		return 0;
+	}
+
+	header->type = SNAPSHOT_DEBUG_SX;
+	header->size = SXDEBUG_COUNT;
+
+	for (i = 0; i < SXDEBUG_COUNT; i++) {
+		adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1B00 | i);
+		adreno_regread(device, REG_RBBM_DEBUG_OUT, &data[i]);
+	}
+
+	adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0);
+
+	return DEBUG_SECTION_SZ(SXDEBUG_COUNT);
+}
+
+#define CPDEBUG_COUNT 0x20
+
+static int a2xx_snapshot_cpdebug(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(CPDEBUG_COUNT)) {
+		SNAPSHOT_ERR_NOMEM(device, "CP DEBUG");
+		return 0;
+	}
+
+	header->type = SNAPSHOT_DEBUG_CP;
+	header->size = CPDEBUG_COUNT;
+
+	for (i = 0; i < CPDEBUG_COUNT; i++) {
+		adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1628);
+		adreno_regread(device, REG_RBBM_DEBUG_OUT, &data[i]);
+	}
+
+	adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0);
+
+	return DEBUG_SECTION_SZ(CPDEBUG_COUNT);
+}
+
+/*
+ * The contents of the SQ debug sections are dword pairs:
+ * [register offset]:[value]
+ * This macro writes both dwords for the given register
+ */
+
+#define SQ_DEBUG_WRITE(_device, _reg, _data, _offset) \
+	do { _data[(_offset)++] = (_reg); \
+	adreno_regread(_device, (_reg), &_data[(_offset)++]); } while (0)
+
+#define SQ_DEBUG_BANK_SIZE 23
+
+static int a2xx_snapshot_sqdebug(struct kgsl_device *device, void *snapshot,
+	int remain, void *priv)
+{
+	struct kgsl_snapshot_debug *header = snapshot;
+	unsigned int *data = snapshot + sizeof(*header);
+	int i, offset = 0;
+	int size = SQ_DEBUG_BANK_SIZE * 2 * 2;
+
+	if (remain < DEBUG_SECTION_SZ(size)) {
+		SNAPSHOT_ERR_NOMEM(device, "SQ Debug");
+		return 0;
+	}
+
+	header->type = SNAPSHOT_DEBUG_SQ;
+	header->size = size;
+
+	for (i = 0; i < 2; i++) {
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_CONST_MGR_FSM+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_EXP_ALLOC+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_FSM_ALU_0+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_FSM_ALU_1+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_GPR_PIX+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_GPR_VTX+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_INPUT_FSM+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_MISC+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_MISC_0+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_MISC_1+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_PIX_TB_0+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_PIX_TB_STATE_MEM+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device,
+			REG_SQ_DEBUG_PIX_TB_STATUS_REG_0+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device,
+			REG_SQ_DEBUG_PIX_TB_STATUS_REG_1+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device,
+			REG_SQ_DEBUG_PIX_TB_STATUS_REG_2+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device,
+			REG_SQ_DEBUG_PIX_TB_STATUS_REG_3+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_PTR_BUFF+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_TB_STATUS_SEL+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_TP_FSM+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_VTX_TB_0+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_VTX_TB_1+i*0x1000,
+			data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_VTX_TB_STATE_MEM+i*0x1000,
+			data, offset);
+	}
+
+	return DEBUG_SECTION_SZ(size);
+}
+
+#define SQ_DEBUG_THREAD_SIZE 7
+
+static int a2xx_snapshot_sqthreaddebug(struct kgsl_device *device,
+	void *snapshot, int remain, void *priv)
+{
+	struct kgsl_snapshot_debug *header = snapshot;
+	unsigned int *data = snapshot + sizeof(*header);
+	int i, offset = 0;
+	int size = SQ_DEBUG_THREAD_SIZE * 2 * 16;
+
+	if (remain < DEBUG_SECTION_SZ(size)) {
+		SNAPSHOT_ERR_NOMEM(device, "SQ THREAD DEBUG");
+		return 0;
+	}
+
+	header->type = SNAPSHOT_DEBUG_SQTHREAD;
+	header->size = size;
+
+	for (i = 0; i < 16; i++) {
+		adreno_regwrite(device, REG_SQ_DEBUG_TB_STATUS_SEL,
+				i | (6<<4) | (i<<7) | (1<<11) | (1<<12)
+				| (i<<16) | (6<<20) | (i<<23));
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_VTX_TB_STATE_MEM,
+			 data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_VTX_TB_STATUS_REG,
+			 data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_PIX_TB_STATE_MEM,
+			 data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_PIX_TB_STATUS_REG_0,
+			 data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_PIX_TB_STATUS_REG_1,
+			 data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_PIX_TB_STATUS_REG_2,
+			 data, offset);
+		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_PIX_TB_STATUS_REG_3,
+			 data, offset);
+	}
+
+	return DEBUG_SECTION_SZ(size);
+}
+
+#define MIUDEBUG_COUNT 0x10
+
+static int a2xx_snapshot_miudebug(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(MIUDEBUG_COUNT)) {
+		SNAPSHOT_ERR_NOMEM(device, "MIU DEBUG");
+		return 0;
+	}
+
+	header->type = SNAPSHOT_DEBUG_MIU;
+	header->size = MIUDEBUG_COUNT;
+
+	for (i = 0; i < MIUDEBUG_COUNT; i++) {
+		adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1600 | i);
+		adreno_regread(device, REG_RBBM_DEBUG_OUT, &data[i]);
+	}
+
+	adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0);
+
+	return DEBUG_SECTION_SZ(MIUDEBUG_COUNT);
+}
+
+/* A2XX GPU snapshot function - this is where all of the A2XX specific
+ * bits and pieces are grabbed into the snapshot memory
+ */
+
+void *a2xx_snapshot(struct adreno_device *adreno_dev, void *snapshot,
+	int *remain, int hang)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+	struct kgsl_snapshot_registers regs;
+	unsigned int pmoverride;
+
+	/* Choose the register set to dump */
+
+	if (adreno_is_a20x(adreno_dev)) {
+		regs.regs = (unsigned int *) a200_registers;
+		regs.count = a200_registers_count;
+	} else {
+		regs.regs = (unsigned int *) a220_registers;
+		regs.count = a220_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);
+
+	/*
+	 * Need to temporarily turn off clock gating for the debug bus to
+	 * work
+	 */
+
+	adreno_regread(device, REG_RBBM_PM_OVERRIDE2, &pmoverride);
+	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xFF);
+
+	/* SX debug registers */
+	snapshot = kgsl_snapshot_add_section(device,
+			KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
+			a2xx_snapshot_sxdebug, NULL);
+
+	/* SU debug indexed registers (only for < 470) */
+	if (!adreno_is_a22x(adreno_dev))
+		snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
+				remain, REG_PA_SU_DEBUG_CNTL,
+				REG_PA_SU_DEBUG_DATA,
+				0, 0x1B);
+
+	/* CP debug registers */
+	snapshot = kgsl_snapshot_add_section(device,
+			KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
+			a2xx_snapshot_cpdebug, NULL);
+
+	/* MH debug indexed registers */
+	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 = kgsl_snapshot_indexed_registers(device, snapshot,
+			remain, REG_RB_DEBUG_CNTL, REG_RB_DEBUG_DATA, 0, 8);
+
+		/* RB DEBUG indexed registers bank 2 */
+		snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
+			remain, REG_RB_DEBUG_CNTL, REG_RB_DEBUG_DATA + 0x1000,
+			0, 8);
+
+		/* PC_DEBUG indexed registers */
+		snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
+			remain, REG_PC_DEBUG_CNTL, REG_PC_DEBUG_DATA, 0, 8);
+
+		/* GRAS_DEBUG indexed registers */
+		snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
+			remain, REG_GRAS_DEBUG_CNTL, REG_GRAS_DEBUG_DATA, 0, 4);
+
+		/* MIU debug registers */
+		snapshot = kgsl_snapshot_add_section(device,
+			KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
+			a2xx_snapshot_miudebug, NULL);
+
+		/* SQ DEBUG debug registers */
+		snapshot = kgsl_snapshot_add_section(device,
+			KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
+			a2xx_snapshot_sqdebug, NULL);
+
+		/*
+		 * Reading SQ THREAD causes bad things to happen on a running
+		 * system, so only read it if the GPU is already hung
+		 */
+
+		if (hang) {
+			/* SQ THREAD debug registers */
+			snapshot = kgsl_snapshot_add_section(device,
+				KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
+				a2xx_snapshot_sqthreaddebug, NULL);
+		}
+	}
+
+	/* Reset the clock gating */
+	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, pmoverride);
+
+	return snapshot;
+}
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/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
new file mode 100644
index 0000000..fb88a72
--- /dev/null
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -0,0 +1,332 @@
+/* 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 "kgsl_sharedmem.h"
+#include "kgsl_snapshot.h"
+
+#include "adreno.h"
+#include "adreno_pm4types.h"
+#include "a2xx_reg.h"
+
+/* Number of dwords of ringbuffer history to record */
+#define NUM_DWORDS_OF_RINGBUFFER_HISTORY 100
+
+/* Maintain a list of the objects we see during parsing */
+
+#define SNAPSHOT_OBJ_BUFSIZE 64
+
+#define SNAPSHOT_OBJ_TYPE_IB 0
+
+static struct kgsl_snapshot_obj {
+	int type;
+	uint32_t gpuaddr;
+	uint32_t ptbase;
+	void *ptr;
+	int dwords;
+} objbuf[SNAPSHOT_OBJ_BUFSIZE];
+
+/* Pointer to the next open entry in the object list */
+static int objbufptr;
+
+/* Push a new buffer object onto the list */
+static void push_object(struct kgsl_device *device, int type, uint32_t ptbase,
+	uint32_t gpuaddr, int dwords)
+{
+	int index;
+	void *ptr;
+
+	/* Go through the list and see that object has already been seen */
+	for (index = 0; index < objbufptr; index++) {
+		if (objbuf[index].gpuaddr == gpuaddr &&
+			objbuf[index].ptbase == ptbase)
+			return;
+	}
+
+	if (objbufptr == SNAPSHOT_OBJ_BUFSIZE) {
+		KGSL_DRV_ERR(device, "snapshot: too many snapshot objects\n");
+		return;
+	}
+
+	/*
+	 * adreno_convertaddr verifies that the IB size is valid - at least in
+	 * the context of it being smaller then the allocated memory space
+	 */
+	ptr = adreno_convertaddr(device, ptbase, gpuaddr, dwords << 2);
+
+	if (ptr == NULL) {
+		KGSL_DRV_ERR(device,
+			"snapshot: Can't find GPU address for %x\n", gpuaddr);
+		return;
+	}
+
+	/* Put it on the list of things to parse */
+	objbuf[objbufptr].type = type;
+	objbuf[objbufptr].gpuaddr = gpuaddr;
+	objbuf[objbufptr].ptbase = ptbase;
+	objbuf[objbufptr].dwords = dwords;
+	objbuf[objbufptr++].ptr = ptr;
+}
+
+/* Snapshot the istore memory */
+static int snapshot_istore(struct kgsl_device *device, void *snapshot,
+	int remain, void *priv)
+{
+	struct kgsl_snapshot_istore *header = snapshot;
+	unsigned int *data = snapshot + sizeof(*header);
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	int count, i;
+
+	count = adreno_dev->istore_size * ADRENO_ISTORE_WORDS;
+
+	if (remain < (count * 4) + sizeof(*header)) {
+		KGSL_DRV_ERR(device,
+			"snapshot: Not enough memory for the istore section");
+		return 0;
+	}
+
+	header->count = adreno_dev->istore_size;
+
+	for (i = 0; i < count; i++)
+		kgsl_regread(device, ADRENO_ISTORE_START + i, &data[i]);
+
+	return (count * 4) + sizeof(*header);
+}
+
+/* Snapshot the ringbuffer memory */
+static int snapshot_rb(struct kgsl_device *device, void *snapshot,
+	int remain, void *priv)
+{
+	struct kgsl_snapshot_rb *header = snapshot;
+	unsigned int *data = snapshot + sizeof(*header);
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
+	unsigned int rbbase, ptbase, rptr, *rbptr;
+	int start, stop, index;
+	int numitems, size;
+
+	/* Get the GPU address of the ringbuffer */
+	kgsl_regread(device, REG_CP_RB_BASE, &rbbase);
+
+	/* Get the physical address of the MMU pagetable */
+	ptbase = kgsl_mmu_get_current_ptbase(device);
+
+	/* Get the current read pointers for the RB */
+	kgsl_regread(device, REG_CP_RB_RPTR, &rptr);
+
+	/* start the dump at the rptr minus some history */
+	start = (int) rptr - NUM_DWORDS_OF_RINGBUFFER_HISTORY;
+	if (start < 0)
+		start += rb->sizedwords;
+
+	/*
+	 * Stop the dump at the point where the software last wrote.  Don't use
+	 * the hardware value here on the chance that it didn't get properly
+	 * updated
+	 */
+
+	stop = (int) rb->wptr + 16;
+	if (stop > rb->sizedwords)
+		stop -= rb->sizedwords;
+
+	/* Set up the header for the section */
+
+	numitems = (stop > start) ? stop - start :
+		(rb->sizedwords - start) + stop;
+
+	size = (numitems << 2);
+
+	if (remain < size + sizeof(*header)) {
+		KGSL_DRV_ERR(device,
+			"snapshot: Not enough memory for the rb section");
+		return 0;
+	}
+
+	/* Write the sub-header for the section */
+	header->start = start;
+	header->end = stop;
+	header->wptr = rb->wptr;
+	header->rbsize = rb->sizedwords;
+	header->count = numitems;
+
+	index = start;
+	rbptr = rb->buffer_desc.hostptr;
+
+	/*
+	 * Loop through the RB, copying the data and looking for indirect
+	 * buffers and MMU pagetable changes
+	 */
+
+	while (index != rb->wptr) {
+		*data = rbptr[index];
+
+		if (rbptr[index] == cp_type3_packet(CP_INDIRECT_BUFFER_PFD, 2))
+			push_object(device, SNAPSHOT_OBJ_TYPE_IB, ptbase,
+				rbptr[index + 1], rbptr[index + 2]);
+
+		/*
+		 * FIXME: Handle upcoming MMU pagetable changes, but only
+		 * between the rptr and the wptr
+		 */
+
+		index = index + 1;
+
+		if (index == rb->sizedwords)
+			index = 0;
+
+		data++;
+	}
+
+	/* Dump 16 dwords past the wptr, but don't  bother interpeting it */
+
+	while (index != stop) {
+		*data = rbptr[index];
+		index = index + 1;
+
+		if (index == rb->sizedwords)
+			index = 0;
+
+		data++;
+	}
+
+	/* Return the size of the section */
+	return size + sizeof(*header);
+}
+
+/* Snapshot the memory for an indirect buffer */
+static int snapshot_ib(struct kgsl_device *device, void *snapshot,
+	int remain, void *priv)
+{
+	struct kgsl_snapshot_ib *header = snapshot;
+	struct kgsl_snapshot_obj *obj = priv;
+	unsigned int *src = obj->ptr;
+	unsigned int *dst = snapshot + sizeof(*header);
+	int i;
+
+	if (remain < (obj->dwords << 2) + sizeof(*header)) {
+		KGSL_DRV_ERR(device,
+			"snapshot: Not enough memory for the ib section");
+		return 0;
+	}
+
+	/* Write the sub-header for the section */
+	header->gpuaddr = obj->gpuaddr;
+	header->ptbase = obj->ptbase;
+	header->size = obj->dwords;
+
+	/* Write the contents of the ib */
+	for (i = 0; i < obj->dwords; i++) {
+		*dst = *src;
+		/* If another IB is discovered, then push it on the list too */
+
+		if (*src == cp_type3_packet(CP_INDIRECT_BUFFER_PFD, 2)) {
+			push_object(device, SNAPSHOT_OBJ_TYPE_IB, obj->ptbase,
+				*(src + 1), *(src + 2));
+		}
+
+		src++;
+		dst++;
+	}
+
+	return (obj->dwords << 2) + sizeof(*header);
+}
+
+/* Dump another item on the current pending list */
+static void *dump_object(struct kgsl_device *device, int obj, void *snapshot,
+	int *remain)
+{
+	switch (objbuf[obj].type) {
+	case SNAPSHOT_OBJ_TYPE_IB:
+		snapshot = kgsl_snapshot_add_section(device,
+			KGSL_SNAPSHOT_SECTION_IB, snapshot, remain,
+			snapshot_ib, &objbuf[obj]);
+		break;
+	default:
+		KGSL_DRV_ERR(device,
+			"snapshot: Invalid snapshot object type: %d\n",
+			objbuf[obj].type);
+		break;
+	}
+
+	return snapshot;
+}
+
+/* adreno_snapshot - Snapshot the Adreno GPU state
+ * @device - KGSL device to snapshot
+ * @snapshot - Pointer to the start of memory to write into
+ * @remain - A pointer to how many bytes of memory are remaining in the snapshot
+ * @hang - set if this snapshot was automatically triggered by a GPU hang
+ * This is a hook function called by kgsl_snapshot to snapshot the
+ * Adreno specific information for the GPU snapshot.  In turn, this function
+ * calls the GPU specific snapshot function to get core specific information.
+ */
+
+void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain,
+		int hang)
+{
+	int i;
+	uint32_t ptbase, ibbase, ibsize;
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+
+	/* Reset the list of objects */
+	objbufptr = 0;
+
+	/* Get the physical address of the MMU pagetable */
+	ptbase = kgsl_mmu_get_current_ptbase(device);
+
+	/* Dump the ringbuffer */
+	snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_RB,
+		snapshot, remain, snapshot_rb, NULL);
+
+	/*
+	 * Make sure that the IBs described in the CP registers are on the
+	 * list of objects
+	 */
+	kgsl_regread(device, REG_CP_IB1_BASE, &ibbase);
+	kgsl_regread(device, REG_CP_IB1_BUFSZ, &ibsize);
+
+	if (ibsize)
+		push_object(device, SNAPSHOT_OBJ_TYPE_IB, ptbase,
+			ibbase, ibsize);
+
+	kgsl_regread(device, REG_CP_IB2_BASE, &ibbase);
+	kgsl_regread(device, REG_CP_IB2_BUFSZ, &ibsize);
+
+	if (ibsize)
+		push_object(device, SNAPSHOT_OBJ_TYPE_IB, ptbase,
+			ibbase, ibsize);
+
+	/*
+	 * Go through the list of found objects and dump each one.  As the IBs
+	 * are parsed, more objects might be found, and objbufptr will increase
+	 */
+	for (i = 0; i < objbufptr; i++)
+		snapshot = dump_object(device, i, snapshot, remain);
+
+	/*
+	 * Only dump the istore on a hang - reading it on a running system
+	 * has a non 0 chance of hanging the GPU
+	 */
+
+	if (hang) {
+		snapshot = kgsl_snapshot_add_section(device,
+			KGSL_SNAPSHOT_SECTION_ISTORE, snapshot, remain,
+			snapshot_istore, NULL);
+	}
+
+	/* Add GPU specific sections - registers mainly, but other stuff too */
+	if (adreno_dev->gpudev->snapshot)
+		snapshot = adreno_dev->gpudev->snapshot(adreno_dev, snapshot,
+			remain, hang);
+
+	return snapshot;
+}
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index e9c3f08..512a262 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -497,8 +497,8 @@
 					struct kgsl_device, display_off);
 	KGSL_PWR_WARN(device, "early suspend start\n");
 	mutex_lock(&device->mutex);
-	kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
 	kgsl_pwrctrl_stop_work(device);
+	kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
 	kgsl_pwrctrl_sleep(device);
 	mutex_unlock(&device->mutex);
 	KGSL_PWR_WARN(device, "early suspend end\n");
@@ -1318,8 +1318,7 @@
 	int sglen = PAGE_ALIGN(size) / PAGE_SIZE;
 	unsigned long paddr = (unsigned long) addr;
 
-	memdesc->sg = kmalloc(sglen * sizeof(struct scatterlist),
-		GFP_KERNEL);
+	memdesc->sg = vmalloc(sglen * sizeof(struct scatterlist));
 	if (memdesc->sg == NULL)
 		return -ENOMEM;
 
@@ -1359,7 +1358,7 @@
 
 err:
 	spin_unlock(&current->mm->page_table_lock);
-	kfree(memdesc->sg);
+	vfree(memdesc->sg);
 	memdesc->sg = NULL;
 
 	return -EINVAL;
@@ -2098,6 +2097,8 @@
 	if (minor == KGSL_DEVICE_MAX)
 		return;
 
+	kgsl_device_snapshot_close(device);
+
 	kgsl_cffdump_close(device->id);
 	kgsl_pwrctrl_uninit_sysfs(device);
 
@@ -2200,6 +2201,9 @@
 
 	idr_init(&device->context_idr);
 
+	/* Initalize the snapshot engine */
+	kgsl_device_snapshot_init(device);
+
 	/* sysfs and debugfs initalization - failure here is non fatal */
 
 	/* Initialize logging */
@@ -2227,6 +2231,7 @@
 int kgsl_device_platform_probe(struct kgsl_device *device,
 			       irqreturn_t (*dev_isr) (int, void*))
 {
+	int result;
 	int status = -EINVAL;
 	struct kgsl_memregion *regspace = NULL;
 	struct resource *res;
@@ -2287,6 +2292,9 @@
 		device->id, regspace->mmio_phys_base,
 		regspace->sizebytes, regspace->mmio_virt_base);
 
+	result = kgsl_drm_init(pdev);
+	if (result)
+		goto error_iounmap;
 
 	status = kgsl_register_device(device);
 	if (!status)
@@ -2422,11 +2430,6 @@
 			goto err;
 	}
 
-	result = kgsl_drm_init(NULL);
-
-	if (result)
-		goto err;
-
 	return 0;
 
 err:
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index f82b038..8ea5279 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.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
@@ -90,6 +90,8 @@
 		struct kgsl_power_stats *stats);
 	void (*irqctrl)(struct kgsl_device *device, int state);
 	unsigned int (*gpuid)(struct kgsl_device *device);
+	void * (*snapshot)(struct kgsl_device *device, void *snapshot,
+		int *remain, int hang);
 	/* Optional functions - these functions are not mandatory.  The
 	   driver will check that the function pointer is not NULL before
 	   calling the hook */
@@ -164,6 +166,15 @@
 	struct idr context_idr;
 	struct early_suspend display_off;
 
+	void *snapshot;		/* Pointer to the snapshot memory region */
+	int snapshot_maxsize;   /* Max size of the snapshot region */
+	int snapshot_size;      /* Current size of the snapshot region */
+	u32 snapshot_timestamp;	/* Timestamp of the last valid snapshot */
+	int snapshot_frozen;	/* 1 if the snapshot output is frozen until
+				   it gets read by the user.  This avoids
+				   losing the output on multiple hangs  */
+	struct kobject snapshot_kobj;
+
 	/* Logging levels */
 	int cmd_log;
 	int ctxt_log;
@@ -320,4 +331,8 @@
 
 const char *kgsl_pwrstate_to_str(unsigned int state);
 
+int kgsl_device_snapshot_init(struct kgsl_device *device);
+int kgsl_device_snapshot(struct kgsl_device *device, int hang);
+void kgsl_device_snapshot_close(struct kgsl_device *device);
+
 #endif  /* __KGSL_DEVICE_H */
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index dba2dfc..e3f6f3b 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,7 +17,6 @@
 #include "drmP.h"
 #include "drm.h"
 #include <linux/android_pmem.h>
-#include <linux/notifier.h>
 
 #include "kgsl.h"
 #include "kgsl_device.h"
@@ -39,6 +38,9 @@
 #define ENTRY_EMPTY -1
 #define ENTRY_NEEDS_CLEANUP -2
 
+#define DRM_KGSL_NOT_INITED -1
+#define DRM_KGSL_INITED   1
+
 #define DRM_KGSL_NUM_FENCE_ENTRIES (DRM_KGSL_HANDLE_WAIT_ENTRIES << 2)
 #define DRM_KGSL_HANDLE_WAIT_ENTRIES 5
 
@@ -127,6 +129,8 @@
 	struct list_head wait_list;
 };
 
+static int kgsl_drm_inited = DRM_KGSL_NOT_INITED;
+
 /* This is a global list of all the memory currently mapped in the MMU */
 static struct list_head kgsl_mem_list;
 
@@ -186,41 +190,6 @@
 	struct kgsl_device_private *devpriv[KGSL_DEVICE_MAX];
 };
 
-static int kgsl_ts_notifier_cb(struct notifier_block *blk,
-			       unsigned long code, void *_param);
-
-static struct notifier_block kgsl_ts_nb[KGSL_DEVICE_MAX];
-
-static int kgsl_drm_firstopen(struct drm_device *dev)
-{
-	int i;
-
-	for (i = 0; i < KGSL_DEVICE_MAX; i++) {
-		struct kgsl_device *device = kgsl_get_device(i);
-
-		if (device == NULL)
-			continue;
-
-		kgsl_ts_nb[i].notifier_call = kgsl_ts_notifier_cb;
-		kgsl_register_ts_notifier(device, &kgsl_ts_nb[i]);
-	}
-
-	return 0;
-}
-
-void kgsl_drm_lastclose(struct drm_device *dev)
-{
-	int i;
-
-	for (i = 0; i < KGSL_DEVICE_MAX; i++) {
-		struct kgsl_device *device = kgsl_get_device(i);
-		if (device == NULL)
-			continue;
-
-		kgsl_unregister_ts_notifier(device, &kgsl_ts_nb[i]);
-	}
-}
-
 void kgsl_drm_preclose(struct drm_device *dev, struct drm_file *file_priv)
 {
 }
@@ -268,74 +237,72 @@
 {
 	struct drm_kgsl_gem_object *priv = obj->driver_private;
 	int index;
+	int result = 0;
 
 	/* Return if the memory is already allocated */
 
 	if (kgsl_gem_memory_allocated(obj) || TYPE_IS_FD(priv->type))
 		return 0;
 
+	if (priv->pagetable == NULL) {
+		priv->pagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
+
+		if (priv->pagetable == NULL) {
+			DRM_ERROR("Unable to get the GPU MMU pagetable\n");
+			return -EINVAL;
+		}
+	}
+
 	if (TYPE_IS_PMEM(priv->type)) {
 		int type;
 
 		if (priv->type == DRM_KGSL_GEM_TYPE_EBI ||
-		    priv->type & DRM_KGSL_GEM_PMEM_EBI)
-			type = PMEM_MEMTYPE_EBI1;
-		else
-			type = PMEM_MEMTYPE_SMI;
-
-		priv->memdesc.physaddr =
-			pmem_kalloc(obj->size * priv->bufcount,
-				    type | PMEM_ALIGNMENT_4K);
-
-		if (IS_ERR((void *) priv->memdesc.physaddr)) {
-			DRM_ERROR("Unable to allocate PMEM memory\n");
-			return -ENOMEM;
+		    priv->type & DRM_KGSL_GEM_PMEM_EBI) {
+				type = PMEM_MEMTYPE_EBI1;
+				result = kgsl_sharedmem_ebimem_user(
+						&priv->memdesc,
+						priv->pagetable,
+						obj->size * priv->bufcount,
+						0);
+				if (result) {
+					DRM_ERROR(
+					"Unable to allocate PMEM memory\n");
+					return result;
+				}
 		}
-
-		priv->memdesc.size = obj->size * priv->bufcount;
+		else
+			return -EINVAL;
 
 	} else if (TYPE_IS_MEM(priv->type)) {
-		priv->memdesc.hostptr =
-			vmalloc_user(obj->size * priv->bufcount);
 
-		if (priv->memdesc.hostptr == NULL) {
-			DRM_ERROR("Unable to allocate vmalloc memory\n");
-			return -ENOMEM;
+		if (priv->type == DRM_KGSL_GEM_TYPE_KMEM ||
+			priv->type & DRM_KGSL_GEM_CACHE_MASK)
+				list_add(&priv->list, &kgsl_mem_list);
+
+		result = kgsl_sharedmem_vmalloc_user(&priv->memdesc,
+					priv->pagetable,
+					obj->size * priv->bufcount, 0);
+
+		if (result != 0) {
+				DRM_ERROR(
+				"Unable to allocate Vmalloc user memory\n");
+				return result;
 		}
-
-		priv->memdesc.size = obj->size * priv->bufcount;
-		priv->memdesc.ops = &kgsl_vmalloc_ops;
 	} else
 		return -EINVAL;
 
-	for (index = 0; index < priv->bufcount; index++)
+	for (index = 0; index < priv->bufcount; index++) {
 		priv->bufs[index].offset = index * obj->size;
-
+		priv->bufs[index].gpuaddr =
+			priv->memdesc.gpuaddr +
+			priv->bufs[index].offset;
+	}
+	priv->flags |= DRM_KGSL_GEM_FLAG_MAPPED;
 
 	return 0;
 }
 
 static void
-kgsl_gem_unmap(struct drm_gem_object *obj)
-{
-	struct drm_kgsl_gem_object *priv = obj->driver_private;
-
-	if (!priv->flags & DRM_KGSL_GEM_FLAG_MAPPED)
-		return;
-
-	kgsl_mmu_unmap(priv->pagetable, &priv->memdesc);
-
-	kgsl_mmu_putpagetable(priv->pagetable);
-	priv->pagetable = NULL;
-
-	if ((priv->type == DRM_KGSL_GEM_TYPE_KMEM) ||
-	    (priv->type & DRM_KGSL_GEM_CACHE_MASK))
-		list_del(&priv->list);
-
-	priv->flags &= ~DRM_KGSL_GEM_FLAG_MAPPED;
-}
-
-static void
 kgsl_gem_free_memory(struct drm_gem_object *obj)
 {
 	struct drm_kgsl_gem_object *priv = obj->driver_private;
@@ -346,12 +313,17 @@
 	kgsl_gem_mem_flush(&priv->memdesc,  priv->type,
 			   DRM_KGSL_GEM_CACHE_OP_FROM_DEV);
 
-	kgsl_gem_unmap(obj);
-
-	if (TYPE_IS_PMEM(priv->type))
-		pmem_kfree(priv->memdesc.physaddr);
-
 	kgsl_sharedmem_free(&priv->memdesc);
+
+	kgsl_mmu_putpagetable(priv->pagetable);
+	priv->pagetable = NULL;
+
+	if ((priv->type == DRM_KGSL_GEM_TYPE_KMEM) ||
+	    (priv->type & DRM_KGSL_GEM_CACHE_MASK))
+		list_del(&priv->list);
+
+	priv->flags &= ~DRM_KGSL_GEM_FLAG_MAPPED;
+
 }
 
 int
@@ -447,7 +419,7 @@
 
 	filp = fget(drm_fd);
 	if (unlikely(filp == NULL)) {
-		DRM_ERROR("Unable to ghet the DRM file descriptor\n");
+		DRM_ERROR("Unable to get the DRM file descriptor\n");
 		return -EINVAL;
 	}
 	file_priv = filp->private_data;
@@ -520,7 +492,7 @@
 
 	ret = drm_gem_handle_create(file_priv, obj, handle);
 
-	drm_gem_object_handle_unreference(obj);
+	drm_gem_object_unreference(obj);
 	INIT_LIST_HEAD(&priv->wait_list);
 
 	for (i = 0; i < DRM_KGSL_HANDLE_WAIT_ENTRIES; i++) {
@@ -695,109 +667,14 @@
 kgsl_gem_unbind_gpu_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv)
 {
-	struct drm_kgsl_gem_bind_gpu *args = data;
-	struct drm_gem_object *obj;
-	struct drm_kgsl_gem_object *priv;
-
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-
-	if (obj == NULL) {
-		DRM_ERROR("Invalid GEM handle %x\n", args->handle);
-		return -EBADF;
-	}
-
-	mutex_lock(&dev->struct_mutex);
-	priv = obj->driver_private;
-
-	if (--priv->bound == 0)
-		kgsl_gem_unmap(obj);
-
-	drm_gem_object_unreference(obj);
-	mutex_unlock(&dev->struct_mutex);
 	return 0;
 }
 
-static int
-kgsl_gem_map(struct drm_gem_object *obj)
-{
-	struct drm_kgsl_gem_object *priv = obj->driver_private;
-	int index;
-	int ret = -EINVAL;
-
-	if (priv->flags & DRM_KGSL_GEM_FLAG_MAPPED)
-		return 0;
-
-	/* Get the global page table */
-
-	if (priv->pagetable == NULL) {
-		priv->pagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
-
-		if (priv->pagetable == NULL) {
-			DRM_ERROR("Unable to get the GPU MMU pagetable\n");
-			return -EINVAL;
-		}
-	}
-
-	priv->memdesc.pagetable = priv->pagetable;
-
-	ret = kgsl_mmu_map(priv->pagetable, &priv->memdesc,
-			   GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
-
-	if (!ret) {
-		for (index = 0; index < priv->bufcount; index++) {
-			priv->bufs[index].gpuaddr =
-				priv->memdesc.gpuaddr +
-				priv->bufs[index].offset;
-		}
-	}
-
-	/* Add cached memory to the list to be cached */
-
-	if (priv->type == DRM_KGSL_GEM_TYPE_KMEM ||
-	    priv->type & DRM_KGSL_GEM_CACHE_MASK)
-		list_add(&priv->list, &kgsl_mem_list);
-
-	priv->flags |= DRM_KGSL_GEM_FLAG_MAPPED;
-
-	return ret;
-}
-
 int
 kgsl_gem_bind_gpu_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv)
 {
-	struct drm_kgsl_gem_bind_gpu *args = data;
-	struct drm_gem_object *obj;
-	struct drm_kgsl_gem_object *priv;
-	int ret = 0;
-
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-
-	if (obj == NULL) {
-		DRM_ERROR("Invalid GEM handle %x\n", args->handle);
-		return -EBADF;
-	}
-
-	mutex_lock(&dev->struct_mutex);
-	priv = obj->driver_private;
-
-	if (priv->bound++ == 0) {
-
-		if (!kgsl_gem_memory_allocated(obj)) {
-			DRM_ERROR("Memory not allocated for this object\n");
-			ret = -ENOMEM;
-			goto out;
-		}
-
-		ret = kgsl_gem_map(obj);
-
-		/* This is legacy behavior - use GET_BUFFERINFO instead */
-		args->gpuptr = priv->bufs[0].gpuaddr;
-	}
-out:
-	drm_gem_object_unreference(obj);
-	mutex_unlock(&dev->struct_mutex);
-	return ret;
+	return 0;
 }
 
 /* Allocate the memory and prepare it for CPU mapping */
@@ -1344,27 +1221,6 @@
 	fence->fence_id = ENTRY_NEEDS_CLEANUP;  /* Mark it as needing cleanup */
 }
 
-static int kgsl_ts_notifier_cb(struct notifier_block *blk,
-			       unsigned long code, void *_param)
-{
-	struct drm_kgsl_gem_object_fence *fence;
-	struct kgsl_device *device = kgsl_get_device(code);
-	int i;
-
-	/* loop through the fences to see what things can be processed */
-
-	for (i = 0; i < DRM_KGSL_NUM_FENCE_ENTRIES; i++) {
-		fence = &gem_buf_fence[i];
-		if (!fence->ts_valid || fence->ts_device != code)
-			continue;
-
-		if (kgsl_check_timestamp(device, fence->timestamp))
-			wakeup_fence_entries(fence);
-	}
-
-	return 0;
-}
-
 int
 kgsl_gem_lock_handle_ioctl(struct drm_device *dev, void *data,
 						   struct drm_file *file_priv)
@@ -1608,11 +1464,9 @@
 };
 
 static struct drm_driver driver = {
-	.driver_features = DRIVER_USE_PLATFORM_DEVICE | DRIVER_GEM,
+	.driver_features = DRIVER_GEM,
 	.load = kgsl_drm_load,
 	.unload = kgsl_drm_unload,
-	.firstopen = kgsl_drm_firstopen,
-	.lastclose = kgsl_drm_lastclose,
 	.preclose = kgsl_drm_preclose,
 	.suspend = kgsl_drm_suspend,
 	.resume = kgsl_drm_resume,
@@ -1643,8 +1497,13 @@
 {
 	int i;
 
+	/* Only initialize once */
+	if (kgsl_drm_inited == DRM_KGSL_INITED)
+		return 0;
+
+	kgsl_drm_inited = DRM_KGSL_INITED;
+
 	driver.num_ioctls = DRM_ARRAY_SIZE(kgsl_drm_ioctls);
-	driver.platform_device = dev;
 
 	INIT_LIST_HEAD(&kgsl_mem_list);
 
@@ -1654,10 +1513,11 @@
 		gem_buf_fence[i].fence_id = ENTRY_EMPTY;
 	}
 
-	return drm_init(&driver);
+	return drm_platform_init(&driver, dev);
 }
 
 void kgsl_drm_exit(void)
 {
-	drm_exit(&driver);
+	kgsl_drm_inited = DRM_KGSL_NOT_INITED;
+	drm_platform_exit(&driver, driver.kdriver.platform_device);
 }
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 6ab9534..1ef71a4 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -621,8 +621,11 @@
 	struct kgsl_device *device = (struct kgsl_device *) data;
 
 	KGSL_PWR_INFO(device, "idle timer expired device %d\n", device->id);
-	if (device->requested_state == KGSL_STATE_NONE) {
-		kgsl_pwrctrl_request_state(device, KGSL_STATE_SLEEP);
+	if (device->requested_state != KGSL_STATE_SUSPEND) {
+		if (device->pwrctrl.restore_slumber)
+			kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
+		else
+			kgsl_pwrctrl_request_state(device, KGSL_STATE_SLEEP);
 		/* Have work run in a non-interrupt context. */
 		queue_work(device->work_queue, &device->idle_check_ws);
 	}
@@ -788,17 +791,10 @@
 	/* Work through the legal state transitions */
 	switch (device->requested_state) {
 	case KGSL_STATE_NAP:
-		if (device->pwrctrl.restore_slumber) {
-			kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
-			break;
-		}
 		status = _nap(device);
 		break;
 	case KGSL_STATE_SLEEP:
-		if (device->pwrctrl.restore_slumber)
-			status = _slumber(device);
-		else
-			status = _sleep(device);
+		status = _sleep(device);
 		break;
 	case KGSL_STATE_SLUMBER:
 		status = _slumber(device);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index ec91b39..7211879 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.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
@@ -421,7 +421,7 @@
 	memdesc->ops = &kgsl_vmalloc_ops;
 	memdesc->hostptr = (void *) ptr;
 
-	memdesc->sg = kmalloc(sglen * sizeof(struct scatterlist), GFP_KERNEL);
+	memdesc->sg = vmalloc(sglen * sizeof(struct scatterlist));
 	if (memdesc->sg == NULL) {
 		ret = -ENOMEM;
 		goto done;
@@ -554,7 +554,7 @@
 	if (memdesc->ops && memdesc->ops->free)
 		memdesc->ops->free(memdesc);
 
-	kfree(memdesc->sg);
+	vfree(memdesc->sg);
 
 	memset(memdesc, 0, sizeof(*memdesc));
 }
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index d345ff3..67a1c2d 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.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
@@ -15,6 +15,7 @@
 
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
 #include "kgsl_mmu.h"
 
 struct kgsl_device;
@@ -81,7 +82,7 @@
 {
 	struct page *page = phys_to_page(physaddr);
 
-	memdesc->sg = kmalloc(sizeof(struct scatterlist) * 1, GFP_KERNEL);
+	memdesc->sg = vmalloc(sizeof(struct scatterlist) * 1);
 	if (memdesc->sg == NULL)
 		return -ENOMEM;
 
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
new file mode 100644
index 0000000..de39ee4
--- /dev/null
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -0,0 +1,500 @@
+/* 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/vmalloc.h>
+#include <linux/time.h>
+#include <linux/sysfs.h>
+#include <linux/utsname.h>
+#include <linux/sched.h>
+#include <linux/idr.h>
+
+#include "kgsl.h"
+#include "kgsl_log.h"
+#include "kgsl_device.h"
+#include "kgsl_sharedmem.h"
+#include "kgsl_snapshot.h"
+
+/* idr_for_each function to count the number of contexts */
+
+static int snapshot_context_count(int id, void *ptr, void *data)
+{
+	int *count = data;
+	*count = *count + 1;
+
+	return 0;
+}
+
+/*
+ * To simplify the iterator loop use a global pointer instead of trying
+ * to pass around double star references to the snapshot data
+ */
+
+static void *_ctxtptr;
+
+static int snapshot_context_info(int id, void *ptr, void *data)
+{
+	struct kgsl_snapshot_linux_context *header = _ctxtptr;
+	struct kgsl_context *context = ptr;
+	struct kgsl_device *device = context->dev_priv->device;
+
+	header->id = id;
+
+	/* Future-proof for per-context timestamps - for now, just
+	 * return the global timestamp for all contexts
+	 */
+
+	header->timestamp_queued = -1;
+	header->timestamp_retired = device->ftbl->readtimestamp(device,
+		KGSL_TIMESTAMP_RETIRED);
+
+	_ctxtptr += sizeof(struct kgsl_snapshot_linux_context);
+
+	return 0;
+}
+
+/* Snapshot the Linux specific information */
+static int snapshot_os(struct kgsl_device *device,
+	void *snapshot, int remain, void *priv)
+{
+	struct kgsl_snapshot_linux *header = snapshot;
+	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+	struct task_struct *task;
+	pid_t pid;
+	int hang = (int) priv;
+	int ctxtcount = 0;
+	int size = sizeof(*header);
+
+	/* Figure out how many active contexts there are - these will
+	 * be appended on the end of the structure */
+
+	idr_for_each(&device->context_idr, snapshot_context_count, &ctxtcount);
+
+	size += ctxtcount * sizeof(struct kgsl_snapshot_linux_context);
+
+	/* Make sure there is enough room for the data */
+	if (remain < size) {
+		SNAPSHOT_ERR_NOMEM(device, "OS");
+		return 0;
+	}
+
+	memset(header, 0, sizeof(*header));
+
+	header->osid = KGSL_SNAPSHOT_OS_LINUX;
+
+	header->state = hang ? SNAPSHOT_STATE_HUNG : SNAPSHOT_STATE_RUNNING;
+
+	/* Get the kernel build information */
+	strlcpy(header->release, utsname()->release, sizeof(header->release));
+	strlcpy(header->version, utsname()->version, sizeof(header->version));
+
+	/* Get the Unix time for the timestamp */
+	header->seconds = get_seconds();
+
+	/* Remember the power information */
+	header->power_flags = pwr->power_flags;
+	header->power_level = pwr->active_pwrlevel;
+	header->power_interval_timeout = pwr->interval_timeout;
+	header->grpclk = kgsl_get_clkrate(pwr->grp_clks[0]);
+	header->busclk = kgsl_get_clkrate(pwr->ebi1_clk);
+
+	/* Future proof for per-context timestamps */
+	header->current_context = -1;
+
+	/* Get the current PT base */
+	header->ptbase = kgsl_mmu_get_current_ptbase(device);
+	/* And the PID for the task leader */
+	pid = header->pid = kgsl_mmu_get_ptname_from_ptbase(header->ptbase);
+
+	task = find_task_by_vpid(pid);
+
+	if (task)
+		get_task_comm(header->comm, task);
+
+	header->ctxtcount = ctxtcount;
+
+	/* append information for each context */
+	_ctxtptr = snapshot + sizeof(*header);
+	idr_for_each(&device->context_idr, snapshot_context_info, NULL);
+
+	/* Return the size of the data segment */
+	return size;
+}
+/*
+ * kgsl_snapshot_dump_indexed_regs - helper function to dump indexed registers
+ * @device - the device to dump registers from
+ * @snapshot - pointer to the start of the region of memory for the snapshot
+ * @remain - a pointer to the number of bytes remaining in the snapshot
+ * @priv - A pointer to the kgsl_snapshot_indexed_registers data
+ *
+ * Given a indexed register cmd/data pair and a count, dump each indexed
+ * register
+ */
+
+static int kgsl_snapshot_dump_indexed_regs(struct kgsl_device *device,
+	void *snapshot, int remain, void *priv)
+{
+	struct kgsl_snapshot_indexed_registers *iregs = priv;
+	struct kgsl_snapshot_indexed_regs *header = snapshot;
+	unsigned int *data = snapshot + sizeof(*header);
+	int i;
+
+	if (remain < (iregs->count * 4) + sizeof(*header)) {
+		SNAPSHOT_ERR_NOMEM(device, "INDEXED REGS");
+		return 0;
+	}
+
+	header->index_reg = iregs->index;
+	header->data_reg = iregs->data;
+	header->count = iregs->count;
+	header->start = iregs->start;
+
+	for (i = 0; i < iregs->count; i++) {
+		kgsl_regwrite(device, iregs->index, iregs->start + i);
+		kgsl_regread(device, iregs->data, &data[i]);
+	}
+
+	return (iregs->count * 4) + sizeof(*header);
+}
+
+/*
+ * kgsl_snapshot_dump_regs - helper function to dump device registers
+ * @device - the device to dump registers from
+ * @snapshot - pointer to the start of the region of memory for the snapshot
+ * @remain - a pointer to the number of bytes remaining in the snapshot
+ * @priv - A pointer to the kgsl_snapshot_registers data
+ *
+ * Given an array of register ranges pairs (start,end [inclusive]), dump the
+ * registers into a snapshot register section.  The snapshot region stores a
+ * part of dwords for each register - the word address of the register, and
+ * the value.
+ */
+int kgsl_snapshot_dump_regs(struct kgsl_device *device, void *snapshot,
+	int remain, void *priv)
+{
+	struct kgsl_snapshot_regs *header = snapshot;
+	struct kgsl_snapshot_registers *regs = priv;
+	unsigned int *data = snapshot + sizeof(*header);
+	int count = 0, i, j;
+
+	/* Figure out how many registers we are going to dump */
+
+	for (i = 0; i < regs->count; i++) {
+		int start = regs->regs[i * 2];
+		int end = regs->regs[i * 2 + 1];
+
+		count += (end - start + 1);
+	}
+
+	if (remain < (count * 8) + sizeof(*header)) {
+		SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
+		return 0;
+	}
+
+	for (i = 0; i < regs->count; i++) {
+		unsigned int start = regs->regs[i * 2];
+		unsigned int end = regs->regs[i * 2 + 1];
+
+		for (j = start; j <= end; j++) {
+			unsigned int val;
+
+			kgsl_regread(device, j, &val);
+			*data++ = j;
+			*data++ = val;
+		}
+	}
+
+	header->count = count;
+
+	/* Return the size of the section */
+	return (count * 8) + sizeof(*header);
+}
+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
+ * @hang - set to 1 if the snapshot was triggered following a hnag
+ * Given a device, construct a binary snapshot dump of the current device state
+ * and store it in the device snapshot memory.
+ */
+int kgsl_device_snapshot(struct kgsl_device *device, int hang)
+{
+	struct kgsl_snapshot_header *header = device->snapshot;
+	int remain = device->snapshot_maxsize - sizeof(*header);
+	void *snapshot;
+
+	/*
+	 * The first hang is always the one we are interested in. To
+	 * avoid a subsequent hang blowing away the first, the snapshot
+	 * is frozen until it is dumped via sysfs.
+	 *
+	 * Note that triggered snapshots are always taken regardless
+	 * of the state and never frozen.
+	 */
+
+	if (hang && device->snapshot_frozen == 1)
+		return 0;
+
+	if (device->snapshot == NULL) {
+		KGSL_DRV_ERR(device,
+			"snapshot: No snapshot memory available\n");
+		return -ENOMEM;
+	}
+
+	if (remain < sizeof(*header)) {
+		KGSL_DRV_ERR(device,
+			"snapshot: Not enough memory for the header\n");
+		return -ENOMEM;
+	}
+
+	header->magic = SNAPSHOT_MAGIC;
+
+	header->gpuid = kgsl_gpuid(device);
+
+	/* Get a pointer to the first section (right after the header) */
+	snapshot = ((void *) device->snapshot) + sizeof(*header);
+
+	/* Build the Linux specific header */
+	snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_OS,
+		snapshot, &remain, snapshot_os, (void *) hang);
+
+	/* Get the device specific sections */
+	if (device->ftbl->snapshot)
+		snapshot = device->ftbl->snapshot(device, snapshot, &remain,
+			hang);
+
+	/* Add the empty end section to let the parser know we are done */
+	snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_END,
+		snapshot, &remain, NULL, NULL);
+
+	device->snapshot_timestamp = get_seconds();
+	device->snapshot_size = (int) (snapshot - device->snapshot);
+
+	/* Freeze the snapshot on a hang until it gets read */
+	device->snapshot_frozen = (hang) ? 1 : 0;
+
+	return 0;
+}
+EXPORT_SYMBOL(kgsl_device_snapshot);
+
+/* An attribute for showing snapshot details */
+struct kgsl_snapshot_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct kgsl_device *device, char *buf);
+	ssize_t (*store)(struct kgsl_device *device, const char *buf,
+		size_t count);
+};
+
+#define to_snapshot_attr(a) \
+container_of(a, struct kgsl_snapshot_attribute, attr)
+
+#define kobj_to_device(a) \
+container_of(a, struct kgsl_device, snapshot_kobj)
+
+/* Dump the sysfs binary data to the user */
+static ssize_t snapshot_show(struct file *filep, struct kobject *kobj,
+	struct bin_attribute *attr, char *buf, loff_t off,
+	size_t count)
+{
+	struct kgsl_device *device = kobj_to_device(kobj);
+
+	if (device == NULL)
+		return 0;
+
+	/* Return nothing if we haven't taken a snapshot yet */
+	if (device->snapshot_timestamp == 0)
+		return 0;
+
+	/* Get the mutex to keep things from changing while we are dumping */
+	mutex_lock(&device->mutex);
+
+	/*
+	 * Release the freeze on the snapshot the first time the buffer is read
+	 */
+
+	device->snapshot_frozen = 0;
+
+	if (off >= device->snapshot_size) {
+		count = 0;
+		goto exit;
+	}
+
+	if (off + count > device->snapshot_size)
+		count = device->snapshot_size - off;
+
+	memcpy(buf, device->snapshot + off, count);
+
+exit:
+	mutex_unlock(&device->mutex);
+	return count;
+}
+
+/* Show the timestamp of the last collected snapshot */
+static ssize_t timestamp_show(struct kgsl_device *device, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%x\n", device->snapshot_timestamp);
+}
+
+/* manually trigger a new snapshot to be collected */
+static ssize_t trigger_store(struct kgsl_device *device, const char *buf,
+	size_t count)
+{
+	if (device && count > 0) {
+		mutex_lock(&device->mutex);
+		kgsl_device_snapshot(device, 0);
+		mutex_unlock(&device->mutex);
+	}
+
+	return count;
+}
+
+static struct bin_attribute snapshot_attr = {
+	.attr.name = "dump",
+	.attr.mode = 0444,
+	.size = 0,
+	.read = snapshot_show
+};
+
+#define SNAPSHOT_ATTR(_name, _mode, _show, _store) \
+struct kgsl_snapshot_attribute attr_##_name = { \
+	.attr = { .name = __stringify(_name), .mode = _mode }, \
+	.show = _show, \
+	.store = _store, \
+}
+
+SNAPSHOT_ATTR(trigger, 0600, NULL, trigger_store);
+SNAPSHOT_ATTR(timestamp, 0444, timestamp_show, NULL);
+
+static void snapshot_sysfs_release(struct kobject *kobj)
+{
+}
+
+static ssize_t snapshot_sysfs_show(struct kobject *kobj,
+	struct attribute *attr, char *buf)
+{
+	struct kgsl_snapshot_attribute *pattr = to_snapshot_attr(attr);
+	struct kgsl_device *device = kobj_to_device(kobj);
+	ssize_t ret;
+
+	if (device && pattr->show)
+		ret = pattr->show(device, buf);
+	else
+		ret = -EIO;
+
+	return ret;
+}
+
+static ssize_t snapshot_sysfs_store(struct kobject *kobj,
+	struct attribute *attr, const char *buf, size_t count)
+{
+	struct kgsl_snapshot_attribute *pattr = to_snapshot_attr(attr);
+	struct kgsl_device *device = kobj_to_device(kobj);
+	ssize_t ret;
+
+	if (device && pattr->store)
+		ret = pattr->store(device, buf, count);
+	else
+		ret = -EIO;
+
+	return ret;
+}
+
+static const struct sysfs_ops snapshot_sysfs_ops = {
+	.show = snapshot_sysfs_show,
+	.store = snapshot_sysfs_store,
+};
+
+static struct kobj_type ktype_snapshot = {
+	.sysfs_ops = &snapshot_sysfs_ops,
+	.default_attrs = NULL,
+	.release = snapshot_sysfs_release,
+};
+
+/* kgsl_device_snapshot_init - Add resources for the device GPU snapshot
+ * @device - The device to initalize
+ *
+ * Allocate memory for a GPU snapshot for the specified device,
+ * and create the sysfs files to manage it
+ */
+
+int kgsl_device_snapshot_init(struct kgsl_device *device)
+{
+	int ret;
+
+	if (device->snapshot == NULL)
+		device->snapshot = vmalloc(KGSL_SNAPSHOT_MEMSIZE);
+
+	if (device->snapshot == NULL)
+		return -ENOMEM;
+
+	device->snapshot_maxsize = KGSL_SNAPSHOT_MEMSIZE;
+	device->snapshot_timestamp = 0;
+
+	ret = kobject_init_and_add(&device->snapshot_kobj, &ktype_snapshot,
+		&device->dev->kobj, "snapshot");
+	if (ret)
+		goto done;
+
+	ret = sysfs_create_bin_file(&device->snapshot_kobj, &snapshot_attr);
+	if (ret)
+		goto done;
+
+	ret  = sysfs_create_file(&device->snapshot_kobj, &attr_trigger.attr);
+	if (ret)
+		goto done;
+
+	ret  = sysfs_create_file(&device->snapshot_kobj, &attr_timestamp.attr);
+
+done:
+	return ret;
+}
+EXPORT_SYMBOL(kgsl_device_snapshot_init);
+
+/* kgsl_device_snapshot_close - Take down snapshot memory for a device
+ * @device - Pointer to the kgsl_device
+ *
+ * Remove the sysfs files and free the memory allocated for the GPU
+ * snapshot
+ */
+
+void kgsl_device_snapshot_close(struct kgsl_device *device)
+{
+	sysfs_remove_bin_file(&device->snapshot_kobj, &snapshot_attr);
+	sysfs_remove_file(&device->snapshot_kobj, &attr_trigger.attr);
+	sysfs_remove_file(&device->snapshot_kobj, &attr_timestamp.attr);
+
+	kobject_put(&device->snapshot_kobj);
+
+	vfree(device->snapshot);
+
+	device->snapshot = NULL;
+	device->snapshot_maxsize = 0;
+	device->snapshot_timestamp = 0;
+}
+EXPORT_SYMBOL(kgsl_device_snapshot_close);
diff --git a/drivers/gpu/msm/kgsl_snapshot.h b/drivers/gpu/msm/kgsl_snapshot.h
new file mode 100644
index 0000000..3b72b0f
--- /dev/null
+++ b/drivers/gpu/msm/kgsl_snapshot.h
@@ -0,0 +1,277 @@
+/* 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 _KGSL_SNAPSHOT_H_
+#define _KGSL_SNAPSHOT_H_
+
+#include <linux/types.h>
+
+/* Snapshot header */
+
+#define SNAPSHOT_MAGIC 0x504D0001
+
+/* GPU ID scheme:
+ * [16:31] - core identifer (0x0002 for 2D or 0x0003 for 3D)
+ * [00:16] - GPU specific identifier
+ */
+
+struct kgsl_snapshot_header {
+	__u32 magic; /* Magic identifier */
+	__u32 gpuid; /* GPU ID - see above */
+} __packed;
+
+/* Section header */
+#define SNAPSHOT_SECTION_MAGIC 0xABCD
+
+struct kgsl_snapshot_section_header {
+	__u16 magic; /* Magic identifier */
+	__u16 id;    /* Type of section */
+	__u32 size;  /* Size of the section including this header */
+} __packed;
+
+/* Section identifiers */
+#define KGSL_SNAPSHOT_SECTION_OS           0x0101
+#define KGSL_SNAPSHOT_SECTION_REGS         0x0201
+#define KGSL_SNAPSHOT_SECTION_RB           0x0301
+#define KGSL_SNAPSHOT_SECTION_IB           0x0401
+#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 */
+#define KGSL_SNAPSHOT_OS_LINUX             0x0001
+
+/* Linux OS specific information */
+
+#define SNAPSHOT_STATE_HUNG 0
+#define SNAPSHOT_STATE_RUNNING 1
+
+struct kgsl_snapshot_linux {
+	int osid;                   /* subsection OS identifier */
+	int state;		    /* 1 if the thread is running, 0 for hung */
+	__u32 seconds;		    /* Unix timestamp for the snapshot */
+	__u32 power_flags;            /* Current power flags */
+	__u32 power_level;            /* Current power level */
+	__u32 power_interval_timeout; /* Power interval timeout */
+	__u32 grpclk;                 /* Current GP clock value */
+	__u32 busclk;		    /* Current busclk value */
+	__u32 ptbase;		    /* Current ptbase */
+	__u32 pid;		    /* PID of the process that owns the PT */
+	__u32 current_context;	    /* ID of the current context */
+	__u32 ctxtcount;	    /* Number of contexts appended to section */
+	unsigned char release[32];  /* kernel release */
+	unsigned char version[32];  /* kernel version */
+	unsigned char comm[16];	    /* Name of the process that owns the PT */
+} __packed;
+
+/*
+ * This structure contains a record of an active context.
+ * These are appended one after another in the OS section below
+ * the header above
+ */
+
+struct kgsl_snapshot_linux_context {
+	__u32 id;			/* The context ID */
+	__u32 timestamp_queued;		/* The last queued timestamp */
+	__u32 timestamp_retired;	/* The last timestamp retired by HW */
+};
+
+/* Ringbuffer sub-section header */
+struct kgsl_snapshot_rb {
+	int start;  /* dword at the start of the dump */
+	int end;    /* dword at the end of the dump */
+	int rbsize; /* Size (in dwords) of the ringbuffer */
+	int wptr;   /* Current index of the CPU write pointer */
+	int rptr;   /* Current index of the GPU read pointer */
+	int count;  /* Number of dwords in the dump */
+} __packed;
+
+/* Indirect buffer sub-section header */
+struct kgsl_snapshot_ib {
+	__u32 gpuaddr; /* GPU address of the the IB */
+	__u32 ptbase;  /* Base for the pagetable the GPU address is valid in */
+	int size;    /* Size of the IB */
+} __packed;
+
+/* Register sub-section header */
+struct kgsl_snapshot_regs {
+	__u32 count; /* Number of register pairs in the section */
+} __packed;
+
+/* Indexed register sub-section header */
+struct kgsl_snapshot_indexed_regs {
+	__u32 index_reg; /* Offset of the index register for this section */
+	__u32 data_reg;  /* Offset of the data register for this section */
+	int start;     /* Starting index */
+	int count;     /* Number of dwords in the data */
+} __packed;
+
+/* Istore sub-section header */
+struct kgsl_snapshot_istore {
+	int count;   /* Number of instructions in the istore */
+} __packed;
+
+/* 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 dwords */
+} __packed;
+
+struct kgsl_snapshot_debugbus {
+	int id;	   /* Debug bus ID */
+	int count; /* Number of dwords in the dump */
+} __packed;
+
+#ifdef __KERNEL__
+
+/* Allocate 512K for each device snapshot */
+#define KGSL_SNAPSHOT_MEMSIZE (512 * 1024)
+
+struct kgsl_device;
+/*
+ * A helper macro to print out "not enough memory functions" - this
+ * makes it easy to standardize the messages as well as cut down on
+ * the number of strings in the binary
+ */
+
+#define SNAPSHOT_ERR_NOMEM(_d, _s) \
+	KGSL_DRV_ERR((_d), \
+	"snapshot: not enough snapshot memory for section %s\n", (_s))
+
+/*
+ * kgsl_snapshot_add_section - Add a new section to the GPU snapshot
+ * @device - the KGSL device being snapshotted
+ * @id - the section id
+ * @snapshot - pointer to the memory for the snapshot
+ * @remain - pointer to the number of bytes left in the snapshot region
+ * @func - Function pointer to fill the section
+ * @priv - Priv pointer to pass to the function
+ *
+ * Set up a KGSL snapshot header by filling the memory with the callback
+ * function and adding the standard section header
+ */
+
+static inline void *kgsl_snapshot_add_section(struct kgsl_device *device,
+	u16 id, void *snapshot, int *remain,
+	int (*func)(struct kgsl_device *, void *, int, void *), void *priv)
+{
+	struct kgsl_snapshot_section_header *header = snapshot;
+	void *data = snapshot + sizeof(*header);
+	int ret = 0;
+
+	/*
+	 * Sanity check to make sure there is enough for the header.  The
+	 * callback will check to make sure there is enough for the rest
+	 * of the data.  If there isn't enough room then don't advance the
+	 * pointer.
+	 */
+
+	if (*remain < sizeof(*header))
+		return snapshot;
+
+	/* It is legal to have no function (i.e. - make an empty section) */
+
+	if (func) {
+		ret = func(device, data, *remain, priv);
+
+		/*
+		 * If there wasn't enough room for the data then don't bother
+		 * setting up the header.
+		 */
+
+		if (ret == 0)
+			return snapshot;
+	}
+
+	header->magic = SNAPSHOT_SECTION_MAGIC;
+	header->id = id;
+	header->size = ret + sizeof(*header);
+
+	/* Decrement the room left in the snapshot region */
+	*remain -= header->size;
+	/* Advance the pointer to the end of the next function */
+	return snapshot + header->size;
+}
+
+/* A common helper function to dump a range of registers.  This will be used in
+ * the GPU specific devices like this:
+ *
+ * struct kgsl_snapshot_registers priv;
+ * priv.regs = registers_array;;
+ * priv.count = num_registers;
+ *
+ * kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, snapshot,
+ *	remain, kgsl_snapshot_dump_regs, &priv).
+ *
+ * Pass in an array of register range pairs in the form of:
+ * start reg, stop reg
+ * All the registers between start and stop inclusive will be dumped
+ */
+
+struct kgsl_snapshot_registers {
+	unsigned int *regs;  /* Pointer to the array of register ranges */
+	int count;	     /* Number of entries in the array */
+};
+
+int kgsl_snapshot_dump_regs(struct kgsl_device *device, void *snapshot,
+	int remain, void *priv);
+
+/*
+ * A common helper function to dump a set of indexed registers. Use it
+ * like this:
+ *
+ * struct kgsl_snapshot_indexed_registers priv;
+ * priv.index = REG_INDEX;
+ * priv.data = REG_DATA;
+ * priv.count = num_registers
+ *
+ * kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_INDEXED_REGS,
+ *	snapshot, remain, kgsl_snapshot_dump_indexed_regs, &priv).
+ *
+ * The callback function will write an index from 0 to priv.count to
+ * the index register and read the data from the data register.
+ */
+
+struct kgsl_snapshot_indexed_registers {
+	unsigned int index; /* Offset of the index register */
+	unsigned int data;  /* Offset of the data register */
+	unsigned int start;	/* Index to start with */
+	unsigned int count; /* Number of values to read from the pair */
+};
+
+/* 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/hwmon/pm8xxx-adc.c b/drivers/hwmon/pm8xxx-adc.c
index 57d34b9..5f8faee 100644
--- a/drivers/hwmon/pm8xxx-adc.c
+++ b/drivers/hwmon/pm8xxx-adc.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
@@ -145,7 +145,7 @@
 	struct wake_lock			adc_wakelock;
 	int					msm_suspend_check;
 	struct pm8xxx_adc_amux_properties	*conv;
-	struct pm8xxx_adc_arb_btm_param		batt[0];
+	struct pm8xxx_adc_arb_btm_param		batt;
 	struct sensor_device_attribute		sens_attr[0];
 };
 
@@ -451,8 +451,8 @@
 
 	spin_lock_irqsave(&adc_pmic->btm_lock, flags);
 	warm_status = irq_read_line(adc_pmic->btm_warm_irq);
-	if (adc_pmic->batt->btm_warm_fn != NULL)
-		adc_pmic->batt->btm_warm_fn(warm_status);
+	if (adc_pmic->batt.btm_warm_fn != NULL)
+		adc_pmic->batt.btm_warm_fn(warm_status);
 	spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
 }
 
@@ -465,8 +465,8 @@
 
 	spin_lock_irqsave(&adc_pmic->btm_lock, flags);
 	cool_status = irq_read_line(adc_pmic->btm_cool_irq);
-	if (adc_pmic->batt->btm_cool_fn != NULL)
-		adc_pmic->batt->btm_cool_fn(cool_status);
+	if (adc_pmic->batt.btm_cool_fn != NULL)
+		adc_pmic->batt.btm_cool_fn(cool_status);
 	spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
 }
 
@@ -860,7 +860,7 @@
 		if (rc < 0)
 			goto write_err;
 
-		adc_pmic->batt->btm_cool_fn = btm_param->btm_cool_fn;
+		adc_pmic->batt.btm_cool_fn = btm_param->btm_cool_fn;
 	}
 
 	if (btm_param->btm_warm_fn != NULL) {
@@ -874,7 +874,7 @@
 		if (rc < 0)
 			goto write_err;
 
-		adc_pmic->batt->btm_warm_fn = btm_param->btm_warm_fn;
+		adc_pmic->batt.btm_warm_fn = btm_param->btm_warm_fn;
 	}
 
 	rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_BTM_CNTRL1, &arb_btm_cntrl1);
@@ -952,10 +952,10 @@
 	if (rc < 0)
 		goto write_err;
 
-	if (pmic_adc->batt->btm_warm_fn != NULL)
+	if (pmic_adc->batt.btm_warm_fn != NULL)
 		enable_irq(adc_pmic->btm_warm_irq);
 
-	if (pmic_adc->batt->btm_cool_fn != NULL)
+	if (pmic_adc->batt.btm_cool_fn != NULL)
 		enable_irq(adc_pmic->btm_cool_irq);
 
 write_err:
@@ -1159,7 +1159,6 @@
 	}
 
 	adc_pmic = devm_kzalloc(&pdev->dev, sizeof(struct pm8xxx_adc) +
-			sizeof(struct pm8xxx_adc_arb_btm_param) +
 			(sizeof(struct sensor_device_attribute) *
 			pdata->adc_num_board_channel), GFP_KERNEL);
 	if (!adc_pmic) {
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 2d69256..9f2e3bd 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -33,6 +33,7 @@
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <linux/gpio.h>
+#include <mach/socinfo.h>
 
 MODULE_LICENSE("GPL v2");
 MODULE_VERSION("0.2");
@@ -303,17 +304,42 @@
 	return 0;
 }
 
+/*
+ * Before calling qup_config_core_on_en(), please make
+ * sure that QuPE core is in RESET state.
+ *
+ * Configuration of CORE_ON_EN - BIT13 in QUP_CONFIG register
+ * is only required for targets like 7x27a, where it needs
+ * be turned on for disabling the QuPE pclks.
+ */
+static void
+qup_config_core_on_en(struct qup_i2c_dev *dev)
+{
+	uint32_t status;
+
+	if (!(cpu_is_msm7x27a() || cpu_is_msm7x27aa() ||
+		 cpu_is_msm7x25a() || cpu_is_msm7x25aa()))
+		return;
+
+	status = readl_relaxed(dev->base + QUP_CONFIG);
+	status |= BIT(13);
+	writel_relaxed(status, dev->base + QUP_CONFIG);
+	/* making sure that write has really gone through */
+	mb();
+}
+
 static void
 qup_i2c_pwr_mgmt(struct qup_i2c_dev *dev, unsigned int state)
 {
 	dev->clk_state = state;
 	if (state != 0) {
-		clk_enable(dev->clk);
-		clk_enable(dev->pclk);
+		clk_prepare_enable(dev->clk);
+		clk_prepare_enable(dev->pclk);
 	} else {
 		qup_update_state(dev, QUP_RESET_STATE);
-		clk_disable(dev->clk);
-		clk_disable(dev->pclk);
+		clk_disable_unprepare(dev->clk);
+		qup_config_core_on_en(dev);
+		clk_disable_unprepare(dev->pclk);
 	}
 }
 
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 2453b6b..d2a8879 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -22,6 +22,8 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include <linux/regulator/consumer.h>
 
 #if defined(CONFIG_HAS_EARLYSUSPEND)
@@ -80,6 +82,7 @@
 #define MXT_PROCI_PALM_T41		41
 #define MXT_PROCI_TOUCHSUPPRESSION_T42	42
 #define MXT_PROCI_STYLUS_T47		47
+#define MXT_PROCI_SHIELDLESS_T56	56
 #define MXT_PROCG_NOISESUPPRESSION_T48	48
 #define MXT_SPT_COMMSCONFIG_T18		18
 #define MXT_SPT_GPIOPWM_T19		19
@@ -206,11 +209,11 @@
 #define MXT_BOOT_VALUE		0xa5
 #define MXT_BACKUP_VALUE	0x55
 #define MXT_BACKUP_TIME		25	/* msec */
-#define MXT224_RESET_TIME		65	/* msec */
-#define MXT224E_RESET_TIME		22	/* msec */
-#define MXT1386_RESET_TIME		250	/* msec */
+#define MXT224_RESET_TIME	65	/* msec */
+#define MXT224E_RESET_TIME	22	/* msec */
+#define MXT1386_RESET_TIME	250	/* msec */
 #define MXT_RESET_TIME		250	/* msec */
-#define MXT_RESET_NOCHGREAD		400	/* msec */
+#define MXT_RESET_NOCHGREAD	400	/* msec */
 
 #define MXT_FWRESET_TIME	175	/* msec */
 
@@ -252,6 +255,9 @@
 #define MXT_MAX_RW_TRIES	3
 #define MXT_BLOCK_SIZE		256
 
+#define MXT_DEBUGFS_DIR		"atmel_mxt_ts"
+#define MXT_DEBUGFS_FILE	"object"
+
 struct mxt_info {
 	u8 family_id;
 	u8 variant_id;
@@ -292,10 +298,13 @@
 	struct i2c_client *client;
 	struct input_dev *input_dev;
 	const struct mxt_platform_data *pdata;
+	const struct mxt_config_info *config_info;
 	struct mxt_object *object_table;
 	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;
@@ -312,8 +321,12 @@
 	u8 t9_min_reportid;
 	u8 t15_max_reportid;
 	u8 t15_min_reportid;
+	u8 curr_cfg_version;
+	int cfg_version_idx;
 };
 
+static struct dentry *debug_base;
+
 static bool mxt_object_readable(unsigned int type)
 {
 	switch (type) {
@@ -334,6 +347,7 @@
 	case MXT_PROCI_PALM_T41:
 	case MXT_PROCI_TOUCHSUPPRESSION_T42:
 	case MXT_PROCI_STYLUS_T47:
+	case MXT_PROCI_SHIELDLESS_T56:
 	case MXT_PROCG_NOISESUPPRESSION_T48:
 	case MXT_SPT_COMMSCONFIG_T18:
 	case MXT_SPT_GPIOPWM_T19:
@@ -366,6 +380,7 @@
 	case MXT_PROCI_PALM_T41:
 	case MXT_PROCI_TOUCHSUPPRESSION_T42:
 	case MXT_PROCI_STYLUS_T47:
+	case MXT_PROCI_SHIELDLESS_T56:
 	case MXT_PROCG_NOISESUPPRESSION_T48:
 	case MXT_SPT_COMMSCONFIG_T18:
 	case MXT_SPT_GPIOPWM_T19:
@@ -654,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];
@@ -750,13 +765,13 @@
 
 static int mxt_check_reg_init(struct mxt_data *data)
 {
-	const struct mxt_platform_data *pdata = data->pdata;
+	const struct mxt_config_info *config_info = data->config_info;
 	struct mxt_object *object;
 	struct device *dev = &data->client->dev;
 	int index = 0;
 	int i, j, config_offset;
 
-	if (!pdata->config) {
+	if (!config_info) {
 		dev_dbg(dev, "No cfg data defined, skipping reg init\n");
 		return 0;
 	}
@@ -769,12 +784,12 @@
 
 		for (j = 0; j < object->size + 1; j++) {
 			config_offset = index + j;
-			if (config_offset > pdata->config_length) {
+			if (config_offset > config_info->config_length) {
 				dev_err(dev, "Not enough config data!\n");
 				return -EINVAL;
 			}
 			mxt_write_object(data, object->type, j,
-					 pdata->config[config_offset]);
+					 config_info->config[config_offset]);
 		}
 		index += object->size + 1;
 	}
@@ -846,6 +861,7 @@
 	u16 reg;
 	u8 reportid = 0;
 	u8 buf[MXT_OBJECT_SIZE];
+	bool found_t38 = false;
 
 	for (i = 0; i < data->info.object_num; i++) {
 		struct mxt_object *object = data->object_table + i;
@@ -866,11 +882,94 @@
 					(object->instances + 1);
 			object->max_reportid = reportid;
 		}
+
+		/* Calculate index for config major version in config array.
+		 * Major version is the first byte in object T38.
+		 */
+		if (object->type == MXT_SPT_USERDATA_T38)
+			found_t38 = true;
+		if (!found_t38 && mxt_object_writable(object->type))
+			data->cfg_version_idx += object->size + 1;
 	}
 
 	return 0;
 }
 
+static int mxt_search_config_array(struct mxt_data *data, bool version_match)
+{
+
+	const struct mxt_platform_data *pdata = data->pdata;
+	const struct mxt_config_info *cfg_info;
+	struct mxt_info *info = &data->info;
+	int i;
+	u8 cfg_version;
+
+	for (i = 0; i < pdata->config_array_size; i++) {
+
+		cfg_info = &pdata->config_array[i];
+
+		if (!cfg_info->config || !cfg_info->config_length)
+			continue;
+
+		if (info->family_id == cfg_info->family_id &&
+			info->variant_id == cfg_info->variant_id &&
+			info->version == cfg_info->version &&
+			info->build == cfg_info->build) {
+
+			cfg_version = cfg_info->config[data->cfg_version_idx];
+			if (data->curr_cfg_version == cfg_version ||
+				!version_match) {
+				data->config_info = cfg_info;
+				return 0;
+			}
+		}
+	}
+
+	dev_info(&data->client->dev,
+		"Config not found: F: %d, V: %d, FW: %d.%d.%d, CFG: %d\n",
+		info->family_id, info->variant_id,
+		info->version >> 4, info->version & 0xF, info->build,
+		data->curr_cfg_version);
+	return -EINVAL;
+}
+
+static int mxt_get_config(struct mxt_data *data)
+{
+	const struct mxt_platform_data *pdata = data->pdata;
+	struct device *dev = &data->client->dev;
+	struct mxt_object *object;
+	int error;
+
+	if (!pdata->config_array || !pdata->config_array_size) {
+		dev_dbg(dev, "No cfg data provided by platform data\n");
+		return 0;
+	}
+
+	/* Get current config version */
+	object = mxt_get_object(data, MXT_SPT_USERDATA_T38);
+	if (!object) {
+		dev_err(dev, "Unable to obtain USERDATA object\n");
+		return -EINVAL;
+	}
+
+	error = mxt_read_reg(data->client, object->start_address,
+				&data->curr_cfg_version);
+	if (error) {
+		dev_err(dev, "Unable to read config version\n");
+		return error;
+	}
+
+	/* It is possible that the config data on the controller is not
+	 * versioned and the version number returns 0. In this case,
+	 * find a match without the config version checking.
+	 */
+	error = mxt_search_config_array(data,
+				data->curr_cfg_version != 0 ? true : false);
+	if (error)
+		return error;
+
+	return 0;
+}
 static void mxt_reset_delay(struct mxt_data *data)
 {
 	struct mxt_info *info = &data->info;
@@ -919,6 +1018,11 @@
 	if (error)
 		goto free_object_table;
 
+	/* Get config data from platform data */
+	error = mxt_get_config(data);
+	if (error)
+		dev_dbg(&client->dev, "Config info not found.\n");
+
 	/* Check register init values */
 	error = mxt_check_reg_init(data);
 	if (error)
@@ -1260,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;
@@ -1267,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);
@@ -1282,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",
@@ -1300,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);
@@ -1321,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);
@@ -1458,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);
@@ -1466,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,
@@ -1476,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,
@@ -1489,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);
@@ -1497,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,
@@ -1507,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);
@@ -1518,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;
 }
@@ -1622,6 +1732,72 @@
 };
 #endif
 
+static int mxt_debugfs_object_show(struct seq_file *m, void *v)
+{
+	struct mxt_data *data = m->private;
+	struct mxt_object *object;
+	struct device *dev = &data->client->dev;
+	int i, j, k;
+	int error;
+	int obj_size;
+	u8 val;
+
+	for (i = 0; i < data->info.object_num; i++) {
+		object = data->object_table + i;
+		obj_size = object->size + 1;
+
+		seq_printf(m, "Object[%d] (Type %d)\n", i + 1, object->type);
+
+		for (j = 0; j < object->instances + 1; j++) {
+			seq_printf(m, "[Instance %d]\n", j);
+
+			for (k = 0; k < obj_size; k++) {
+				error = mxt_read_object(data, object->type,
+							j * obj_size + k, &val);
+				if (error) {
+					dev_err(dev,
+						"Failed to read object %d "
+						"instance %d at offset %d\n",
+						object->type, j, k);
+					return error;
+				}
+
+				seq_printf(m, "Byte %d: 0x%02x (%d)\n",
+						k, val, val);
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int mxt_debugfs_object_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mxt_debugfs_object_show, inode->i_private);
+}
+
+static const struct file_operations mxt_object_fops = {
+	.owner		= THIS_MODULE,
+	.open		= mxt_debugfs_object_open,
+	.read		= seq_read,
+	.release	= single_release,
+};
+
+static void __init mxt_debugfs_init(struct mxt_data *data)
+{
+	debug_base = debugfs_create_dir(MXT_DEBUGFS_DIR, NULL);
+	if (IS_ERR_OR_NULL(debug_base))
+		pr_err("atmel_mxt_ts: Failed to create debugfs dir\n");
+	if (IS_ERR_OR_NULL(debugfs_create_file(MXT_DEBUGFS_FILE,
+					       0444,
+					       debug_base,
+					       data,
+					       &mxt_object_fops))) {
+		pr_err("atmel_mxt_ts: Failed to create object file\n");
+		debugfs_remove_recursive(debug_base);
+	}
+}
+
 static int __devinit mxt_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
@@ -1641,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;
@@ -1674,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++) {
@@ -1773,6 +1959,8 @@
 	register_early_suspend(&data->early_suspend);
 #endif
 
+	mxt_debugfs_init(data);
+
 	return 0;
 
 err_unregister_device:
@@ -1834,6 +2022,8 @@
 	kfree(data->object_table);
 	kfree(data);
 
+	debugfs_remove_recursive(debug_base);
+
 	return 0;
 }
 
diff --git a/drivers/input/touchscreen/cyttsp-i2c.c b/drivers/input/touchscreen/cyttsp-i2c.c
index bb02be6..a60dbf5 100644
--- a/drivers/input/touchscreen/cyttsp-i2c.c
+++ b/drivers/input/touchscreen/cyttsp-i2c.c
@@ -2407,27 +2407,29 @@
 				regulator_put(ts->vdd[i]);
 				goto error_vdd;
 			}
-		}
 
-		rc = regulator_set_optimum_mode(ts->vdd[i],
+			rc = regulator_set_optimum_mode(ts->vdd[i],
 						reg_info[i].hpm_load_uA);
-		if (rc < 0) {
-			pr_err("%s: regulator_set_optimum_mode failed rc=%d\n",
-								__func__, rc);
+			if (rc < 0) {
+				pr_err("%s: regulator_set_optimum_mode failed "
+				       "rc=%d\n", __func__, rc);
 
-			regulator_set_voltage(ts->vdd[i], 0,
-						reg_info[i].max_uV);
-			regulator_put(ts->vdd[i]);
-			goto error_vdd;
+				regulator_set_voltage(ts->vdd[i], 0,
+							reg_info[i].max_uV);
+				regulator_put(ts->vdd[i]);
+				goto error_vdd;
+			}
 		}
 
 		rc = regulator_enable(ts->vdd[i]);
 		if (rc) {
 			pr_err("%s: regulator_enable failed rc =%d\n",
 								__func__, rc);
-			regulator_set_optimum_mode(ts->vdd[i], 0);
-			regulator_set_voltage(ts->vdd[i], 0,
-						reg_info[i].max_uV);
+			if (regulator_count_voltages(ts->vdd[i]) > 0) {
+				regulator_set_optimum_mode(ts->vdd[i], 0);
+				regulator_set_voltage(ts->vdd[i], 0,
+						      reg_info[i].max_uV);
+			}
 			regulator_put(ts->vdd[i]);
 			goto error_vdd;
 		}
@@ -2439,10 +2441,11 @@
 	i = ts->platform_data->num_regulators;
 error_vdd:
 	while (--i >= 0) {
-		if (regulator_count_voltages(ts->vdd[i]) > 0)
+		if (regulator_count_voltages(ts->vdd[i]) > 0) {
 			regulator_set_voltage(ts->vdd[i], 0,
 						reg_info[i].max_uV);
-		regulator_set_optimum_mode(ts->vdd[i], 0);
+			regulator_set_optimum_mode(ts->vdd[i], 0);
+		}
 		regulator_disable(ts->vdd[i]);
 		regulator_put(ts->vdd[i]);
 	}
@@ -2834,6 +2837,8 @@
 		goto regulator_hpm;
 
 	for (i = 0; i < num_reg; i++) {
+		if (regulator_count_voltages(ts->vdd[i]) < 0)
+			continue;
 		rc = regulator_set_optimum_mode(ts->vdd[i],
 					reg_info[i].lpm_load_uA);
 		if (rc < 0) {
@@ -2848,6 +2853,8 @@
 
 regulator_hpm:
 	for (i = 0; i < num_reg; i++) {
+		if (regulator_count_voltages(ts->vdd[i]) < 0)
+			continue;
 		rc = regulator_set_optimum_mode(ts->vdd[i],
 					reg_info[i].hpm_load_uA);
 		if (rc < 0) {
@@ -2860,16 +2867,22 @@
 	return 0;
 
 fail_regulator_lpm:
-	while (i--)
+	while (i--) {
+		if (regulator_count_voltages(ts->vdd[i]) < 0)
+			continue;
 		regulator_set_optimum_mode(ts->vdd[i],
 					reg_info[i].hpm_load_uA);
+	}
 
 	return rc;
 
 fail_regulator_hpm:
-	while (i--)
+	while (i--) {
+		if (regulator_count_voltages(ts->vdd[i]) < 0)
+			continue;
 		regulator_set_optimum_mode(ts->vdd[i],
 					reg_info[i].lpm_load_uA);
+	}
 
 	return rc;
 }
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
index ac76cde..fa6f4d9 100644
--- a/drivers/input/touchscreen/tsc2007.c
+++ b/drivers/input/touchscreen/tsc2007.c
@@ -81,6 +81,10 @@
 	u16			max_rt;
 	unsigned long		poll_delay;
 	unsigned long		poll_period;
+	u16			min_x;
+	u16			max_x;
+	u16			min_y;
+	u16			max_y;
 
 	bool			pendown;
 	int			irq;
@@ -396,6 +400,10 @@
 	ts->invert_y	      = pdata->invert_y;
 	ts->invert_z1	      = pdata->invert_z1;
 	ts->invert_z2	      = pdata->invert_z2;
+	ts->min_x	      = pdata->min_x ? pdata->min_x : 0;
+	ts->max_x	      = pdata->max_x ? pdata->max_x : MAX_12BIT;
+	ts->min_y	      = pdata->min_y ? pdata->min_y : 0;
+	ts->max_y	      = pdata->max_y ? pdata->max_y : MAX_12BIT;
 	ts->power_shutdown    = pdata->power_shutdown;
 
 	snprintf(ts->phys, sizeof(ts->phys),
@@ -408,8 +416,10 @@
 	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, 0, MAX_12BIT, pdata->fuzzx, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, pdata->fuzzy, 0);
+	input_set_abs_params(input_dev, ABS_X, ts->min_x,
+				ts->max_x, pdata->fuzzx, 0);
+	input_set_abs_params(input_dev, ABS_Y, ts->min_y,
+				ts->max_y, pdata->fuzzy, 0);
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT,
 			pdata->fuzzz, 0);
 
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index ff0e00d..545c61c 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -61,7 +61,7 @@
 	__u8 pty;
 	__u8 ps_repeatcount;
 	__u8 prev_trans_rds;
-
+	__u8 af_jump_bit;
 	struct video_device *videodev;
 
 	struct mutex lock;
@@ -98,6 +98,7 @@
 	struct hci_fm_ssbi_req    ssbi_data_accs;
 	struct hci_fm_ssbi_peek   ssbi_peek_reg;
 	struct hci_fm_sig_threshold_rsp sig_th;
+	struct hci_fm_ch_det_threshold ch_det_threshold;
 };
 
 static struct video_device *priv_videodev;
@@ -427,6 +428,38 @@
 	.minimum        =       -128,
 	.maximum        =       127,
 	},
+	{
+	.id     =       V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD,
+	.type   =       V4L2_CTRL_TYPE_INTEGER,
+	.name   =       "Intf High Threshold",
+	.minimum        =       0,
+	.maximum        =       0xFF,
+	.default_value  =       0,
+	},
+	{
+	.id     =       V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD,
+	.type   =       V4L2_CTRL_TYPE_INTEGER,
+	.name   =       "Intf low Threshold",
+	.minimum        =       0,
+	.maximum        =       0xFF,
+	.default_value  =       0,
+	},
+	{
+	.id     =       V4L2_CID_PRIVATE_SINR_THRESHOLD,
+	.type   =       V4L2_CTRL_TYPE_INTEGER,
+	.name   =       "SINR Threshold",
+	.minimum        =       -128,
+	.maximum        =       127,
+	.default_value  =       0,
+	},
+	{
+	.id     =       V4L2_CID_PRIVATE_SINR_SAMPLES,
+	.type   =       V4L2_CTRL_TYPE_INTEGER,
+	.name   =       "SINR samples",
+	.minimum        =       1,
+	.maximum        =       0xFF,
+	.default_value  =       0,
+	},
 };
 
 static void iris_q_event(struct iris_device *radio,
@@ -1046,6 +1079,25 @@
 	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
 }
 
+static int hci_fm_set_ch_det_th(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	struct hci_fm_ch_det_threshold *ch_det_th =
+			 (struct hci_fm_ch_det_threshold *) param;
+	u16 opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_SET_CH_DET_THRESHOLD);
+	return radio_hci_send_cmd(hdev, opcode, sizeof((*ch_det_th)),
+		ch_det_th);
+}
+
+static int hci_fm_get_ch_det_th(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	u16 opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+			HCI_OCF_FM_GET_CH_DET_THRESHOLD);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
 static int radio_hci_err(__u16 code)
 {
 	switch (code) {
@@ -1369,6 +1421,16 @@
 	return ret;
 }
 
+static int hci_set_ch_det_thresholds_req(struct hci_fm_ch_det_threshold *arg,
+		struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_ch_det_threshold *ch_det_threshold = arg;
+	ret = radio_hci_request(hdev, hci_fm_set_ch_det_th,
+		 (unsigned long)ch_det_threshold, RADIO_HCI_TIMEOUT);
+	return ret;
+}
+
 static int hci_fm_set_cal_req_proc(struct radio_hci_dev *hdev,
 		unsigned long param)
 {
@@ -1482,6 +1544,10 @@
 		ret = radio_hci_request(hdev, hci_get_fm_trans_conf_req, arg,
 			msecs_to_jiffies(RADIO_HCI_TIMEOUT));
 		break;
+	case HCI_FM_GET_DET_CH_TH_CMD:
+		ret = radio_hci_request(hdev, hci_fm_get_ch_det_th, arg,
+					msecs_to_jiffies(RADIO_HCI_TIMEOUT));
+		break;
 	default:
 		ret = -EINVAL;
 		break;
@@ -1786,6 +1852,21 @@
 
 	radio_hci_req_complete(hdev, rsp.status);
 }
+
+static void hci_cc_get_ch_det_threshold_rsp(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	u8  status = skb->data[0];
+	if (status) {
+		FMDERR("status = %d", status);
+		return;
+	}
+	memcpy(&radio->ch_det_threshold, &skb->data[1],
+		sizeof(struct hci_fm_ch_det_threshold));
+	radio_hci_req_complete(hdev, status);
+}
+
 static inline void hci_cmd_complete_event(struct radio_hci_dev *hdev,
 		struct sk_buff *skb)
 {
@@ -1818,6 +1899,7 @@
 	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_RDS_GRP_PROCESS):
 	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_EN_WAN_AVD_CTRL):
 	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_EN_NOTCH_CTRL):
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_SET_CH_DET_THRESHOLD):
 	case hci_trans_ctrl_cmd_op_pack(HCI_OCF_FM_ENABLE_TRANS_REQ):
 	case hci_trans_ctrl_cmd_op_pack(HCI_OCF_FM_DISABLE_TRANS_REQ):
 	case hci_trans_ctrl_cmd_op_pack(HCI_OCF_FM_RDS_RT_REQ):
@@ -1886,6 +1968,9 @@
 	case hci_trans_ctrl_cmd_op_pack(HCI_OCF_FM_GET_TRANS_CONF_REQ):
 		hci_cc_fm_trans_get_conf_rsp(hdev, skb);
 		break;
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_GET_CH_DET_THRESHOLD):
+		hci_cc_get_ch_det_threshold_rsp(hdev, skb);
+		break;
 	default:
 		FMDERR("%s opcode 0x%x", hdev->name, opcode);
 		break;
@@ -2227,7 +2312,10 @@
 
 		if (power_mode) {
 			radio->event_mask = 0x00;
-			rds_grps_proc = 0x00 | AF_JUMP_ENABLE ;
+			if (radio->af_jump_bit)
+				rds_grps_proc = 0x00 | AF_JUMP_ENABLE;
+			else
+				rds_grps_proc = 0x00;
 			retval = hci_fm_rds_grps_process(
 				&rds_grps_proc,
 				radio->fm_hdev);
@@ -2522,6 +2610,38 @@
 		} else
 			retval = -EINVAL;
 
+	case V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD:
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Get High det threshold failed %x", retval);
+			return retval;
+		}
+		ctrl->value = radio->ch_det_threshold.high_th;
+		break;
+	case V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD:
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Get Low det threshold failed %x", retval);
+			return retval;
+		}
+		ctrl->value = radio->ch_det_threshold.low_th;
+		break;
+	case V4L2_CID_PRIVATE_SINR_THRESHOLD:
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Get SINR threshold failed %x", retval);
+			return retval;
+		}
+		ctrl->value = radio->ch_det_threshold.sinr;
+		break;
+	case V4L2_CID_PRIVATE_SINR_SAMPLES:
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Get SINR samples failed %x", retval);
+			return retval;
+		}
+
+		ctrl->value = radio->ch_det_threshold.sinr_samples;
 		break;
 	default:
 		retval = -EINVAL;
@@ -2893,6 +3013,10 @@
 				radio->fm_hdev);
 		break;
 	case V4L2_CID_PRIVATE_IRIS_AF_JUMP:
+		/*Clear the current AF jump settings*/
+		radio->g_rds_grp_proc_ps &= ~(1 << RDS_AF_JUMP_OFFSET);
+		radio->af_jump_bit = ctrl->value;
+		rds_grps_proc = 0x00;
 		rds_grps_proc = (ctrl->value << RDS_AF_JUMP_OFFSET);
 		radio->g_rds_grp_proc_ps |= rds_grps_proc;
 		retval = hci_fm_rds_grps_process(
@@ -2905,6 +3029,11 @@
 	case V4L2_CID_PRIVATE_IRIS_ANTENNA:
 		temp_val = ctrl->value;
 		retval = hci_fm_set_antenna(&temp_val, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Set Antenna failed retval = %x", retval);
+			return retval;
+		}
+		radio->g_antenna =  ctrl->value;
 		break;
 	case V4L2_CID_RDS_TX_PTY:
 		radio->pty = ctrl->value;
@@ -2983,6 +3112,66 @@
 		temp_val = ctrl->value;
 		retval = hci_set_notch_filter(&temp_val, radio->fm_hdev);
 		break;
+	case V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD:
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Failed to get chnl det thresholds  %d", retval);
+			return retval;
+		}
+		radio->ch_det_threshold.high_th = ctrl->value;
+		retval = hci_set_ch_det_thresholds_req(&radio->ch_det_threshold,
+							 radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Failed to set High det threshold %d ", retval);
+			return retval;
+		}
+		break;
+
+	case V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD:
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Failed to get chnl det thresholds  %d", retval);
+			return retval;
+		}
+		radio->ch_det_threshold.low_th = ctrl->value;
+		retval = hci_set_ch_det_thresholds_req(&radio->ch_det_threshold,
+							 radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Failed to Set Low det threshold %d", retval);
+			return retval;
+		}
+		break;
+
+	case V4L2_CID_PRIVATE_SINR_THRESHOLD:
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Failed to get chnl det thresholds  %d", retval);
+			return retval;
+		}
+		radio->ch_det_threshold.sinr = ctrl->value;
+		retval = hci_set_ch_det_thresholds_req(&radio->ch_det_threshold,
+							 radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Failed to set SINR threshold %d", retval);
+			return retval;
+		}
+		break;
+
+	case V4L2_CID_PRIVATE_SINR_SAMPLES:
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Failed to get chnl det thresholds  %d", retval);
+			return retval;
+		}
+		radio->ch_det_threshold.sinr_samples = ctrl->value;
+		retval = hci_set_ch_det_thresholds_req(&radio->ch_det_threshold,
+							 radio->fm_hdev);
+	       if (retval < 0) {
+			FMDERR("Failed to set SINR samples  %d", retval);
+			return retval;
+		}
+		break;
+
 	case V4L2_CID_PRIVATE_IRIS_SRCH_ALGORITHM:
 	case V4L2_CID_PRIVATE_IRIS_SET_AUDIO_PATH:
 		/*
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index 8f09b6a..1c4f616 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -3966,6 +3966,9 @@
 		if (i == TAVARUA_BUF_RAW_RDS)
 			kfifo_alloc_rc = kfifo_alloc(&radio->data_buf[i],
 				rds_buf*3, GFP_KERNEL);
+		else if (i == TAVARUA_BUF_RT_RDS)
+			kfifo_alloc_rc = kfifo_alloc(&radio->data_buf[i],
+				STD_BUF_SIZE * 2, GFP_KERNEL);
 		else
 			kfifo_alloc_rc = kfifo_alloc(&radio->data_buf[i],
 				STD_BUF_SIZE, GFP_KERNEL);
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 7d4bbc2..5508c3d 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -226,4 +226,13 @@
 	   To compile this driver as a module, choose M here: the module will
 	   be called rc_loopback.
 
+config IR_GPIO_CIR
+	tristate "GPIO IR remote control"
+	depends on RC_CORE
+	---help---
+	   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 gpio-ir-recv.
+
 endif #RC_CORE
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index 52830e5..523fcd0 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -23,3 +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_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/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile
index b57fc83..45b0134 100644
--- a/drivers/media/rc/keymaps/Makefile
+++ b/drivers/media/rc/keymaps/Makefile
@@ -70,6 +70,7 @@
 			rc-hauppauge.o \
 			rc-rc6-mce.o \
 			rc-real-audio-220-32-keys.o \
+			rc-samsung-necx.o\
 			rc-streamzap.o \
 			rc-tbs-nec.o \
 			rc-technisat-usb2.o \
diff --git a/drivers/media/rc/keymaps/rc-samsung-necx.c b/drivers/media/rc/keymaps/rc-samsung-necx.c
new file mode 100644
index 0000000..e99c057
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-samsung-necx.c
@@ -0,0 +1,80 @@
+/* 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 <media/rc-map.h>
+
+static struct rc_map_table samsung_necx[] = {
+	{ 0x70702, KEY_POWER},		/* power */
+	{ 0x7070f, KEY_MUTE},		/* mute */
+	{ 0x70704, KEY_1},
+	{ 0x70705, KEY_2},
+	{ 0x70706, KEY_3},
+	{ 0x70708, KEY_4},
+	{ 0x70709, KEY_5},
+	{ 0x7070a, KEY_6},
+	{ 0x7070c, KEY_7},
+	{ 0x7070d, KEY_8},
+	{ 0x7070e, KEY_9},
+	{ 0x70711, KEY_0},
+	{ 0x70712, KEY_CHANNELUP},
+	{ 0x70710, KEY_CHANNELDOWN},
+	{ 0x70707, KEY_VOLUMEUP},
+	{ 0x7070b, KEY_VOLUMEDOWN},
+	{ 0x70760, KEY_UP},
+	{ 0x70768, KEY_ENTER},		/* ok */
+	{ 0x70761, KEY_DOWN},
+	{ 0x70765, KEY_LEFT},
+	{ 0x70762, KEY_RIGHT},
+	{ 0x7072d, KEY_EXIT},
+	{ 0x70749, KEY_RECORD},
+	{ 0x70747, KEY_PLAY},
+	{ 0x70746, KEY_STOP},
+	{ 0x70745, KEY_REWIND},
+	{ 0x70748, KEY_FORWARD},
+	{ 0x7074a, KEY_PAUSE},
+	{ 0x70703, KEY_SLEEP},
+	{ 0x7076c, KEY_A},		/* search */
+	{ 0x70714, KEY_B},		/* camera */
+	{ 0x70715, KEY_C},
+	{ 0x70716, KEY_D},
+	{ 0x70758, KEY_BACK},
+	{ 0x7071a, KEY_MENU},
+	{ 0x7076b, KEY_LIST},
+	{ 0x70701, KEY_SCREENLOCK},
+	{ 0x7071f, KEY_HOME},
+
+};
+
+static struct rc_map_list samsung_necx_map = {
+	.map = {
+		.scan    = samsung_necx,
+		.size    = ARRAY_SIZE(samsung_necx),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_SAMSUNG_NECX,
+	}
+};
+
+static int __init init_rc_map_samsung_necx(void)
+{
+	return rc_map_register(&samsung_necx_map);
+}
+
+static void __exit exit_rc_map_samsung_necx(void)
+{
+	rc_map_unregister(&samsung_necx_map);
+}
+
+module_init(init_rc_map_samsung_necx)
+module_exit(exit_rc_map_samsung_necx)
+
+MODULE_DESCRIPTION("SAMSUNG IR Remote Keymap");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index aa0e392..ca44c34 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -62,7 +62,7 @@
 	  Omni Vision VGA YUV Sensor.
 config WEBCAM_OV9726
 	bool "Sensor OV9726 (VGA Bayer)"
-	depends on MSM_CAMERA && (ARCH_MSM8X60 || ARCH_MSM7X30 || ARCH_MSM7X27A) && !MSM_CAMERA_V4L2
+	depends on MSM_CAMERA && (ARCH_MSM8X60 || ARCH_MSM7X30 || ARCH_MSM7X27A)
 	default n
 	---help---
 	  Omni Vision VGA Bayer Sensor.
@@ -113,7 +113,7 @@
 
 config MT9E013
 	bool "Sensor mt9e013 module (BAYER 8M)"
-	depends on MSM_CAMERA && (ARCH_MSM7X30 || ARCH_MSM8X60 || ARCH_MSM7X27A) && !MSM_CAMERA_V4L2
+	depends on MSM_CAMERA && (ARCH_MSM7X30 || ARCH_MSM8X60 || ARCH_MSM7X27A)
 	default n
 	---help---
 	  Aptina 8M Bayer Sensor modules with Autofocus
@@ -149,6 +149,13 @@
 	  two mipi lanes, required for msm7x2xA platform.
 	  Say Y here if this is msm7x2xA variant platform.
 
+config DW9712_ACT
+	bool "Lens actuator dw9721"
+	depends on MSM_CAMERA && S5K4E1
+	---help---
+	  dw9721 lens actuator driver for S5K4E1.
+	  Say Y here if this is msm7627A variant platform.
+
 config MSM_CAMERA_FLASH_SC628A
 	bool "Qualcomm MSM camera sc628a flash support"
 	depends on MSM_CAMERA
@@ -219,3 +226,11 @@
 	  by QUP in the board file as QUP is used by
 	  applications other than camera.
 
+config S5K3L1YX
+	bool "Sensor S5K3L1YX (BAYER 12M)"
+	depends on MSM_CAMERA
+	---help---
+		Samsung 12 MP Bayer Sensor with auto focus, uses
+		4 mipi lanes, preview config = 1984 * 1508 at 30 fps,
+		snapshot config = 4000 * 3000 at 20 fps,
+		hfr video at 60, 90 and 120 fps.
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 5454763..b91449a 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -15,7 +15,11 @@
 obj-$(CONFIG_MSM_CAMERA) += msm_axi_qos.o gemini/
 obj-$(CONFIG_MSM_CAMERA_FLASH) += flash.o
 obj-$(CONFIG_ARCH_MSM_ARM11) += msm_vfe7x.o msm_io7x.o
-obj-$(CONFIG_ARCH_MSM7X27A) += msm_vfe7x27a.o msm_io_7x27a.o
+ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
+  obj-$(CONFIG_ARCH_MSM7X27A) += msm_vfe7x27a_v4l2.o msm_io_7x27a_v4l2.o
+else
+  obj-$(CONFIG_ARCH_MSM7X27A) += msm_vfe7x27a.o msm_io_7x27a.o
+endif
 obj-$(CONFIG_ARCH_MSM7X30) += msm_vfe31.o msm_io_vfe31.o msm_vpe1.o
 obj-$(CONFIG_ARCH_QSD8X50) += msm_vfe8x.o msm_vfe8x_proc.o msm_io8x.o
 obj-$(CONFIG_ARCH_MSM8X60) += msm_vfe31.o msm_io_8x60.o msm_vpe1.o
@@ -26,20 +30,20 @@
 obj-$(CONFIG_MSM_CAMERA_AF_FOXCONN) += mt9p012_fox.o
 obj-$(CONFIG_MSM_CAMERA_AF_BAM) += mt9p012_bam.o
 obj-$(CONFIG_MT9P012_KM) += mt9p012_km.o mt9p012_km_reg.o
-obj-$(CONFIG_MT9E013) += mt9e013.o mt9e013_reg.o
 obj-$(CONFIG_S5K3E2FX) += s5k3e2fx.o
-obj-$(CONFIG_S5K4E1) += s5k4e1.o s5k4e1_reg.o
 #FIXME: Merge the two ifeq causes VX6953 preview not coming up.
 ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
   obj-$(CONFIG_VX6953) += vx6953_v4l2.o vx6953_reg_v4l2.o
 else
   obj-$(CONFIG_VX6953) += vx6953.o vx6953_reg.o
   obj-$(CONFIG_IMX074) += imx074.o imx074_reg.o
+  obj-$(CONFIG_MT9E013) += mt9e013.o mt9e013_reg.o
+  obj-$(CONFIG_WEBCAM_OV9726) += ov9726.o ov9726_reg.o
+  obj-$(CONFIG_S5K4E1) += s5k4e1.o s5k4e1_reg.o
 endif
 obj-$(CONFIG_QS_S5K4E1) += qs_s5k4e1.o qs_s5k4e1_reg.o
 obj-$(CONFIG_VB6801) += vb6801.o
 obj-$(CONFIG_IMX072) += imx072.o imx072_reg.o
-obj-$(CONFIG_WEBCAM_OV9726) += ov9726.o ov9726_reg.o
 obj-$(CONFIG_WEBCAM_OV7692) += ov7692.o
 obj-$(CONFIG_WEBCAM_OV7692_QRD) += ov7692_qrd.o
 obj-$(CONFIG_OV5640) += ov5640.o
diff --git a/drivers/media/video/msm/actuators/Makefile b/drivers/media/video/msm/actuators/Makefile
index 4f4d5ee..f0a0c69 100644
--- a/drivers/media/video/msm/actuators/Makefile
+++ b/drivers/media/video/msm/actuators/Makefile
@@ -3,3 +3,4 @@
 EXTRA_CFLAGS += -Idrivers/media/video/msm/io
 obj-$(CONFIG_MSM_ACTUATOR) += msm_actuator.o
 obj-$(CONFIG_IMX074_ACT) += imx074_act.o
+obj-$(CONFIG_DW9712_ACT) += dw9712_act.o
diff --git a/drivers/media/video/msm/actuators/dw9712_act.c b/drivers/media/video/msm/actuators/dw9712_act.c
new file mode 100644
index 0000000..562290f
--- /dev/null
+++ b/drivers/media/video/msm/actuators/dw9712_act.c
@@ -0,0 +1,277 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_actuator.h"
+#include "msm_camera_i2c.h"
+
+#define	DW9712_TOTAL_STEPS_NEAR_TO_FAR			32
+DEFINE_MUTEX(dw9712_act_mutex);
+static struct msm_actuator_ctrl_t dw9712_act_t;
+
+static struct region_params_t g_regions[] = {
+	/* step_bound[0] - macro side boundary
+	 * step_bound[1] - infinity side boundary
+	 */
+	/* Region 1 */
+	{
+		.step_bound = {DW9712_TOTAL_STEPS_NEAR_TO_FAR, 0},
+		.code_per_step = 2,
+	},
+};
+
+static uint16_t g_scenario[] = {
+	/* MOVE_NEAR and MOVE_FAR dir*/
+	DW9712_TOTAL_STEPS_NEAR_TO_FAR,
+};
+
+static int32_t dw9712_af_i2c_txdata(unsigned short saddr,
+				unsigned char *txdata, int length,
+				struct msm_actuator_ctrl_t *a_ctrl)
+{
+	struct i2c_msg msg[] = {
+		{
+			.addr = saddr,
+			.flags = 0,
+			.len = length,
+			.buf = txdata,
+		},
+	};
+	if (i2c_transfer(a_ctrl->i2c_client.client->adapter, msg, 1) < 0) {
+		pr_err("s5k4e1_af_i2c_txdata faild 0x%x\n", saddr);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int32_t dw9712_af_i2c_write_b_sensor(struct msm_actuator_ctrl_t *a_ctrl,
+			      uint8_t waddr, uint8_t bdata)
+{
+	int32_t rc = -EFAULT;
+	unsigned char buf[2];
+
+	memset(buf, 0, sizeof(buf));
+	buf[0] = waddr;
+	buf[1] = bdata;
+	rc = dw9712_af_i2c_txdata(a_ctrl->i2c_addr, buf, 2, a_ctrl);
+	if (rc < 0) {
+		pr_err("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
+				waddr, bdata);
+	}
+	return rc;
+}
+
+static int32_t dw9712_wrapper_i2c_write(struct msm_actuator_ctrl_t *a_ctrl,
+	int16_t next_lens_position, void *params)
+{
+	uint8_t msb, lsb;
+
+	msb = (next_lens_position & 0xFF00) >> 8;
+	lsb = next_lens_position & 0xFF;
+	dw9712_af_i2c_write_b_sensor(a_ctrl, msb, lsb);
+
+	return 0;
+}
+
+int32_t msm_dw9712_act_move_focus(
+	struct msm_actuator_ctrl_t *a_ctrl,
+	int dir,
+	int32_t num_steps)
+{
+	int32_t rc = 0;
+	int8_t sign_dir = 0;
+	int16_t dest_step_pos = 0;
+	uint8_t code_val_msb, code_val_lsb;
+	uint16_t code_val;
+
+	LINFO("%s called, dir %d, num_steps %d\n",
+		__func__,
+		dir,
+		num_steps);
+
+	/* Determine sign direction */
+	if (dir == MOVE_NEAR)
+		sign_dir = 1;
+	else if (dir == MOVE_FAR)
+		sign_dir = -1;
+	else {
+		pr_err("Illegal focus direction\n");
+		rc = -EINVAL;
+		return rc;
+	}
+
+	/* Determine destination step position */
+	dest_step_pos = a_ctrl->curr_step_pos +
+		(sign_dir * num_steps);
+
+	if (dest_step_pos < 0)
+		dest_step_pos = 0;
+	else if (dest_step_pos > 1023)
+		dest_step_pos = 1023;
+
+	if (dest_step_pos == a_ctrl->curr_step_pos)
+		return rc;
+
+	code_val_msb = dest_step_pos >> 4;
+	code_val_lsb = (dest_step_pos & 0x000F) << 4;
+	code_val = (code_val_msb << 8) | (code_val_lsb);
+	rc = dw9712_wrapper_i2c_write(a_ctrl, code_val, NULL);
+	if (rc >= 0) {
+		rc = 0;
+		a_ctrl->curr_step_pos = dest_step_pos;
+	}
+	return 0;
+}
+
+static int32_t dw9712_set_default_focus(
+	struct msm_actuator_ctrl_t *a_ctrl)
+{
+	int32_t rc = 0;
+
+	if (!a_ctrl->step_position_table)
+		a_ctrl->func_tbl.actuator_init_table(a_ctrl);
+
+	if (a_ctrl->curr_step_pos != 0) {
+		rc = a_ctrl->func_tbl.actuator_move_focus(a_ctrl,
+				MOVE_FAR, a_ctrl->curr_step_pos);
+		a_ctrl->curr_step_pos = 0;
+	} else
+		rc = dw9712_wrapper_i2c_write(a_ctrl, 0x00, NULL);
+		if (rc >= 0)
+			rc = 0;
+	return rc;
+}
+
+static const struct i2c_device_id dw9712_act_i2c_id[] = {
+	{"dw9712_act", (kernel_ulong_t)&dw9712_act_t},
+	{ }
+};
+
+static int dw9712_act_config(void __user *argp)
+{
+	LINFO("%s called\n", __func__);
+	return (int) msm_actuator_config(&dw9712_act_t, argp);
+}
+
+static int dw9712_i2c_add_driver_table(void)
+{
+	LINFO("%s called\n", __func__);
+	return (int) msm_actuator_init_table(&dw9712_act_t);
+}
+
+static struct i2c_driver dw9712_act_i2c_driver = {
+	.id_table = dw9712_act_i2c_id,
+	.probe  = msm_actuator_i2c_probe,
+	.remove = __exit_p(dw9712_act_i2c_remove),
+	.driver = {
+		.name = "dw9712_act",
+	},
+};
+
+static int __init dw9712_i2c_add_driver(void)
+{
+	int rc = 0;
+
+	LINFO("%s called :%x\n", __func__, dw9712_act_t.i2c_addr);
+	rc = i2c_add_driver(dw9712_act_t.i2c_driver);
+	LINFO("%s called:%d %x\n", __func__, rc, dw9712_act_t.i2c_addr);
+	return rc;
+}
+
+static struct v4l2_subdev_core_ops dw9712_act_subdev_core_ops;
+
+static struct v4l2_subdev_ops dw9712_act_subdev_ops = {
+	.core = &dw9712_act_subdev_core_ops,
+};
+
+static int32_t dw9712_act_create_subdevice(
+	void *board_info,
+	void *sdev)
+{
+	int rc = 0;
+
+	struct msm_actuator_info *ptr;
+	LINFO("%s called\n", __func__);
+
+	ptr = board_info;
+	dw9712_act_t.vcm_pwd = ptr->vcm_pwd;
+	dw9712_act_t.vcm_enable = ptr->vcm_enable;
+	LINFO("vcm info: %x %x\n", dw9712_act_t.vcm_pwd,
+				dw9712_act_t.vcm_enable);
+	if (dw9712_act_t.vcm_enable) {
+		rc = gpio_request(dw9712_act_t.vcm_pwd, "dw9712_af");
+		if (!rc) {
+			LINFO("Enable VCM PWD\n");
+			gpio_direction_output(dw9712_act_t.vcm_pwd, 1);
+		}
+	}
+	return (int) msm_actuator_create_subdevice(&dw9712_act_t,
+		ptr->board_info,
+		(struct v4l2_subdev *)sdev);
+}
+
+static struct msm_actuator_ctrl_t dw9712_act_t = {
+	.i2c_driver = &dw9712_act_i2c_driver,
+	.i2c_addr = 0x8C,
+	.act_v4l2_subdev_ops = &dw9712_act_subdev_ops,
+	.actuator_ext_ctrl = {
+		.a_init_table = dw9712_i2c_add_driver_table,
+		.a_create_subdevice = dw9712_act_create_subdevice,
+		.a_config = dw9712_act_config,
+	},
+
+	.i2c_client = {
+		.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+	},
+
+	.set_info = {
+		.total_steps = DW9712_TOTAL_STEPS_NEAR_TO_FAR,
+	},
+
+	.curr_step_pos = 0,
+	.curr_region_index = 0,
+	.initial_code = 0x0,
+	.actuator_mutex = &dw9712_act_mutex,
+
+	.func_tbl = {
+		.actuator_init_table = msm_actuator_init_table,
+		.actuator_move_focus = msm_dw9712_act_move_focus,
+		.actuator_set_default_focus = dw9712_set_default_focus,
+		.actuator_i2c_write = dw9712_wrapper_i2c_write,
+	},
+
+	.get_info = {
+		.focal_length_num = 46,
+		.focal_length_den = 10,
+		.f_number_num = 265,
+		.f_number_den = 100,
+		.f_pix_num = 14,
+		.f_pix_den = 10,
+		.total_f_dist_num = 197681,
+		.total_f_dist_den = 1000,
+	},
+
+	/* Initialize scenario */
+	.ringing_scenario[MOVE_NEAR] = g_scenario,
+	.scenario_size[MOVE_NEAR] = ARRAY_SIZE(g_scenario),
+	.ringing_scenario[MOVE_FAR] = g_scenario,
+	.scenario_size[MOVE_FAR] = ARRAY_SIZE(g_scenario),
+
+	/* Initialize region params */
+	.region_params = g_regions,
+	.region_size = ARRAY_SIZE(g_regions),
+};
+
+subsys_initcall(dw9712_i2c_add_driver);
+MODULE_DESCRIPTION("DW9712 actuator");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/actuators/imx074_act.c b/drivers/media/video/msm/actuators/imx074_act.c
index e01d2c7..e4d340d4 100644
--- a/drivers/media/video/msm/actuators/imx074_act.c
+++ b/drivers/media/video/msm/actuators/imx074_act.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,13 +186,14 @@
 };
 
 static int32_t imx074_act_create_subdevice(
-	void *board_info,
+	void *act_info,
 	void *sdev)
 {
+	struct msm_actuator_info *info = (struct msm_actuator_info *)act_info;
 	LINFO("%s called\n", __func__);
 
 	return (int) msm_actuator_create_subdevice(&imx074_act_t,
-		(struct i2c_board_info const *)board_info,
+		(struct i2c_board_info const *)info->board_info,
 		(struct v4l2_subdev *)sdev);
 }
 
diff --git a/drivers/media/video/msm/actuators/msm_actuator.h b/drivers/media/video/msm/actuators/msm_actuator.h
index 6fad8dd..9c90282 100644
--- a/drivers/media/video/msm/actuators/msm_actuator.h
+++ b/drivers/media/video/msm/actuators/msm_actuator.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
@@ -14,6 +14,7 @@
 
 #include <linux/i2c.h>
 #include <mach/camera.h>
+#include <mach/gpio.h>
 #include <media/v4l2-subdev.h>
 #include <media/msm_camera.h>
 #include "msm_camera_i2c.h"
@@ -100,6 +101,8 @@
 	uint16_t region_size;
 	struct damping_t *damping[2];
 	void *user_data;
+	uint32_t vcm_pwd;
+	uint32_t vcm_enable;
 };
 
 int32_t msm_actuator_i2c_write_b_af(struct msm_actuator_ctrl_t *a_ctrl,
diff --git a/drivers/media/video/msm/csi/Makefile b/drivers/media/video/msm/csi/Makefile
index 3ce81af..6e8eb122 100644
--- a/drivers/media/video/msm/csi/Makefile
+++ b/drivers/media/video/msm/csi/Makefile
@@ -1,3 +1,4 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
 EXTRA_CFLAGS += -Idrivers/media/video/msm
 obj-$(CONFIG_ARCH_MSM8960) += msm_csiphy.o msm_csid.o msm_ispif.o
+obj-$(CONFIG_ARCH_MSM7X27A) += msm_csic.o
diff --git a/drivers/media/video/msm/csi/msm_csic.c b/drivers/media/video/msm/csi/msm_csic.c
new file mode 100644
index 0000000..476615d
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csic.c
@@ -0,0 +1,430 @@
+/* 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 <linux/clk.h>
+#include <linux/io.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include <media/msm_isp.h>
+#include "msm_csic.h"
+#include "msm.h"
+
+#define DBG_CSIC 0
+
+#define V4L2_IDENT_CSIC			50004
+/* MIPI	CSI controller registers */
+#define	MIPI_PHY_CONTROL		0x00000000
+#define	MIPI_PROTOCOL_CONTROL		0x00000004
+#define	MIPI_INTERRUPT_STATUS		0x00000008
+#define	MIPI_INTERRUPT_MASK		0x0000000C
+#define	MIPI_CAMERA_CNTL		0x00000024
+#define	MIPI_CALIBRATION_CONTROL	0x00000018
+#define	MIPI_PHY_D0_CONTROL2		0x00000038
+#define	MIPI_PHY_D1_CONTROL2		0x0000003C
+#define	MIPI_PHY_D2_CONTROL2		0x00000040
+#define	MIPI_PHY_D3_CONTROL2		0x00000044
+#define	MIPI_PHY_CL_CONTROL		0x00000048
+#define	MIPI_PHY_D0_CONTROL		0x00000034
+#define	MIPI_PHY_D1_CONTROL		0x00000020
+#define	MIPI_PHY_D2_CONTROL		0x0000002C
+#define	MIPI_PHY_D3_CONTROL		0x00000030
+#define	MIPI_PWR_CNTL			0x00000054
+
+/*
+ * MIPI_PROTOCOL_CONTROL register bits to enable/disable the features of
+ * CSI Rx Block
+ */
+
+/* DPCM scheme */
+#define	MIPI_PROTOCOL_CONTROL_DPCM_SCHEME_SHFT			0x1e
+/* SW_RST to issue a SW reset to the CSI core */
+#define	MIPI_PROTOCOL_CONTROL_SW_RST_BMSK			0x8000000
+/* To Capture Long packet Header Info in MIPI_PROTOCOL_STATUS register */
+#define	MIPI_PROTOCOL_CONTROL_LONG_PACKET_HEADER_CAPTURE_BMSK	0x200000
+/* Data format for unpacking purpose */
+#define	MIPI_PROTOCOL_CONTROL_DATA_FORMAT_SHFT			0x13
+/* Enable decoding of payload based on data type filed of packet hdr */
+#define	MIPI_PROTOCOL_CONTROL_DECODE_ID_BMSK			0x00000
+/* Enable error correction on packet headers */
+#define	MIPI_PROTOCOL_CONTROL_ECC_EN_BMSK			0x20000
+
+/*
+ * MIPI_CALIBRATION_CONTROL register contains control info for
+ * calibration impledence controller
+*/
+
+/* Enable bit for calibration pad */
+#define	MIPI_CALIBRATION_CONTROL_SWCAL_CAL_EN_SHFT		0x16
+/* With SWCAL_STRENGTH_OVERRIDE_EN, SW_CAL_EN and MANUAL_OVERRIDE_EN
+ * the hardware calibration circuitry associated with CAL_SW_HW_MODE
+ * is bypassed
+*/
+#define	MIPI_CALIBRATION_CONTROL_SWCAL_STRENGTH_OVERRIDE_EN_SHFT	0x15
+/* To indicate the Calibration process is in the control of HW/SW */
+#define	MIPI_CALIBRATION_CONTROL_CAL_SW_HW_MODE_SHFT		0x14
+/* When this is set the strength value of the data and clk lane impedence
+ * termination is updated with MANUAL_STRENGTH settings and calibration
+ * sensing logic is idle.
+*/
+#define	MIPI_CALIBRATION_CONTROL_MANUAL_OVERRIDE_EN_SHFT	0x7
+
+/* Data lane0 control */
+/* T-hs Settle count value  for Rx */
+#define	MIPI_PHY_D0_CONTROL2_SETTLE_COUNT_SHFT			0x18
+/* Rx termination control */
+#define	MIPI_PHY_D0_CONTROL2_HS_TERM_IMP_SHFT			0x10
+/* LP Rx enable */
+#define	MIPI_PHY_D0_CONTROL2_LP_REC_EN_SHFT			0x4
+/*
+ * Enable for error in sync sequence
+ * 1 - one bit error in sync seq
+ * 0 - requires all 8 bit correct seq
+*/
+#define	MIPI_PHY_D0_CONTROL2_ERR_SOT_HS_EN_SHFT			0x3
+
+/* Comments are same as D0 */
+#define	MIPI_PHY_D1_CONTROL2_SETTLE_COUNT_SHFT			0x18
+#define	MIPI_PHY_D1_CONTROL2_HS_TERM_IMP_SHFT			0x10
+#define	MIPI_PHY_D1_CONTROL2_LP_REC_EN_SHFT			0x4
+#define	MIPI_PHY_D1_CONTROL2_ERR_SOT_HS_EN_SHFT			0x3
+
+/* Comments are same as D0 */
+#define	MIPI_PHY_D2_CONTROL2_SETTLE_COUNT_SHFT			0x18
+#define	MIPI_PHY_D2_CONTROL2_HS_TERM_IMP_SHFT			0x10
+#define	MIPI_PHY_D2_CONTROL2_LP_REC_EN_SHFT			0x4
+#define	MIPI_PHY_D2_CONTROL2_ERR_SOT_HS_EN_SHFT			0x3
+
+/* Comments are same as D0 */
+#define	MIPI_PHY_D3_CONTROL2_SETTLE_COUNT_SHFT			0x18
+#define	MIPI_PHY_D3_CONTROL2_HS_TERM_IMP_SHFT			0x10
+#define	MIPI_PHY_D3_CONTROL2_LP_REC_EN_SHFT			0x4
+#define	MIPI_PHY_D3_CONTROL2_ERR_SOT_HS_EN_SHFT			0x3
+
+/* PHY_CL_CTRL programs the parameters of clk lane of CSIRXPHY */
+/* HS Rx termination control */
+#define	MIPI_PHY_CL_CONTROL_HS_TERM_IMP_SHFT			0x18
+/* Start signal for T-hs delay */
+#define	MIPI_PHY_CL_CONTROL_LP_REC_EN_SHFT			0x2
+
+/* PHY DATA lane 0 control */
+/*
+ * HS RX equalizer strength control
+ * 00 - 0db 01 - 3db 10 - 5db 11 - 7db
+*/
+#define	MIPI_PHY_D0_CONTROL_HS_REC_EQ_SHFT			0x1c
+/* PHY DATA lane 1 control */
+/* Shutdown signal for MIPI clk phy line */
+#define	MIPI_PHY_D1_CONTROL_MIPI_CLK_PHY_SHUTDOWNB_SHFT		0x9
+/* Shutdown signal for MIPI data phy line */
+#define	MIPI_PHY_D1_CONTROL_MIPI_DATA_PHY_SHUTDOWNB_SHFT	0x8
+
+#define MSM_AXI_QOS_PREVIEW 200000
+#define MSM_AXI_QOS_SNAPSHOT 200000
+#define MSM_AXI_QOS_RECORDING 200000
+
+#define MIPI_PWR_CNTL_ENA	0x07
+#define MIPI_PWR_CNTL_DIS	0x0
+
+static int msm_csic_config(struct csic_cfg_params *cfg_params)
+{
+	int rc = 0;
+	uint32_t val = 0;
+	struct csic_device *csic_dev;
+	struct msm_camera_csi_params *csic_params;
+	void __iomem *csicbase;
+
+	csic_dev = v4l2_get_subdevdata(cfg_params->subdev);
+	csicbase = csic_dev->base;
+	csic_params = cfg_params->parms;
+
+	/* Enable error correction for DATA lane. Applies to all data lanes */
+	msm_io_w(0x4, csicbase + MIPI_PHY_CONTROL);
+
+	msm_io_w(MIPI_PROTOCOL_CONTROL_SW_RST_BMSK,
+		csicbase + MIPI_PROTOCOL_CONTROL);
+
+	val = MIPI_PROTOCOL_CONTROL_LONG_PACKET_HEADER_CAPTURE_BMSK |
+		MIPI_PROTOCOL_CONTROL_DECODE_ID_BMSK |
+		MIPI_PROTOCOL_CONTROL_ECC_EN_BMSK;
+	val |= (uint32_t)(csic_params->data_format) <<
+		MIPI_PROTOCOL_CONTROL_DATA_FORMAT_SHFT;
+	val |= csic_params->dpcm_scheme <<
+		MIPI_PROTOCOL_CONTROL_DPCM_SCHEME_SHFT;
+	CDBG("%s MIPI_PROTOCOL_CONTROL val=0x%x\n", __func__, val);
+	msm_io_w(val, csicbase + MIPI_PROTOCOL_CONTROL);
+
+	val = (0x1 << MIPI_CALIBRATION_CONTROL_SWCAL_CAL_EN_SHFT) |
+		(0x1 <<
+		MIPI_CALIBRATION_CONTROL_SWCAL_STRENGTH_OVERRIDE_EN_SHFT) |
+		(0x1 << MIPI_CALIBRATION_CONTROL_CAL_SW_HW_MODE_SHFT) |
+		(0x1 << MIPI_CALIBRATION_CONTROL_MANUAL_OVERRIDE_EN_SHFT);
+	CDBG("%s MIPI_CALIBRATION_CONTROL val=0x%x\n", __func__, val);
+	msm_io_w(val, csicbase + MIPI_CALIBRATION_CONTROL);
+
+	val = (csic_params->settle_cnt <<
+		MIPI_PHY_D0_CONTROL2_SETTLE_COUNT_SHFT) |
+		(0x0F << MIPI_PHY_D0_CONTROL2_HS_TERM_IMP_SHFT) |
+		(0x1 << MIPI_PHY_D0_CONTROL2_LP_REC_EN_SHFT) |
+		(0x1 << MIPI_PHY_D0_CONTROL2_ERR_SOT_HS_EN_SHFT);
+	CDBG("%s MIPI_PHY_D0_CONTROL2 val=0x%x\n", __func__, val);
+	msm_io_w(val, csicbase + MIPI_PHY_D0_CONTROL2);
+	msm_io_w(val, csicbase + MIPI_PHY_D1_CONTROL2);
+	msm_io_w(val, csicbase + MIPI_PHY_D2_CONTROL2);
+	msm_io_w(val, csicbase + MIPI_PHY_D3_CONTROL2);
+
+
+	val = (0x0F << MIPI_PHY_CL_CONTROL_HS_TERM_IMP_SHFT) |
+		(0x1 << MIPI_PHY_CL_CONTROL_LP_REC_EN_SHFT);
+	CDBG("%s MIPI_PHY_CL_CONTROL val=0x%x\n", __func__, val);
+	msm_io_w(val, csicbase + MIPI_PHY_CL_CONTROL);
+
+	val = 0 << MIPI_PHY_D0_CONTROL_HS_REC_EQ_SHFT;
+	msm_io_w(val, csicbase + MIPI_PHY_D0_CONTROL);
+
+	val = (0x1 << MIPI_PHY_D1_CONTROL_MIPI_CLK_PHY_SHUTDOWNB_SHFT) |
+		(0x1 << MIPI_PHY_D1_CONTROL_MIPI_DATA_PHY_SHUTDOWNB_SHFT);
+	CDBG("%s MIPI_PHY_D1_CONTROL val=0x%x\n", __func__, val);
+	msm_io_w(val, csicbase + MIPI_PHY_D1_CONTROL);
+
+	msm_io_w(0x00000000, csicbase + MIPI_PHY_D2_CONTROL);
+	msm_io_w(0x00000000, csicbase + MIPI_PHY_D3_CONTROL);
+
+	/* program number of lanes and lane mapping */
+	switch (csic_params->lane_cnt) {
+	case 1:
+		msm_io_w(csic_params->lane_assign << 8 | 0x4,
+			csicbase + MIPI_CAMERA_CNTL);
+		break;
+	case 2:
+		msm_io_w(csic_params->lane_assign << 8 | 0x5,
+			csicbase + MIPI_CAMERA_CNTL);
+		break;
+	case 3:
+		msm_io_w(csic_params->lane_assign << 8 | 0x6,
+			csicbase + MIPI_CAMERA_CNTL);
+		break;
+	case 4:
+		msm_io_w(csic_params->lane_assign << 8 | 0x7,
+			csicbase + MIPI_CAMERA_CNTL);
+		break;
+	}
+
+	msm_io_w(0xFFFFF3FF, csicbase + MIPI_INTERRUPT_MASK);
+	/*clear IRQ bits - write 1 clears the status*/
+	msm_io_w(0xFFFFF3FF, csicbase + MIPI_INTERRUPT_STATUS);
+
+	return rc;
+}
+
+static irqreturn_t msm_csic_irq(int irq_num, void *data)
+{
+	uint32_t irq;
+	struct csic_device *csic_dev = data;
+
+	pr_info("msm_csic_irq: %x\n", (unsigned int)csic_dev->base);
+	irq = msm_io_r(csic_dev->base + MIPI_INTERRUPT_STATUS);
+	pr_info("%s MIPI_INTERRUPT_STATUS = 0x%x\n", __func__, irq);
+	msm_io_w(irq, csic_dev->base + MIPI_INTERRUPT_STATUS);
+
+	/* TODO: Needs to send this info to upper layers */
+	if ((irq >> 19) & 0x1)
+		pr_info("Unsupported packet format is received\n");
+	return IRQ_HANDLED;
+}
+
+static int msm_csic_subdev_g_chip_ident(struct v4l2_subdev *sd,
+			struct v4l2_dbg_chip_ident *chip)
+{
+	BUG_ON(!chip);
+	chip->ident = V4L2_IDENT_CSIC;
+	chip->revision = 0;
+	return 0;
+}
+
+static struct msm_cam_clk_info csic_clk_info[] = {
+	{"csi_clk", 400000000},
+	{"csi_vfe_clk", -1},
+	{"csi_pclk", -1},
+};
+
+static int msm_csic_init(struct v4l2_subdev *sd, uint32_t *csic_version)
+{
+	int rc = 0;
+	struct csic_device *csic_dev;
+	csic_dev = v4l2_get_subdevdata(sd);
+	if (csic_dev == NULL) {
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	csic_dev->base = ioremap(csic_dev->mem->start,
+		resource_size(csic_dev->mem));
+	if (!csic_dev->base) {
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	pr_info("msm_cam_clk_enable: enable csi_pclk, csi_clk, csi_vfe_clk\n");
+	rc = msm_cam_clk_enable(&csic_dev->pdev->dev, csic_clk_info,
+		csic_dev->csic_clk, ARRAY_SIZE(csic_clk_info), 1);
+	if (rc < 0) {
+		iounmap(csic_dev->base);
+		return rc;
+	}
+
+#if DBG_CSIC
+	enable_irq(csic_dev->irq->start);
+#endif
+
+	return 0;
+}
+
+static int msm_csic_release(struct v4l2_subdev *sd)
+{
+	struct csic_device *csic_dev;
+	csic_dev = v4l2_get_subdevdata(sd);
+
+#if DBG_CSIC
+	disable_irq(csic_dev->irq->start);
+#endif
+
+	pr_info("msm_cam_clk_enable: disble csi_pclk, csi_clk, csi_vfe_clk\n");
+	msm_cam_clk_enable(&csic_dev->pdev->dev, csic_clk_info,
+		csic_dev->csic_clk, ARRAY_SIZE(csic_clk_info), 0);
+
+	iounmap(csic_dev->base);
+	return 0;
+}
+
+static long msm_csic_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	struct csic_cfg_params cfg_params;
+	switch (cmd) {
+	case VIDIOC_MSM_CSIC_CFG:
+		cfg_params.subdev = sd;
+		cfg_params.parms = arg;
+		return msm_csic_config((struct csic_cfg_params *)&cfg_params);
+	case VIDIOC_MSM_CSIC_INIT:
+		return msm_csic_init(sd, (uint32_t *)arg);
+	case VIDIOC_MSM_CSIC_RELEASE:
+		return msm_csic_release(sd);
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+static struct v4l2_subdev_core_ops msm_csic_subdev_core_ops = {
+	.g_chip_ident = &msm_csic_subdev_g_chip_ident,
+	.ioctl = &msm_csic_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_csic_subdev_ops = {
+	.core = &msm_csic_subdev_core_ops,
+};
+
+static int __devinit csic_probe(struct platform_device *pdev)
+{
+	struct csic_device *new_csic_dev;
+	int rc = 0;
+	CDBG("%s: device id = %d\n", __func__, pdev->id);
+	new_csic_dev = kzalloc(sizeof(struct csic_device), GFP_KERNEL);
+	if (!new_csic_dev) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	v4l2_subdev_init(&new_csic_dev->subdev, &msm_csic_subdev_ops);
+	v4l2_set_subdevdata(&new_csic_dev->subdev, new_csic_dev);
+	platform_set_drvdata(pdev, &new_csic_dev->subdev);
+	mutex_init(&new_csic_dev->mutex);
+
+	new_csic_dev->mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "csic");
+	if (!new_csic_dev->mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto csic_no_resource;
+	}
+	new_csic_dev->irq = platform_get_resource_byname(pdev,
+					IORESOURCE_IRQ, "csic");
+	if (!new_csic_dev->irq) {
+		pr_err("%s: no irq resource?\n", __func__);
+		rc = -ENODEV;
+		goto csic_no_resource;
+	}
+	new_csic_dev->io = request_mem_region(new_csic_dev->mem->start,
+		resource_size(new_csic_dev->mem), pdev->name);
+	if (!new_csic_dev->io) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto csic_no_resource;
+	}
+
+	rc = request_irq(new_csic_dev->irq->start, msm_csic_irq,
+		IRQF_TRIGGER_RISING, "csic", new_csic_dev);
+	if (rc < 0) {
+		release_mem_region(new_csic_dev->mem->start,
+			resource_size(new_csic_dev->mem));
+		pr_err("%s: irq request fail\n", __func__);
+		rc = -EBUSY;
+		goto csic_no_resource;
+	}
+	disable_irq(new_csic_dev->irq->start);
+	pr_info("msm_cam_clk_enable: enable csi_pclk\n");
+	msm_cam_clk_enable(&pdev->dev, &csic_clk_info[2],
+				new_csic_dev->csic_clk, 1, 1);
+	new_csic_dev->base = ioremap(new_csic_dev->mem->start,
+		resource_size(new_csic_dev->mem));
+	if (!new_csic_dev->base) {
+		rc = -ENOMEM;
+		goto csic_no_resource;
+	}
+
+	msm_io_w(MIPI_PWR_CNTL_DIS, new_csic_dev->base + MIPI_PWR_CNTL_DIS);
+	pr_info("msm_cam_clk_enable: disable csi_pclk\n");
+	msm_cam_clk_enable(&pdev->dev, &csic_clk_info[2],
+					new_csic_dev->csic_clk, 1, 0);
+	iounmap(new_csic_dev->base);
+
+	new_csic_dev->pdev = pdev;
+	return 0;
+
+csic_no_resource:
+	mutex_destroy(&new_csic_dev->mutex);
+	kfree(new_csic_dev);
+	return 0;
+}
+
+static struct platform_driver csic_driver = {
+	.probe = csic_probe,
+	.driver = {
+		.name = MSM_CSIC_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_csic_init_module(void)
+{
+	return platform_driver_register(&csic_driver);
+}
+
+static void __exit msm_csic_exit_module(void)
+{
+	platform_driver_unregister(&csic_driver);
+}
+
+module_init(msm_csic_init_module);
+module_exit(msm_csic_exit_module);
+MODULE_DESCRIPTION("MSM csic driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/csi/msm_csic.h b/drivers/media/video/msm/csi/msm_csic.h
new file mode 100644
index 0000000..08dde52
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csic.h
@@ -0,0 +1,48 @@
+/* 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_CSIC_H
+#define MSM_CSIC_H
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+
+struct csic_device {
+	struct platform_device *pdev;
+	struct v4l2_subdev subdev;
+	struct resource *mem;
+	struct resource *irq;
+	struct resource *io;
+	void __iomem *base;
+	struct mutex mutex;
+	uint32_t hw_version;
+
+	struct clk *csic_clk[5];
+};
+
+struct csic_cfg_params {
+	struct v4l2_subdev *subdev;
+	void *parms;
+};
+
+#define VIDIOC_MSM_CSIC_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct csic_cfg_params)
+
+#define VIDIOC_MSM_CSIC_INIT \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct v4l2_subdev*)
+
+#define VIDIOC_MSM_CSIC_RELEASE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct v4l2_subdev*)
+
+#endif
+
diff --git a/drivers/media/video/msm/io/msm_io_util.c b/drivers/media/video/msm/io/msm_io_util.c
index 9f58d6e..0ae247e 100644
--- a/drivers/media/video/msm/io/msm_io_util.c
+++ b/drivers/media/video/msm/io/msm_io_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,8 +12,11 @@
 
 #include <linux/delay.h>
 #include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
 #include <mach/board.h>
 #include <mach/camera.h>
+#include <mach/gpiomux.h>
 
 int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info,
 		struct clk **clk_ptr, int num_clk, int enable)
@@ -66,3 +69,183 @@
 	return rc;
 }
 
+int msm_camera_config_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
+		int num_vreg, struct regulator **reg_ptr, int config)
+{
+	int i = 0;
+	int rc = 0;
+	struct camera_vreg_t *curr_vreg;
+	if (config) {
+		for (i = 0; i < num_vreg; i++) {
+			curr_vreg = &cam_vreg[i];
+			reg_ptr[i] = regulator_get(dev,
+				curr_vreg->reg_name);
+			if (IS_ERR(reg_ptr[i])) {
+				pr_err("%s: %s get failed\n",
+				 __func__,
+				 curr_vreg->reg_name);
+				reg_ptr[i] = NULL;
+				goto vreg_get_fail;
+			}
+			if (curr_vreg->type == REG_LDO) {
+				rc = regulator_set_voltage(
+				reg_ptr[i],
+				curr_vreg->min_voltage,
+				curr_vreg->max_voltage);
+				if (rc < 0) {
+					pr_err(
+					"%s: %s set voltage failed\n",
+					__func__,
+					curr_vreg->reg_name);
+					goto vreg_set_voltage_fail;
+				}
+				rc = regulator_set_optimum_mode(
+					reg_ptr[i],
+					curr_vreg->op_mode);
+				if (rc < 0) {
+					pr_err(
+					"%s: %s set optimum mode failed\n",
+					__func__,
+					curr_vreg->reg_name);
+					goto vreg_set_opt_mode_fail;
+				}
+			}
+		}
+	} else {
+		for (i = num_vreg-1; i >= 0; i--) {
+			curr_vreg = &cam_vreg[i];
+			if (reg_ptr[i]) {
+				if (curr_vreg->type == REG_LDO) {
+					regulator_set_optimum_mode(
+						reg_ptr[i], 0);
+					regulator_set_voltage(
+						reg_ptr[i],
+						0, curr_vreg->max_voltage);
+				}
+				regulator_put(reg_ptr[i]);
+				reg_ptr[i] = NULL;
+			}
+		}
+	}
+	return 0;
+
+vreg_unconfig:
+if (curr_vreg->type == REG_LDO)
+	regulator_set_optimum_mode(reg_ptr[i], 0);
+
+vreg_set_opt_mode_fail:
+if (curr_vreg->type == REG_LDO)
+	regulator_set_voltage(reg_ptr[i], 0,
+		curr_vreg->max_voltage);
+
+vreg_set_voltage_fail:
+	regulator_put(reg_ptr[i]);
+	reg_ptr[i] = NULL;
+
+vreg_get_fail:
+	for (i--; i >= 0; i--) {
+		curr_vreg = &cam_vreg[i];
+		goto vreg_unconfig;
+	}
+	return -ENODEV;
+}
+
+int msm_camera_enable_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
+		int num_vreg, struct regulator **reg_ptr, int enable)
+{
+	int i = 0, rc = 0;
+	if (enable) {
+		for (i = 0; i < num_vreg; i++) {
+			if (IS_ERR(reg_ptr[i])) {
+				pr_err("%s: %s null regulator\n",
+				__func__, cam_vreg[i].reg_name);
+				goto disable_vreg;
+			}
+			rc = regulator_enable(reg_ptr[i]);
+			if (rc < 0) {
+				pr_err("%s: %s enable failed\n",
+				__func__, cam_vreg[i].reg_name);
+				goto disable_vreg;
+			}
+		}
+	} else {
+		for (i = num_vreg-1; i >= 0; i--)
+			regulator_disable(reg_ptr[i]);
+	}
+	return rc;
+disable_vreg:
+	for (i--; i >= 0; i--) {
+		regulator_disable(reg_ptr[i]);
+		goto disable_vreg;
+	}
+	return rc;
+}
+
+int msm_camera_request_gpio_table(struct msm_camera_sensor_info *sinfo,
+	int gpio_en)
+{
+	int rc = 0;
+	struct msm_camera_gpio_conf *gpio_conf =
+		sinfo->sensor_platform_info->gpio_conf;
+
+	if (gpio_conf->cam_gpio_req_tbl == NULL ||
+		gpio_conf->cam_gpio_common_tbl == NULL) {
+		pr_err("%s: NULL camera gpio table\n", __func__);
+		return -EFAULT;
+	}
+
+	if (gpio_en) {
+		if (gpio_conf->cam_gpiomux_conf_tbl != NULL) {
+			msm_gpiomux_install(
+				(struct msm_gpiomux_config *)gpio_conf->
+				cam_gpiomux_conf_tbl,
+				gpio_conf->cam_gpiomux_conf_tbl_size);
+		}
+		rc = gpio_request_array(gpio_conf->cam_gpio_common_tbl,
+				gpio_conf->cam_gpio_common_tbl_size);
+		if (rc < 0) {
+			pr_err("%s common gpio request failed\n", __func__);
+			return rc;
+		}
+		rc = gpio_request_array(gpio_conf->cam_gpio_req_tbl,
+				gpio_conf->cam_gpio_req_tbl_size);
+		if (rc < 0) {
+			pr_err("%s camera gpio request failed\n", __func__);
+			gpio_free_array(gpio_conf->cam_gpio_common_tbl,
+				gpio_conf->cam_gpio_common_tbl_size);
+			return rc;
+		}
+	} else {
+		gpio_free_array(gpio_conf->cam_gpio_req_tbl,
+				gpio_conf->cam_gpio_req_tbl_size);
+		gpio_free_array(gpio_conf->cam_gpio_common_tbl,
+			gpio_conf->cam_gpio_common_tbl_size);
+	}
+	return rc;
+}
+
+int msm_camera_config_gpio_table(struct msm_camera_sensor_info *sinfo,
+	int gpio_en)
+{
+	struct msm_camera_gpio_conf *gpio_conf =
+		sinfo->sensor_platform_info->gpio_conf;
+	int rc = 0, i;
+
+	if (gpio_en) {
+		for (i = 0; i < gpio_conf->cam_gpio_set_tbl_size; i++) {
+			gpio_set_value_cansleep(
+				gpio_conf->cam_gpio_set_tbl[i].gpio,
+				gpio_conf->cam_gpio_set_tbl[i].flags);
+			usleep_range(gpio_conf->cam_gpio_set_tbl[i].delay,
+				gpio_conf->cam_gpio_set_tbl[i].delay + 1000);
+		}
+	} else {
+		for (i = gpio_conf->cam_gpio_set_tbl_size - 1; i >= 0; i--) {
+			if (gpio_conf->cam_gpio_set_tbl[i].flags)
+				gpio_set_value_cansleep(
+					gpio_conf->cam_gpio_set_tbl[i].gpio,
+					GPIOF_OUT_INIT_LOW);
+		}
+	}
+	return rc;
+}
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 363e437..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;
 }
@@ -1478,15 +1477,14 @@
 				__func__, rc);
 			return rc;
 		}
-		rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
-					pcam->mctl.isp_sdev->sd_vpe);
-		if (rc < 0) {
-			mutex_unlock(&pcam->vid_lock);
-			pr_err("%s: vpe v4l2_device_register_subdev failed rc = %d\n",
-				__func__, rc);
-			return rc;
+		if (pcam->mctl.isp_sdev->sd_vpe) {
+			rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
+						pcam->mctl.isp_sdev->sd_vpe);
+			if (rc < 0) {
+				mutex_unlock(&pcam->vid_lock);
+				return rc;
+			}
 		}
-
 		rc = msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
 							pcam->pvdev);
 		if (rc < 0) {
@@ -1678,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;
 
@@ -1745,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,
@@ -1992,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 +
@@ -2153,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;
@@ -2395,7 +2421,7 @@
 		goto client_fail;
 
 	*actctrl = *a_ext_ctrl;
-	a_ext_ctrl->a_create_subdevice((void *)actuator_info->board_info,
+	a_ext_ctrl->a_create_subdevice((void *)actuator_info,
 				       (void *)act_sdev);
 	return rc;
 
@@ -2477,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);
@@ -2487,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
@@ -2502,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 5fc3e6a..22322b8 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.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
@@ -43,6 +43,7 @@
 
 #define MSM_CSIPHY_DRV_NAME "msm_csiphy"
 #define MSM_CSID_DRV_NAME "msm_csid"
+#define MSM_CSIC_DRV_NAME "msm_csic"
 #define MSM_ISPIF_DRV_NAME "msm_ispif"
 #define MSM_VFE_DRV_NAME "msm_vfe"
 #define MSM_VPE_DRV_NAME "msm_vpe"
@@ -121,6 +122,8 @@
 	NOTIFY_PCLK_CHANGE, /* arg = pclk */
 	NOTIFY_CSIPHY_CFG, /* arg = msm_camera_csiphy_params */
 	NOTIFY_CSID_CFG, /* arg = msm_camera_csid_params */
+	NOTIFY_CSIC_CFG, /* arg = msm_camera_csic_params */
+	NOTIFY_VFE_BUF_FREE_EVT, /* arg = msm_camera_csic_params */
 	NOTIFY_INVALID
 };
 
@@ -225,12 +228,17 @@
 	struct msm_cam_config_dev *config_device;
 	struct v4l2_subdev *csiphy_sdev; /*csiphy sub device*/
 	struct v4l2_subdev *csid_sdev; /*csid sub device*/
+	struct v4l2_subdev *csic_sdev; /*csid sub device*/
 	struct v4l2_subdev *ispif_sdev; /* ispif sub device */
 	struct v4l2_subdev *act_sdev; /* actuator sub device */
 
 	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 */
@@ -286,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 */
@@ -336,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)
@@ -383,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 */
@@ -408,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,
@@ -450,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,
@@ -486,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_camera.c b/drivers/media/video/msm/msm_camera.c
index dbf0eae..e609d6e 100644
--- a/drivers/media/video/msm/msm_camera.c
+++ b/drivers/media/video/msm/msm_camera.c
@@ -3652,6 +3652,7 @@
 			vdata->phy.output_id |= OUTPUT_TYPE_L;
 			sync->liveshot_enabled = false;
 		}
+		vdata->phy.p2_phy = vdata->phy.p0_phy;
 		if (sync->frame_q.len <= 100 && sync->event_q.len <= 100) {
 			CDBG("%s: enqueue to frame_q from VPE\n", __func__);
 			msm_enqueue(&sync->frame_q, &qcmd->list_frame);
diff --git a/drivers/media/video/msm/msm_io_7x27a_v4l2.c b/drivers/media/video/msm/msm_io_7x27a_v4l2.c
new file mode 100644
index 0000000..bee9f49
--- /dev/null
+++ b/drivers/media/video/msm/msm_io_7x27a_v4l2.c
@@ -0,0 +1,258 @@
+/* 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 <linux/clk.h>
+#include <linux/io.h>
+#include <linux/pm_qos_params.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include <mach/camera.h>
+#include <mach/clk.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+
+
+#define MSM_AXI_QOS_PREVIEW 200000
+#define MSM_AXI_QOS_SNAPSHOT 200000
+#define MSM_AXI_QOS_RECORDING 200000
+
+static struct clk *camio_cam_clk;
+static struct resource *clk_ctrl_mem;
+static struct msm_camera_io_clk camio_clk;
+void __iomem *appbase;
+
+void msm_io_w(u32 data, void __iomem *addr)
+{
+	CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
+	writel_relaxed((data), (addr));
+}
+
+u32 msm_io_r(void __iomem *addr)
+{
+	uint32_t data = readl_relaxed(addr);
+	CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
+	return data;
+}
+
+void msm_camio_clk_rate_set_2(struct clk *clk, int rate)
+{
+	clk_set_rate(clk, rate);
+}
+int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
+{
+	int rc = 0;
+	struct clk *clk = NULL;
+
+	switch (clktype) {
+	case CAMIO_CAM_MCLK_CLK:
+		clk = clk_get(NULL, "cam_m_clk");
+		camio_cam_clk = clk;
+		msm_camio_clk_rate_set_2(clk, camio_clk.mclk_clk_rate);
+		break;
+	default:
+		break;
+	}
+
+	if (!IS_ERR(clk))
+		clk_enable(clk);
+	else
+		rc = -1;
+	return rc;
+}
+
+int msm_camio_clk_disable(enum msm_camio_clk_type clktype)
+{
+	int rc = 0;
+	struct clk *clk = NULL;
+
+	switch (clktype) {
+	case CAMIO_CAM_MCLK_CLK:
+		clk = camio_cam_clk;
+		break;
+	default:
+		break;
+	}
+
+	if (!IS_ERR(clk)) {
+		clk_disable(clk);
+		clk_put(clk);
+	} else
+		rc = -1;
+	return rc;
+}
+
+void msm_camio_clk_rate_set(int rate)
+{
+	struct clk *clk = camio_cam_clk;
+	clk_set_rate(clk, rate);
+}
+
+int msm_sensor_probe_on(struct device *dev)
+{
+	int rc = 0;
+	struct msm_camera_sensor_info *sinfo = dev->platform_data;
+	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+	camio_clk = camdev->ioclk;
+
+	rc = camdev->camera_gpio_on();
+	if (rc < 0)
+		return rc;
+
+	rc = msm_camio_clk_enable(CAMIO_CAM_MCLK_CLK);
+	if (rc < 0)
+		camdev->camera_gpio_off();
+
+	return rc;
+}
+
+int msm_sensor_probe_off(struct device *dev)
+{
+	struct msm_camera_sensor_info *sinfo = dev->platform_data;
+	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+
+	camdev->camera_gpio_off();
+	return msm_camio_clk_disable(CAMIO_CAM_MCLK_CLK);
+}
+
+void msm_camio_vfe_blk_reset(void)
+{
+	uint32_t val;
+
+	/* do apps reset */
+	val = readl_relaxed(appbase + 0x00000210);
+	val |= 0x1;
+	writel_relaxed(val, appbase + 0x00000210);
+	usleep_range(10000, 11000);
+
+	val = readl_relaxed(appbase + 0x00000210);
+	val &= ~0x1;
+	writel_relaxed(val, appbase + 0x00000210);
+	usleep_range(10000, 11000);
+
+	/* do axi reset */
+	val = readl_relaxed(appbase + 0x00000208);
+	val |= 0x1;
+	writel_relaxed(val, appbase + 0x00000208);
+	usleep_range(10000, 11000);
+
+	val = readl_relaxed(appbase + 0x00000208);
+	val &= ~0x1;
+	writel_relaxed(val, appbase + 0x00000208);
+	mb();
+	usleep_range(10000, 11000);
+}
+
+int msm_camio_probe_on(struct platform_device *pdev)
+{
+	int rc = 0;
+	const struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
+	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+	camio_clk = camdev->ioclk;
+
+	rc = camdev->camera_gpio_on();
+	if (rc < 0)
+		return rc;
+	return msm_camio_clk_enable(CAMIO_CAM_MCLK_CLK);
+}
+
+int msm_camio_probe_off(struct platform_device *pdev)
+{
+	const struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
+	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+
+	camdev->camera_gpio_off();
+	return msm_camio_clk_disable(CAMIO_CAM_MCLK_CLK);
+}
+
+void msm_camio_set_perf_lvl(enum msm_bus_perf_setting perf_setting)
+{
+	switch (perf_setting) {
+	case S_INIT:
+		add_axi_qos();
+		break;
+	case S_PREVIEW:
+		update_axi_qos(MSM_AXI_QOS_PREVIEW);
+		break;
+	case S_VIDEO:
+		update_axi_qos(MSM_AXI_QOS_RECORDING);
+		break;
+	case S_CAPTURE:
+		update_axi_qos(MSM_AXI_QOS_SNAPSHOT);
+		break;
+	case S_DEFAULT:
+		update_axi_qos(PM_QOS_DEFAULT_VALUE);
+		break;
+	case S_EXIT:
+		release_axi_qos();
+		break;
+	default:
+		CDBG("%s: INVALID CASE\n", __func__);
+	}
+}
+
+static int __devinit clkctl_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+
+	clk_ctrl_mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "clk_ctl");
+	if (!clk_ctrl_mem) {
+		pr_err("%s: no mem resource:3?\n", __func__);
+		return -ENODEV;
+	}
+
+	appbase = ioremap(clk_ctrl_mem->start,
+		resource_size(clk_ctrl_mem));
+	if (!appbase) {
+		pr_err("clkctl_probe: appbase:err\n");
+		rc = -ENOMEM;
+		goto ioremap_fail;
+	}
+	return 0;
+
+ioremap_fail:
+	msm_camio_clk_disable(CAMIO_CAM_MCLK_CLK);
+	return rc;
+}
+
+static int clkctl_remove(struct platform_device *pdev)
+{
+	if (clk_ctrl_mem)
+		iounmap(clk_ctrl_mem);
+
+	return 0;
+}
+
+static struct platform_driver clkctl_driver = {
+	.probe  = clkctl_probe,
+	.remove = clkctl_remove,
+	.driver = {
+		.name = "msm_clk_ctl",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_clkctl_init_module(void)
+{
+	return platform_driver_register(&clkctl_driver);
+}
+
+static void __exit msm_clkctl_exit_module(void)
+{
+	platform_driver_unregister(&clkctl_driver);
+}
+
+module_init(msm_clkctl_init_module);
+module_exit(msm_clkctl_exit_module);
+MODULE_DESCRIPTION("CAM IO driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_io_8960.c b/drivers/media/video/msm/msm_io_8960.c
index 3168bb6..79294a3 100644
--- a/drivers/media/video/msm/msm_io_8960.c
+++ b/drivers/media/video/msm/msm_io_8960.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
@@ -27,38 +27,14 @@
 
 #define BUFF_SIZE_128 128
 
-#define CAM_VAF_MINUV                 2800000
-#define CAM_VAF_MAXUV                 2800000
-#define CAM_VDIG_MINUV                    1200000
-#define CAM_VDIG_MAXUV                    1200000
-#define CAM_VANA_MINUV                    2800000
-#define CAM_VANA_MAXUV                    2850000
-#define CAM_CSI_VDD_MINUV                  1200000
-#define CAM_CSI_VDD_MAXUV                  1200000
-
-#define CAM_VAF_LOAD_UA               300000
-#define CAM_VDIG_LOAD_UA                  105000
-#define CAM_VANA_LOAD_UA                  85600
-#define CAM_CSI_LOAD_UA                    20000
-
-static struct clk *camio_cam_clk;
-
 static struct clk *camio_jpeg_clk;
 static struct clk *camio_jpeg_pclk;
 static struct regulator *fs_ijpeg;
-static struct regulator *cam_vana;
-static struct regulator *cam_vio;
-static struct regulator *cam_vdig;
-static struct regulator *cam_vaf;
-static struct regulator *mipi_csi_vdd;
 
-static struct msm_camera_io_clk camio_clk;
 static struct platform_device *camio_dev;
 static struct resource *s3drw_io, *s3dctl_io;
 static struct resource *s3drw_mem, *s3dctl_mem;
 void __iomem *s3d_rw, *s3d_ctl;
-struct msm_bus_scale_pdata *cam_bus_scale_table;
-
 
 void msm_io_w(u32 data, void __iomem *addr)
 {
@@ -136,213 +112,12 @@
 	msm_io_dump(dest_addr, len);
 }
 
-static int msm_camera_vreg_enable(struct device *dev)
-{
-	if (mipi_csi_vdd == NULL) {
-		mipi_csi_vdd = regulator_get(dev, "mipi_csi_vdd");
-		if (IS_ERR(mipi_csi_vdd)) {
-			CDBG("%s: VREG MIPI CSI VDD get failed\n", __func__);
-			mipi_csi_vdd = NULL;
-			return -ENODEV;
-		}
-		if (regulator_set_voltage(mipi_csi_vdd, CAM_CSI_VDD_MINUV,
-			CAM_CSI_VDD_MAXUV)) {
-			CDBG("%s: VREG MIPI CSI VDD set voltage failed\n",
-				__func__);
-			goto mipi_csi_vdd_put;
-		}
-		if (regulator_set_optimum_mode(mipi_csi_vdd,
-			CAM_CSI_LOAD_UA) < 0) {
-			CDBG("%s: VREG MIPI CSI set optimum mode failed\n",
-				__func__);
-			goto mipi_csi_vdd_release;
-		}
-		if (regulator_enable(mipi_csi_vdd)) {
-			CDBG("%s: VREG MIPI CSI VDD enable failed\n",
-				__func__);
-			goto mipi_csi_vdd_disable;
-		}
-	}
-	if (cam_vana == NULL) {
-		cam_vana = regulator_get(dev, "cam_vana");
-		if (IS_ERR(cam_vana)) {
-			CDBG("%s: VREG CAM VANA get failed\n", __func__);
-			cam_vana = NULL;
-			goto mipi_csi_vdd_disable;
-		}
-		if (regulator_set_voltage(cam_vana, CAM_VANA_MINUV,
-			CAM_VANA_MAXUV)) {
-			CDBG("%s: VREG CAM VANA set voltage failed\n",
-				__func__);
-			goto cam_vana_put;
-		}
-		if (regulator_set_optimum_mode(cam_vana,
-			CAM_VANA_LOAD_UA) < 0) {
-			CDBG("%s: VREG CAM VANA set optimum mode failed\n",
-				__func__);
-			goto cam_vana_release;
-		}
-		if (regulator_enable(cam_vana)) {
-			CDBG("%s: VREG CAM VANA enable failed\n", __func__);
-			goto cam_vana_disable;
-		}
-	}
-	if (cam_vio == NULL) {
-		cam_vio = regulator_get(dev, "cam_vio");
-		if (IS_ERR(cam_vio)) {
-			CDBG("%s: VREG VIO get failed\n", __func__);
-			cam_vio = NULL;
-			goto cam_vana_disable;
-		}
-		if (regulator_enable(cam_vio)) {
-			CDBG("%s: VREG VIO enable failed\n", __func__);
-			goto cam_vio_put;
-		}
-	}
-	if (cam_vdig == NULL) {
-		cam_vdig = regulator_get(dev, "cam_vdig");
-		if (IS_ERR(cam_vdig)) {
-			CDBG("%s: VREG CAM VDIG get failed\n", __func__);
-			cam_vdig = NULL;
-			goto cam_vio_disable;
-		}
-		if (regulator_set_voltage(cam_vdig, CAM_VDIG_MINUV,
-			CAM_VDIG_MAXUV)) {
-			CDBG("%s: VREG CAM VDIG set voltage failed\n",
-				__func__);
-			goto cam_vdig_put;
-		}
-		if (regulator_set_optimum_mode(cam_vdig,
-			CAM_VDIG_LOAD_UA) < 0) {
-			CDBG("%s: VREG CAM VDIG set optimum mode failed\n",
-				__func__);
-			goto cam_vdig_release;
-		}
-		if (regulator_enable(cam_vdig)) {
-			CDBG("%s: VREG CAM VDIG enable failed\n", __func__);
-			goto cam_vdig_disable;
-		}
-	}
-	if (cam_vaf == NULL) {
-		cam_vaf = regulator_get(dev, "cam_vaf");
-		if (IS_ERR(cam_vaf)) {
-			CDBG("%s: VREG CAM VAF get failed\n", __func__);
-			cam_vaf = NULL;
-			goto cam_vdig_disable;
-		}
-		if (regulator_set_voltage(cam_vaf, CAM_VAF_MINUV,
-			CAM_VAF_MAXUV)) {
-			CDBG("%s: VREG CAM VAF set voltage failed\n",
-				__func__);
-			goto cam_vaf_put;
-		}
-		if (regulator_set_optimum_mode(cam_vaf,
-			CAM_VAF_LOAD_UA) < 0) {
-			CDBG("%s: VREG CAM VAF set optimum mode failed\n",
-				__func__);
-			goto cam_vaf_release;
-		}
-		if (regulator_enable(cam_vaf)) {
-			CDBG("%s: VREG CAM VAF enable failed\n", __func__);
-			goto cam_vaf_disable;
-		}
-	}
-	return 0;
-
-cam_vaf_disable:
-	regulator_set_optimum_mode(cam_vaf, 0);
-cam_vaf_release:
-	regulator_set_voltage(cam_vaf, 0, CAM_VAF_MAXUV);
-	regulator_disable(cam_vaf);
-cam_vaf_put:
-	regulator_put(cam_vaf);
-	cam_vaf = NULL;
-cam_vdig_disable:
-	regulator_set_optimum_mode(cam_vdig, 0);
-cam_vdig_release:
-	regulator_set_voltage(cam_vdig, 0, CAM_VDIG_MAXUV);
-	regulator_disable(cam_vdig);
-cam_vdig_put:
-	regulator_put(cam_vdig);
-	cam_vdig = NULL;
-cam_vio_disable:
-	regulator_disable(cam_vio);
-cam_vio_put:
-	regulator_put(cam_vio);
-	cam_vio = NULL;
-cam_vana_disable:
-	regulator_set_optimum_mode(cam_vana, 0);
-cam_vana_release:
-	regulator_set_voltage(cam_vana, 0, CAM_VANA_MAXUV);
-	regulator_disable(cam_vana);
-cam_vana_put:
-	regulator_put(cam_vana);
-	cam_vana = NULL;
-mipi_csi_vdd_disable:
-	regulator_set_optimum_mode(mipi_csi_vdd, 0);
-mipi_csi_vdd_release:
-	regulator_set_voltage(mipi_csi_vdd, 0, CAM_CSI_VDD_MAXUV);
-	regulator_disable(mipi_csi_vdd);
-
-mipi_csi_vdd_put:
-	regulator_put(mipi_csi_vdd);
-	mipi_csi_vdd = NULL;
-	return -ENODEV;
-}
-
-static void msm_camera_vreg_disable(void)
-{
-	if (mipi_csi_vdd) {
-		regulator_set_voltage(mipi_csi_vdd, 0, CAM_CSI_VDD_MAXUV);
-		regulator_set_optimum_mode(mipi_csi_vdd, 0);
-		regulator_disable(mipi_csi_vdd);
-		regulator_put(mipi_csi_vdd);
-		mipi_csi_vdd = NULL;
-	}
-
-	if (cam_vana) {
-		regulator_set_voltage(cam_vana, 0, CAM_VANA_MAXUV);
-		regulator_set_optimum_mode(cam_vana, 0);
-		regulator_disable(cam_vana);
-		regulator_put(cam_vana);
-		cam_vana = NULL;
-	}
-
-	if (cam_vio) {
-		regulator_disable(cam_vio);
-		regulator_put(cam_vio);
-		cam_vio = NULL;
-	}
-
-	if (cam_vdig) {
-		regulator_set_voltage(cam_vdig, 0, CAM_VDIG_MAXUV);
-		regulator_set_optimum_mode(cam_vdig, 0);
-		regulator_disable(cam_vdig);
-		regulator_put(cam_vdig);
-		cam_vdig = NULL;
-	}
-
-	if (cam_vaf) {
-		regulator_set_voltage(cam_vaf, 0, CAM_VAF_MAXUV);
-		regulator_set_optimum_mode(cam_vaf, 0);
-		regulator_disable(cam_vaf);
-		regulator_put(cam_vaf);
-		cam_vaf = NULL;
-	}
-}
-
 int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
 {
 	int rc = 0;
 	struct clk *clk = NULL;
 
 	switch (clktype) {
-	case CAMIO_CAM_MCLK_CLK:
-		camio_cam_clk =
-		clk = clk_get(&camio_dev->dev, "cam_clk");
-		msm_camio_clk_rate_set_2(clk, camio_clk.mclk_clk_rate);
-		break;
-
 	case CAMIO_JPEG_CLK:
 		camio_jpeg_clk =
 		clk = clk_get(NULL, "ijpeg_clk");
@@ -375,10 +150,6 @@
 	struct clk *clk = NULL;
 
 	switch (clktype) {
-	case CAMIO_CAM_MCLK_CLK:
-		clk = camio_cam_clk;
-		break;
-
 	case CAMIO_JPEG_CLK:
 		clk = camio_jpeg_clk;
 		break;
@@ -403,12 +174,6 @@
 	return rc;
 }
 
-void msm_camio_clk_rate_set(int rate)
-{
-	struct clk *clk = camio_cam_clk;
-	clk_set_rate(clk, rate);
-}
-
 void msm_camio_clk_rate_set_2(struct clk *clk, int rate)
 {
 	clk_set_rate(clk, rate);
@@ -417,6 +182,11 @@
 int msm_camio_jpeg_clk_disable(void)
 {
 	int rc = 0;
+	rc = msm_camio_clk_disable(CAMIO_JPEG_PCLK);
+	if (rc < 0)
+		return rc;
+	rc = msm_camio_clk_disable(CAMIO_JPEG_CLK);
+
 	if (fs_ijpeg) {
 		rc = regulator_disable(fs_ijpeg);
 		if (rc < 0) {
@@ -426,10 +196,6 @@
 		}
 		regulator_put(fs_ijpeg);
 	}
-	rc = msm_camio_clk_disable(CAMIO_JPEG_PCLK);
-	if (rc < 0)
-		return rc;
-	rc = msm_camio_clk_disable(CAMIO_JPEG_CLK);
 	CDBG("%s: exit %d\n", __func__, rc);
 	return rc;
 }
@@ -437,12 +203,6 @@
 int msm_camio_jpeg_clk_enable(void)
 {
 	int rc = 0;
-	rc = msm_camio_clk_enable(CAMIO_JPEG_CLK);
-	if (rc < 0)
-		return rc;
-	rc = msm_camio_clk_enable(CAMIO_JPEG_PCLK);
-	if (rc < 0)
-		return rc;
 	fs_ijpeg = regulator_get(NULL, "fs_ijpeg");
 	if (IS_ERR(fs_ijpeg)) {
 		pr_err("%s: Regulator FS_IJPEG get failed %ld\n",
@@ -452,42 +212,18 @@
 		pr_err("%s: Regulator FS_IJPEG enable failed\n", __func__);
 		regulator_put(fs_ijpeg);
 	}
+
+	rc = msm_camio_clk_enable(CAMIO_JPEG_CLK);
+	if (rc < 0)
+		return rc;
+	rc = msm_camio_clk_enable(CAMIO_JPEG_PCLK);
+	if (rc < 0)
+		return rc;
+
 	CDBG("%s: exit %d\n", __func__, rc);
 	return rc;
 }
 
-static int config_gpio_table(struct msm_camera_sensor_info *sinfo, int gpio_en)
-{
-	struct msm_camera_gpio_conf *gpio_conf = sinfo->gpio_conf;
-	int rc = 0, i = 0;
-
-	if (gpio_conf->cam_gpio_tbl == NULL || gpio_conf->cam_gpiomux_conf_tbl
-		== NULL) {
-		pr_err("%s: Invalid NULL cam gpio config table\n", __func__);
-		return -EFAULT;
-	}
-
-	if (gpio_en) {
-		msm_gpiomux_install((struct msm_gpiomux_config *)gpio_conf->
-			cam_gpiomux_conf_tbl,
-			gpio_conf->cam_gpiomux_conf_tbl_size);
-		for (i = 0; i < gpio_conf->cam_gpio_tbl_size; i++) {
-			rc = gpio_request(gpio_conf->cam_gpio_tbl[i],
-				 "CAM_GPIO");
-			if (rc < 0) {
-				pr_err("%s not able to get gpio\n", __func__);
-				for (i--; i >= 0; i--)
-					gpio_free(gpio_conf->cam_gpio_tbl[i]);
-					break;
-			}
-		}
-	} else {
-		for (i = 0; i < gpio_conf->cam_gpio_tbl_size; i++)
-			gpio_free(gpio_conf->cam_gpio_tbl[i]);
-	}
-	return rc;
-}
-
 int32_t msm_camio_3d_enable(const struct msm_camera_sensor_info *s_info)
 {
 	int32_t val = 0, rc = 0;
@@ -554,61 +290,6 @@
 	release_mem_region(s3drw_mem->start, resource_size(s3drw_mem));
 }
 
-static struct pm8xxx_mpp_config_data privacy_light_on_config = {
-	.type		= PM8XXX_MPP_TYPE_SINK,
-	.level		= PM8XXX_MPP_CS_OUT_5MA,
-	.control	= PM8XXX_MPP_CS_CTRL_MPP_LOW_EN,
-};
-
-static struct pm8xxx_mpp_config_data privacy_light_off_config = {
-	.type		= PM8XXX_MPP_TYPE_SINK,
-	.level		= PM8XXX_MPP_CS_OUT_5MA,
-	.control	= PM8XXX_MPP_CS_CTRL_DISABLE,
-};
-
-static struct msm_cam_clk_info cam_clk_info[] = {
-	{"cam_clk", 24000000},
-};
-
-int msm_sensor_probe_on(struct device *dev)
-{
-	int rc = 0;
-	struct msm_camera_sensor_info *sinfo = dev->platform_data;
-	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
-	camio_clk = camdev->ioclk;
-
-	rc = config_gpio_table(sinfo, 1);
-	if (rc < 0)
-		return rc;
-	msm_camera_vreg_enable(dev);
-	if (sinfo->sensor_platform_info->privacy_light) {
-		struct msm8960_privacy_light_cfg *privacy_light_config =
-			sinfo->sensor_platform_info->privacy_light_info;
-		pm8xxx_mpp_config(privacy_light_config->mpp,
-						  &privacy_light_on_config);
-	}
-	return msm_cam_clk_enable(dev, cam_clk_info,
-		&camio_cam_clk, ARRAY_SIZE(cam_clk_info), 1);
-}
-
-int msm_sensor_probe_off(struct device *dev)
-{
-	int rc = 0;
-	struct msm_camera_sensor_info *sinfo = dev->platform_data;
-	if (sinfo->sensor_platform_info->privacy_light) {
-		struct msm8960_privacy_light_cfg *privacy_light_config =
-			sinfo->sensor_platform_info->privacy_light_info;
-		pm8xxx_mpp_config(privacy_light_config->mpp,
-						  &privacy_light_off_config);
-	}
-	msm_camera_vreg_disable();
-	rc = config_gpio_table(sinfo, 0);
-	if (rc < 0)
-		return rc;
-	return msm_cam_clk_enable(dev, cam_clk_info,
-		&camio_cam_clk, ARRAY_SIZE(cam_clk_info), 0);
-}
-
 void msm_camio_mode_config(enum msm_cam_mode mode)
 {
 	uint32_t val;
diff --git a/drivers/media/video/msm/msm_io_8x60.c b/drivers/media/video/msm/msm_io_8x60.c
index bac650a..49ec461 100644
--- a/drivers/media/video/msm/msm_io_8x60.c
+++ b/drivers/media/video/msm/msm_io_8x60.c
@@ -460,10 +460,12 @@
 
 static irqreturn_t msm_io_csi_irq(int irq_num, void *data)
 {
-	uint32_t irq;
-	irq = msm_io_r(csibase + MIPI_INTERRUPT_STATUS);
+	uint32_t irq = 0;
+	if (csibase != NULL)
+		irq = msm_io_r(csibase + MIPI_INTERRUPT_STATUS);
 	CDBG("%s MIPI_INTERRUPT_STATUS = 0x%x\n", __func__, irq);
-	msm_io_w(irq, csibase + MIPI_INTERRUPT_STATUS);
+	if (csibase != NULL)
+		msm_io_w(irq, csibase + MIPI_INTERRUPT_STATUS);
 	return IRQ_HANDLED;
 }
 
@@ -604,8 +606,10 @@
 
 csi_irq_fail:
 	iounmap(csibase);
+	csibase = NULL;
 csi_busy:
 	release_mem_region(camio_ext.csiphy, camio_ext.csisz);
+	csibase = NULL;
 common_fail:
 	msm_camio_clk_disable(CAMIO_CAM_MCLK_CLK);
 	msm_camio_clk_disable(CAMIO_CSI0_VFE_CLK);
@@ -625,27 +629,29 @@
 	uint32_t val;
 
 	val = 0x0;
-	CDBG("%s MIPI_PHY_D0_CONTROL2 val=0x%x\n", __func__, val);
-	msm_io_w(val, csibase + MIPI_PHY_D0_CONTROL2);
-	msm_io_w(val, csibase + MIPI_PHY_D1_CONTROL2);
-	msm_io_w(val, csibase + MIPI_PHY_D2_CONTROL2);
-	msm_io_w(val, csibase + MIPI_PHY_D3_CONTROL2);
-
-	CDBG("%s MIPI_PHY_CL_CONTROL val=0x%x\n", __func__, val);
-	msm_io_w(val, csibase + MIPI_PHY_CL_CONTROL);
-	msleep(10);
-
-	val = msm_io_r(csibase + MIPI_PHY_D1_CONTROL);
-	val &= ~((0x1 << MIPI_PHY_D1_CONTROL_MIPI_CLK_PHY_SHUTDOWNB_SHFT) |
-	(0x1 << MIPI_PHY_D1_CONTROL_MIPI_DATA_PHY_SHUTDOWNB_SHFT));
-	CDBG("%s MIPI_PHY_D1_CONTROL val=0x%x\n", __func__, val);
-	msm_io_w(val, csibase + MIPI_PHY_D1_CONTROL);
-	usleep_range(5000, 6000);
-	msm_io_w(0x0, csibase + MIPI_INTERRUPT_MASK);
-	msm_io_w(0x0, csibase + MIPI_INTERRUPT_STATUS);
-	csi_free_irq();
-	iounmap(csibase);
-	release_mem_region(camio_ext.csiphy, camio_ext.csisz);
+	if (csibase != NULL) {
+		CDBG("%s MIPI_PHY_D0_CONTROL2 val=0x%x\n", __func__, val);
+		msm_io_w(val, csibase + MIPI_PHY_D0_CONTROL2);
+		msm_io_w(val, csibase + MIPI_PHY_D1_CONTROL2);
+		msm_io_w(val, csibase + MIPI_PHY_D2_CONTROL2);
+		msm_io_w(val, csibase + MIPI_PHY_D3_CONTROL2);
+		CDBG("%s MIPI_PHY_CL_CONTROL val=0x%x\n", __func__, val);
+		msm_io_w(val, csibase + MIPI_PHY_CL_CONTROL);
+		msleep(20);
+		val = msm_io_r(csibase + MIPI_PHY_D1_CONTROL);
+		val &=
+		~((0x1 << MIPI_PHY_D1_CONTROL_MIPI_CLK_PHY_SHUTDOWNB_SHFT)
+		|(0x1 << MIPI_PHY_D1_CONTROL_MIPI_DATA_PHY_SHUTDOWNB_SHFT));
+		CDBG("%s MIPI_PHY_D1_CONTROL val=0x%x\n", __func__, val);
+		msm_io_w(val, csibase + MIPI_PHY_D1_CONTROL);
+		usleep_range(5000, 6000);
+		msm_io_w(0x0, csibase + MIPI_INTERRUPT_MASK);
+		msm_io_w(0x0, csibase + MIPI_INTERRUPT_STATUS);
+		csi_free_irq();
+		iounmap(csibase);
+		csibase = NULL;
+		release_mem_region(camio_ext.csiphy, camio_ext.csisz);
+	}
 }
 void msm_camio_disable(struct platform_device *pdev)
 {
@@ -727,78 +733,82 @@
 	int i;
 
 	CDBG("msm_camio_csi_config\n");
+	if (csibase != NULL) {
+		/* SOT_ECC_EN enable error correction for SYNC (data-lane) */
+		msm_io_w(0x4, csibase + MIPI_PHY_CONTROL);
 
-	/* SOT_ECC_EN enable error correction for SYNC (data-lane) */
-	msm_io_w(0x4, csibase + MIPI_PHY_CONTROL);
-
-	/* SW_RST to the CSI core */
-	msm_io_w(MIPI_PROTOCOL_CONTROL_SW_RST_BMSK,
+		/* SW_RST to the CSI core */
+		msm_io_w(MIPI_PROTOCOL_CONTROL_SW_RST_BMSK,
 		csibase + MIPI_PROTOCOL_CONTROL);
 
-	/* PROTOCOL CONTROL */
-	val = MIPI_PROTOCOL_CONTROL_LONG_PACKET_HEADER_CAPTURE_BMSK |
-		MIPI_PROTOCOL_CONTROL_DECODE_ID_BMSK |
-		MIPI_PROTOCOL_CONTROL_ECC_EN_BMSK;
-	val |= (uint32_t)(csi_params->data_format) <<
-		MIPI_PROTOCOL_CONTROL_DATA_FORMAT_SHFT;
-	val |= csi_params->dpcm_scheme <<
-		MIPI_PROTOCOL_CONTROL_DPCM_SCHEME_SHFT;
-	CDBG("%s MIPI_PROTOCOL_CONTROL val=0x%x\n", __func__, val);
-	msm_io_w(val, csibase + MIPI_PROTOCOL_CONTROL);
+		/* PROTOCOL CONTROL */
+		val = MIPI_PROTOCOL_CONTROL_LONG_PACKET_HEADER_CAPTURE_BMSK |
+			MIPI_PROTOCOL_CONTROL_DECODE_ID_BMSK |
+			MIPI_PROTOCOL_CONTROL_ECC_EN_BMSK;
+		val |= (uint32_t)(csi_params->data_format) <<
+			MIPI_PROTOCOL_CONTROL_DATA_FORMAT_SHFT;
+		val |= csi_params->dpcm_scheme <<
+			MIPI_PROTOCOL_CONTROL_DPCM_SCHEME_SHFT;
+		CDBG("%s MIPI_PROTOCOL_CONTROL val=0x%x\n", __func__, val);
+		msm_io_w(val, csibase + MIPI_PROTOCOL_CONTROL);
 
-	/* settle_cnt is very sensitive to speed!
-	increase this value to run at higher speeds */
-	val = (csi_params->settle_cnt <<
-		MIPI_PHY_D0_CONTROL2_SETTLE_COUNT_SHFT) |
-		(0x0F << MIPI_PHY_D0_CONTROL2_HS_TERM_IMP_SHFT) |
-		(0x1 << MIPI_PHY_D0_CONTROL2_LP_REC_EN_SHFT) |
-		(0x1 << MIPI_PHY_D0_CONTROL2_ERR_SOT_HS_EN_SHFT);
-	CDBG("%s MIPI_PHY_D0_CONTROL2 val=0x%x\n", __func__, val);
-	for (i = 0; i < csi_params->lane_cnt; i++)
-		msm_io_w(val, csibase + MIPI_PHY_D0_CONTROL2 + i * 4);
+		/* settle_cnt is very sensitive to speed!
+		increase this value to run at higher speeds */
+		val = (csi_params->settle_cnt <<
+			MIPI_PHY_D0_CONTROL2_SETTLE_COUNT_SHFT) |
+			(0x0F << MIPI_PHY_D0_CONTROL2_HS_TERM_IMP_SHFT) |
+			(0x1 << MIPI_PHY_D0_CONTROL2_LP_REC_EN_SHFT) |
+			(0x1 << MIPI_PHY_D0_CONTROL2_ERR_SOT_HS_EN_SHFT);
+		CDBG("%s MIPI_PHY_D0_CONTROL2 val=0x%x\n", __func__, val);
+		for (i = 0; i < csi_params->lane_cnt; i++)
+			msm_io_w(val, csibase + MIPI_PHY_D0_CONTROL2 + i * 4);
 
-	val = (0x0F << MIPI_PHY_CL_CONTROL_HS_TERM_IMP_SHFT) |
-		(0x1 << MIPI_PHY_CL_CONTROL_LP_REC_EN_SHFT);
-	CDBG("%s MIPI_PHY_CL_CONTROL val=0x%x\n", __func__, val);
-	msm_io_w(val, csibase + MIPI_PHY_CL_CONTROL);
+		val = (0x0F << MIPI_PHY_CL_CONTROL_HS_TERM_IMP_SHFT) |
+			(0x1 << MIPI_PHY_CL_CONTROL_LP_REC_EN_SHFT);
+		CDBG("%s MIPI_PHY_CL_CONTROL val=0x%x\n", __func__, val);
+		msm_io_w(val, csibase + MIPI_PHY_CL_CONTROL);
 
-	val = 0 << MIPI_PHY_D0_CONTROL_HS_REC_EQ_SHFT;
-	msm_io_w(val, csibase + MIPI_PHY_D0_CONTROL);
+		val = 0 << MIPI_PHY_D0_CONTROL_HS_REC_EQ_SHFT;
+		msm_io_w(val, csibase + MIPI_PHY_D0_CONTROL);
 
-	val = (0x1 << MIPI_PHY_D1_CONTROL_MIPI_CLK_PHY_SHUTDOWNB_SHFT) |
-		(0x1 << MIPI_PHY_D1_CONTROL_MIPI_DATA_PHY_SHUTDOWNB_SHFT);
-	CDBG("%s MIPI_PHY_D1_CONTROL val=0x%x\n", __func__, val);
-	msm_io_w(val, csibase + MIPI_PHY_D1_CONTROL);
+		val =
+		(0x1 << MIPI_PHY_D1_CONTROL_MIPI_CLK_PHY_SHUTDOWNB_SHFT)
+		|(0x1 << MIPI_PHY_D1_CONTROL_MIPI_DATA_PHY_SHUTDOWNB_SHFT);
+		CDBG("%s MIPI_PHY_D1_CONTROL val=0x%x\n", __func__, val);
+		msm_io_w(val, csibase + MIPI_PHY_D1_CONTROL);
 
-	msm_io_w(0x00000000, csibase + MIPI_PHY_D2_CONTROL);
-	msm_io_w(0x00000000, csibase + MIPI_PHY_D3_CONTROL);
+		msm_io_w(0x00000000, csibase + MIPI_PHY_D2_CONTROL);
+		msm_io_w(0x00000000, csibase + MIPI_PHY_D3_CONTROL);
 
-	/* halcyon only supports 1 or 2 lane */
-	switch (csi_params->lane_cnt) {
-	case 1:
-		msm_io_w(csi_params->lane_assign << 8 | 0x4,
-			csibase + MIPI_CAMERA_CNTL);
-		break;
-	case 2:
-		msm_io_w(csi_params->lane_assign << 8 | 0x5,
-			csibase + MIPI_CAMERA_CNTL);
-		break;
-	case 3:
-		msm_io_w(csi_params->lane_assign << 8 | 0x6,
-			csibase + MIPI_CAMERA_CNTL);
-		break;
-	case 4:
-		msm_io_w(csi_params->lane_assign << 8 | 0x7,
-			csibase + MIPI_CAMERA_CNTL);
-		break;
+		/* halcyon only supports 1 or 2 lane */
+		switch (csi_params->lane_cnt) {
+		case 1:
+			msm_io_w(csi_params->lane_assign << 8 | 0x4,
+				csibase + MIPI_CAMERA_CNTL);
+			break;
+		case 2:
+			msm_io_w(csi_params->lane_assign << 8 | 0x5,
+				csibase + MIPI_CAMERA_CNTL);
+			break;
+		case 3:
+			msm_io_w(csi_params->lane_assign << 8 | 0x6,
+				csibase + MIPI_CAMERA_CNTL);
+			break;
+		case 4:
+			msm_io_w(csi_params->lane_assign << 8 | 0x7,
+				csibase + MIPI_CAMERA_CNTL);
+			break;
+		}
+
+		/* mask out ID_ERROR[19], DATA_CMM_ERR[11]
+		and CLK_CMM_ERR[10] - de-featured */
+		msm_io_w(0xF017F3C0, csibase + MIPI_INTERRUPT_MASK);
+		/*clear IRQ bits*/
+		msm_io_w(0xF017F3C0, csibase + MIPI_INTERRUPT_STATUS);
+	} else {
+		pr_info("CSIBASE is NULL");
 	}
 
-	/* mask out ID_ERROR[19], DATA_CMM_ERR[11]
-	and CLK_CMM_ERR[10] - de-featured */
-	msm_io_w(0xF017F3C0, csibase + MIPI_INTERRUPT_MASK);
-	/*clear IRQ bits*/
-	msm_io_w(0xF017F3C0, csibase + MIPI_INTERRUPT_STATUS);
-
 	return rc;
 }
 
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 0a1516b..6b3aef7 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.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
@@ -69,9 +69,78 @@
 	}
 }
 
+static int msm_isp_notify_VFE_BUF_FREE_EVT(struct v4l2_subdev *sd, void *arg)
+{
+	struct msm_vfe_cfg_cmd cfgcmd;
+	struct msm_camvfe_params vfe_params;
+	int rc;
+
+	cfgcmd.cmd_type = CMD_VFE_BUFFER_RELEASE;
+	cfgcmd.value = NULL;
+	vfe_params.vfe_cfg = &cfgcmd;
+	vfe_params.data = NULL;
+	rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
+	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;
@@ -86,18 +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;
@@ -105,9 +180,11 @@
 		rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
 		break;
 	case VFE_MSG_V32_CAPTURE:
+	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;
@@ -123,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;
@@ -161,6 +239,9 @@
 	if (notification == NOTIFY_VFE_BUF_EVT)
 		return msm_isp_notify_VFE_BUF_EVT(sd, arg);
 
+	if (notification == NOTIFY_VFE_BUF_FREE_EVT)
+		return msm_isp_notify_VFE_BUF_FREE_EVT(sd, arg);
+
 	isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_ATOMIC);
 	if (!isp_event) {
 		pr_err("%s Insufficient memory. return", __func__);
@@ -200,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);
@@ -213,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);
 		}
@@ -376,6 +465,19 @@
 		axi_data.region = &region[0];
 		return msm_isp_subdev_ioctl(sd, &cfgcmd,
 							&axi_data);
+	case CMD_STATS_AEC_AWB_ENABLE:
+		axi_data.bufnum1 =
+			msm_pmem_region_lookup(&sync->pmem_stats,
+			MSM_PMEM_AEC_AWB, &region[0],
+			NUM_STAT_OUTPUT_BUFFERS);
+		if (!axi_data.bufnum1) {
+			pr_err("%s %d: pmem region lookup error\n",
+				__func__, __LINE__);
+			return -EINVAL;
+		}
+		axi_data.region = &region[0];
+		return msm_isp_subdev_ioctl(sd, &cfgcmd,
+							&axi_data);
 	case CMD_STATS_IHIST_ENABLE:
 		axi_data.bufnum1 =
 			msm_pmem_region_lookup(&sync->pmem_stats,
@@ -529,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.
@@ -614,6 +721,8 @@
 			cfgcmd.cmd_type = CMD_STATS_RS_BUF_RELEASE;
 		else if (buf.type == STAT_CS)
 			cfgcmd.cmd_type = CMD_STATS_CS_BUF_RELEASE;
+		else if (buf.type == STAT_AEAW)
+			cfgcmd.cmd_type = CMD_STATS_BUF_RELEASE;
 
 		else {
 			pr_err("%s: invalid buf type %d\n",
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index e13dd62..2c4fbe4 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -29,6 +29,7 @@
 
 #include "msm.h"
 #include "msm_csid.h"
+#include "msm_csic.h"
 #include "msm_csiphy.h"
 #include "msm_ispif.h"
 #include "msm_sensor.h"
@@ -92,6 +93,14 @@
 	.colorspace = V4L2_COLORSPACE_JPEG,
 	},
 	{
+	.name	   = "NV21BAYER",
+	.depth	  = 8,
+	.bitsperpxl = 8,
+	.fourcc	 = V4L2_PIX_FMT_NV21,
+	.pxlcode	= V4L2_MBUS_FMT_SGRBG10_1X10, /* Bayer sensor */
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	},
+	{
 	.name	   = "YU12BAYER",
 	.depth	  = 8,
 	.bitsperpxl = 8,
@@ -107,6 +116,14 @@
 	.pxlcode	= V4L2_MBUS_FMT_SBGGR10_1X10, /* Bayer sensor */
 	.colorspace = V4L2_COLORSPACE_JPEG,
 	},
+	{
+	.name	   = "RAWBAYER",
+	.depth	  = 10,
+	.bitsperpxl = 10,
+	.fourcc	 = V4L2_PIX_FMT_SBGGR10,
+	.pxlcode	= V4L2_MBUS_FMT_SGRBG10_1X10, /* Bayer sensor */
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	},
 
 };
 
@@ -225,6 +242,7 @@
 	case NOTIFY_VFE_MSG_OUT:
 	case NOTIFY_VFE_MSG_STATS:
 	case NOTIFY_VFE_BUF_EVT:
+	case NOTIFY_VFE_BUF_FREE_EVT:
 		if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
 			rc = p_mctl->isp_sdev->isp_notify(
 				p_mctl->isp_sdev->sd, notification, arg);
@@ -248,6 +266,10 @@
 		rc = v4l2_subdev_call(p_mctl->csid_sdev,
 			core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
 		break;
+	case NOTIFY_CSIC_CFG:
+		rc = v4l2_subdev_call(p_mctl->csic_sdev,
+			core, ioctl, VIDIOC_MSM_CSIC_CFG, arg);
+		break;
 	default:
 		break;
 	}
@@ -255,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,
@@ -387,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*/
@@ -416,44 +461,70 @@
 	struct device *dev;
 	int rc = -ENODEV;
 
-	/* register csiphy subdev */
-	driver = driver_find(MSM_CSIPHY_DRV_NAME, &platform_bus_type);
-	if (!driver)
-		goto out;
+	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(p_mctl->sensor_sdev);
+	struct msm_camera_sensor_info *sinfo =
+		(struct msm_camera_sensor_info *) s_ctrl->sensordata;
+	struct msm_camera_device_platform_data *pdata = sinfo->pdata;
 
-	dev = driver_find_device(driver, NULL, (void *)core_index,
+	if (pdata->is_csiphy) {
+		/* register csiphy subdev */
+		driver = driver_find(MSM_CSIPHY_DRV_NAME, &platform_bus_type);
+		if (!driver)
+			goto out;
+
+		dev = driver_find_device(driver, NULL, (void *)core_index,
 				msm_mctl_subdev_match_core);
-	if (!dev)
-		goto out_put_driver;
+		if (!dev)
+			goto out_put_driver;
 
-	p_mctl->csiphy_sdev = dev_get_drvdata(dev);
-	put_driver(driver);
+		p_mctl->csiphy_sdev = dev_get_drvdata(dev);
+		put_driver(driver);
+	}
 
-	/* register csid subdev */
-	driver = driver_find(MSM_CSID_DRV_NAME, &platform_bus_type);
-	if (!driver)
-		goto out;
+	if (pdata->is_csic) {
+		/* register csic subdev */
+		driver = driver_find(MSM_CSIC_DRV_NAME, &platform_bus_type);
+		if (!driver)
+			goto out;
 
-	dev = driver_find_device(driver, NULL, (void *)core_index,
+		dev = driver_find_device(driver, NULL, (void *)core_index,
 				msm_mctl_subdev_match_core);
-	if (!dev)
-		goto out_put_driver;
+		if (!dev)
+			goto out_put_driver;
 
-	p_mctl->csid_sdev = dev_get_drvdata(dev);
-	put_driver(driver);
+		p_mctl->csic_sdev = dev_get_drvdata(dev);
+		put_driver(driver);
+	}
 
-	/* register ispif subdev */
-	driver = driver_find(MSM_ISPIF_DRV_NAME, &platform_bus_type);
-	if (!driver)
-		goto out;
+	if (pdata->is_csid) {
+		/* register csid subdev */
+		driver = driver_find(MSM_CSID_DRV_NAME, &platform_bus_type);
+		if (!driver)
+			goto out;
 
-	dev = driver_find_device(driver, NULL, 0,
+		dev = driver_find_device(driver, NULL, (void *)core_index,
 				msm_mctl_subdev_match_core);
-	if (!dev)
-		goto out_put_driver;
+		if (!dev)
+			goto out_put_driver;
 
-	p_mctl->ispif_sdev = dev_get_drvdata(dev);
-	put_driver(driver);
+		p_mctl->csid_sdev = dev_get_drvdata(dev);
+		put_driver(driver);
+	}
+
+	if (pdata->is_ispif) {
+		/* register ispif subdev */
+		driver = driver_find(MSM_ISPIF_DRV_NAME, &platform_bus_type);
+		if (!driver)
+			goto out;
+
+		dev = driver_find_device(driver, NULL, 0,
+				msm_mctl_subdev_match_core);
+		if (!dev)
+			goto out_put_driver;
+
+		p_mctl->ispif_sdev = dev_get_drvdata(dev);
+		put_driver(driver);
+	}
 
 	/* register vfe subdev */
 	driver = driver_find(MSM_VFE_DRV_NAME, &platform_bus_type);
@@ -468,18 +539,20 @@
 	p_mctl->isp_sdev->sd = dev_get_drvdata(dev);
 	put_driver(driver);
 
-	/* register vfe subdev */
-	driver = driver_find(MSM_VPE_DRV_NAME, &platform_bus_type);
-	if (!driver)
-		goto out;
+	if (pdata->is_vpe) {
+		/* register vfe subdev */
+		driver = driver_find(MSM_VPE_DRV_NAME, &platform_bus_type);
+		if (!driver)
+			goto out;
 
-	dev = driver_find_device(driver, NULL, 0,
+		dev = driver_find_device(driver, NULL, 0,
 				msm_mctl_subdev_match_core);
-	if (!dev)
-		goto out_put_driver;
+		if (!dev)
+			goto out_put_driver;
 
-	p_mctl->isp_sdev->sd_vpe = dev_get_drvdata(dev);
-	put_driver(driver);
+		p_mctl->isp_sdev->sd_vpe = dev_get_drvdata(dev);
+		put_driver(driver);
+	}
 
 	rc = 0;
 	return rc;
@@ -522,20 +595,33 @@
 			goto msm_open_done;
 		}
 
-		rc = v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
-			VIDIOC_MSM_CSIPHY_INIT, NULL);
-		if (rc < 0) {
-			pr_err("%s: csiphy initialization failed %d\n",
+		if (camdev->is_csiphy) {
+			rc = v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
+				VIDIOC_MSM_CSIPHY_INIT, NULL);
+			if (rc < 0) {
+				pr_err("%s: csiphy initialization failed %d\n",
 				__func__, rc);
-			goto msm_open_done;
+				goto msm_open_done;
+			}
 		}
 
-		rc = v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
-			VIDIOC_MSM_CSID_INIT, &csid_version);
-		if (rc < 0) {
-			pr_err("%s: csid initialization failed %d\n",
+		if (camdev->is_csid) {
+			rc = v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
+				VIDIOC_MSM_CSID_INIT, &csid_version);
+			if (rc < 0) {
+				pr_err("%s: csid initialization failed %d\n",
 				__func__, rc);
-			goto msm_open_done;
+				goto msm_open_done;
+			}
+		}
+		if (camdev->is_csic) {
+			rc = v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
+				VIDIOC_MSM_CSIC_INIT, &csid_version);
+			if (rc < 0) {
+				pr_err("%s: csic initialization failed %d\n",
+				__func__, rc);
+				goto msm_open_done;
+			}
 		}
 
 		/* ISP first*/
@@ -548,12 +634,14 @@
 			goto msm_open_done;
 		}
 
-		rc = v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
-			VIDIOC_MSM_ISPIF_INIT, &csid_version);
-		if (rc < 0) {
-			pr_err("%s: ispif initialization failed %d\n",
+		if (camdev->is_ispif) {
+			rc = v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
+				VIDIOC_MSM_ISPIF_INIT, &csid_version);
+			if (rc < 0) {
+				pr_err("%s: ispif initialization failed %d\n",
 				__func__, rc);
-			goto msm_open_done;
+				goto msm_open_done;
+			}
 		}
 
 		/* then sensor - move sub dev later*/
@@ -563,7 +651,6 @@
 			pr_err("%s: isp init failed: %d\n", __func__, rc);
 			goto msm_open_done;
 		}
-
 		if (sync->actctrl.a_power_up)
 			rc = sync->actctrl.a_power_up(
 				sync->sdata->actuator_info);
@@ -573,12 +660,13 @@
 			goto msm_open_done;
 		}
 
-		pm_qos_add_request(&p_mctl->pm_qos_req_list,
+		if (camdev->is_ispif) {
+			pm_qos_add_request(&p_mctl->pm_qos_req_list,
 					PM_QOS_CPU_DMA_LATENCY,
 					PM_QOS_DEFAULT_VALUE);
-		pm_qos_update_request(&p_mctl->pm_qos_req_list,
+			pm_qos_update_request(&p_mctl->pm_qos_req_list,
 					MSM_V4L2_SWFI_LATENCY);
-
+		}
 		sync->apps_id = apps_id;
 		sync->opencnt++;
 	}
@@ -591,28 +679,44 @@
 static int msm_mctl_release(struct msm_cam_media_controller *p_mctl)
 {
 	int rc = 0;
-	v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
-		VIDIOC_MSM_ISPIF_RELEASE, NULL);
+	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(p_mctl->sensor_sdev);
+	struct msm_camera_sensor_info *sinfo =
+		(struct msm_camera_sensor_info *) s_ctrl->sensordata;
+	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+
+	if (camdev->is_ispif) {
+		v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
+			VIDIOC_MSM_ISPIF_RELEASE, NULL);
+	}
 
 	if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
 		p_mctl->isp_sdev->isp_release(&p_mctl->sync);
 
-	v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
-		VIDIOC_MSM_CSID_RELEASE, NULL);
+	if (camdev->is_csid) {
+		v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
+			VIDIOC_MSM_CSID_RELEASE, NULL);
+	}
 
-	v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
-		VIDIOC_MSM_CSIPHY_RELEASE, NULL);
+	if (camdev->is_csic) {
+		v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
+			VIDIOC_MSM_CSIC_RELEASE, NULL);
+	}
+
+	if (camdev->is_csiphy) {
+		v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
+			VIDIOC_MSM_CSIPHY_RELEASE, NULL);
+	}
 
 	if (p_mctl->sync.actctrl.a_power_down)
 		p_mctl->sync.actctrl.a_power_down(
 			p_mctl->sync.sdata->actuator_info);
 
 	v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 0);
-
-	pm_qos_update_request(&p_mctl->pm_qos_req_list,
+	if (camdev->is_ispif) {
+		pm_qos_update_request(&p_mctl->pm_qos_req_list,
 				PM_QOS_DEFAULT_VALUE);
-	pm_qos_remove_request(&p_mctl->pm_qos_req_list);
-
+		pm_qos_remove_request(&p_mctl->pm_qos_req_list);
+	}
 	wake_unlock(&p_mctl->sync.wake_lock);
 	return rc;
 }
@@ -697,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);
@@ -704,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_mem.c b/drivers/media/video/msm/msm_mem.c
index b631981..0ba1c0f 100644
--- a/drivers/media/video/msm/msm_mem.c
+++ b/drivers/media/video/msm/msm_mem.c
@@ -220,6 +220,7 @@
 	case MSM_PMEM_CS:
 	case MSM_PMEM_IHIST:
 	case MSM_PMEM_SKIN:
+	case MSM_PMEM_AEC_AWB:
 		rc = msm_pmem_table_add(ptype, pinfo, client);
 		break;
 
@@ -246,6 +247,7 @@
 	case MSM_PMEM_CS:
 	case MSM_PMEM_IHIST:
 	case MSM_PMEM_SKIN:
+	case MSM_PMEM_AEC_AWB:
 		hlist_for_each_entry_safe(region, node, n,
 				ptype, list) {
 
diff --git a/drivers/media/video/msm/msm_vfe31.c b/drivers/media/video/msm/msm_vfe31.c
index 2b3732c..f1d70aa 100644
--- a/drivers/media/video/msm/msm_vfe31.c
+++ b/drivers/media/video/msm/msm_vfe31.c
@@ -3892,6 +3892,7 @@
 	spin_lock_init(&vfe31_ctrl->io_lock);
 	spin_lock_init(&vfe31_ctrl->update_ack_lock);
 	spin_lock_init(&vfe31_ctrl->tasklet_lock);
+	spin_lock_init(&vfe31_ctrl->xbar_lock);
 
 	INIT_LIST_HEAD(&vfe31_ctrl->tasklet_q);
 	vfe31_init_free_buf_queue();
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_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
new file mode 100644
index 0000000..638c51d
--- /dev/null
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -0,0 +1,1353 @@
+/* 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/msm_adsp.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/android_pmem.h>
+#include <linux/slab.h>
+#include <linux/pm_qos_params.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/msm_isp.h>
+#include <mach/msm_adsp.h>
+#include <mach/clk.h>
+#include <mach/camera.h>
+#include "msm_vfe7x27a_v4l2.h"
+#include "msm.h"
+
+/* ADSP Messages */
+#define MSG_RESET_ACK  0
+#define MSG_STOP_ACK  1
+#define MSG_SNAPSHOT  2
+#define MSG_ILLEGAL_COMMAND  3
+#define MSG_START_ACK  4
+#define MSG_UPDATE_ACK  5
+#define MSG_OUTPUT1  6
+#define MSG_OUTPUT2  7
+#define MSG_STATS_AF  8
+#define MSG_STATS_WE  9
+#define MSG_STATS_HISTOGRAM  10
+#define MSG_EPOCH1  11
+#define MSG_EPOCH2  12
+#define MSG_VFE_ERROR 13
+#define MSG_SYNC_TIMER1_DONE  14
+#define MSG_SYNC_TIMER2_DONE  15
+#define MSG_ASYNC_TIMER1_DONE  16
+#define MSG_ASYNC_TIMER2_DONE  17
+#define MSG_CAPTURE_COMPLETE  18
+#define MSG_TABLE_CMD_ACK  19
+#define MSG_EXP_TIMEOUT_ACK  20
+#define MSG_SOF  21
+#define MSG_OUTPUT_T  22
+#define MSG_OUTPUT_S  23
+
+#define VFE_ADSP_EVENT 0xFFFF
+#define SNAPSHOT_MASK_MODE 0x00000001
+#define MSM_AXI_QOS_PREVIEW	122000
+#define MSM_AXI_QOS_SNAPSHOT	192000
+
+
+#define QDSP_CMDQUEUE 25
+#define QDSP_SCALEQUEUE 26
+#define QDSP_TABLEQUEUE 27
+
+/* ADSP Scler queue Cmd IDs */
+#define VFE_SCALE_OUTPUT1_CONFIG  0
+#define VFE_SCALE_OUTPUT2_CONFIG  1
+#define VFE_SCALE_MAX  0xFFFFFFFF
+
+/* ADSP table queue Cmd IDs */
+#define VFE_AXI_INPUT_CONFIG  0
+#define VFE_AXI_OUTPUT_CONFIG  1
+#define VFE_RGB_GAMMA_CONFIG  2
+#define VFE_Y_GAMMA_CONFIG  3
+#define VFE_ROLL_OFF_CONFIG  4
+#define VFE_DEMOSAICv3_BPC_CFG  6
+#define VFE_DEMOSAICv3_ABF_CFG  7
+#define VFE_DEMOSAICv3_CFG  8
+#define VFE_MAX  0xFFFFFFFF
+
+/* ADSP cfg queue cmd IDs */
+#define VFE_RESET  0
+#define VFE_START  1
+#define VFE_STOP  2
+#define VFE_UPDATE  3
+#define VFE_CAMIF_CONFIG  4
+#define VFE_ACTIVE_REGION_CONFIG  5
+#define VFE_DEMOSAIC_CONFIG  6
+#define VFE_INPUT_FORMAT_CONFIG  7
+#define VFE_OUTPUT_CLAMP_CONFIG  8
+#define VFE_CHROMA_SUBSAMPLE_CONFIG  9
+#define VFE_BLACK_LEVEL_CONFIG  10
+#define VFE_WHITE_BALANCE_CONFIG  11
+#define VFE_COLOR_PROCESSING_CONFIG  12
+#define VFE_ADAPTIVE_FILTER_CONFIG  13
+#define VFE_FRAME_SKIP_CONFIG  14
+#define VFE_FOV_CROP  15
+#define VFE_STATS_AUTOFOCUS_CONFIG  16
+#define VFE_STATS_WB_EXP_CONFIG  17
+#define VFE_STATS_HISTOGRAM_CONFIG  18
+#define VFE_OUTPUT1_ACK  19
+#define VFE_OUTPUT2_ACK  20
+#define VFE_STATS_AUTOFOCUS_ACK  21
+#define VFE_STATS_WB_EXP_ACK  22
+#define VFE_EPOCH1_ACK  23
+#define VFE_EPOCH2_ACK  24
+#define VFE_UPDATE_CAMIF_FRAME_CONFIG  25
+#define VFE_SYNC_TIMER1_CONFIG  26
+#define VFE_SYNC_TIMER2_CONFIG  27
+#define VFE_ASYNC_TIMER1_START  28
+#define VFE_ASYNC_TIMER2_START  29
+#define VFE_STATS_AUTOFOCUS_UPDATE  30
+#define VFE_STATS_WB_EXP_UPDATE  31
+#define VFE_ROLL_OFF_UPDATE  33
+#define VFE_DEMOSAICv3_BPC_UPDATE  34
+#define VFE_TESTGEN_START  35
+#define VFE_STATS_MA  0xFFFFFFFF
+
+struct msg_id_map msgs_map[] = {
+	{MSG_RESET_ACK, MSG_ID_RESET_ACK},
+	{MSG_STOP_ACK, MSG_ID_STOP_ACK},
+	{MSG_SNAPSHOT, MSG_ID_SNAPSHOT_DONE},
+	{MSG_ILLEGAL_COMMAND, VFE_MAX},
+	{MSG_START_ACK, MSG_ID_START_ACK},
+	{MSG_UPDATE_ACK, MSG_ID_UPDATE_ACK},
+	{MSG_OUTPUT1, VFE_MAX},
+	{MSG_OUTPUT2, VFE_MAX},
+	{MSG_STATS_AF, MSG_ID_STATS_AF},
+	{MSG_STATS_WE, MSG_ID_STATS_AWB_AEC},
+	{MSG_STATS_HISTOGRAM, MSG_ID_STATS_IHIST},
+	{MSG_EPOCH1, MSG_ID_EPOCH1},
+	{MSG_EPOCH2, MSG_ID_EPOCH2},
+	{MSG_VFE_ERROR, MSG_ID_CAMIF_ERROR},
+	{MSG_SYNC_TIMER1_DONE, MSG_ID_SYNC_TIMER1_DONE},
+	{MSG_SYNC_TIMER2_DONE, MSG_ID_SYNC_TIMER2_DONE},
+	{MSG_ASYNC_TIMER1_DONE, MSG_ID_ASYNC_TIMER1_DONE},
+	{MSG_ASYNC_TIMER2_DONE, MSG_ID_ASYNC_TIMER2_DONE},
+	{MSG_CAPTURE_COMPLETE, MSG_CAPTURE_COMPLETE},
+	{MSG_TABLE_CMD_ACK, MSG_TABLE_CMD_ACK},
+	{MSG_EXP_TIMEOUT_ACK, MSG_EXP_TIMEOUT_ACK},
+	{MSG_SOF, MSG_ID_SOF_ACK},
+	{MSG_OUTPUT_T, MSG_ID_OUTPUT_T},
+	{MSG_OUTPUT_S, MSG_ID_OUTPUT_S},
+};
+
+struct cmd_id_map cmds_map[] = {
+	{VFE_CMD_DUMMY_0, VFE_MAX, VFE_MAX},
+	{VFE_CMD_SET_CLK, VFE_MAX, VFE_MAX},
+	{VFE_CMD_RESET, VFE_RESET, QDSP_CMDQUEUE,
+			"VFE_CMD_RESET", "VFE_RESET"},
+	{VFE_CMD_START, VFE_START, QDSP_CMDQUEUE,
+			"VFE_CMD_START", "VFE_START"},
+	{VFE_CMD_TEST_GEN_START, VFE_TESTGEN_START, QDSP_CMDQUEUE,
+		"VFE_CMD_TEST_GEN_START", "VFE_TESTGEN_START"},
+	{VFE_CMD_OPERATION_CFG, VFE_MAX , VFE_MAX},
+	{VFE_CMD_AXI_OUT_CFG, VFE_AXI_OUTPUT_CONFIG, QDSP_TABLEQUEUE,
+		"VFE_CMD_AXI_OUT_CFG", "VFE_AXI_OUTPUT_CONFIG"},
+	{VFE_CMD_CAMIF_CFG, VFE_CAMIF_CONFIG, QDSP_CMDQUEUE,
+			"VFE_CMD_CAMIF_CFG", "VFE_CAMIF_CONFIG"},
+	{VFE_CMD_AXI_INPUT_CFG, VFE_AXI_INPUT_CONFIG, QDSP_TABLEQUEUE,
+		"VFE_CMD_AXI_INPUT_CFG", "VFE_AXI_INPUT_CONFIG"},
+	{VFE_CMD_BLACK_LEVEL_CFG, VFE_BLACK_LEVEL_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_BLACK_LEVEL_CFG", "VFE_BLACK_LEVEL_CONFIG"},
+	{VFE_CMD_MESH_ROLL_OFF_CFG, VFE_ROLL_OFF_CONFIG, QDSP_TABLEQUEUE,
+		"VFE_CMD_MESH_ROLL_OFF_CFG", "VFE_ROLL_OFF_CONFIG"},
+	{VFE_CMD_DEMUX_CFG, VFE_INPUT_FORMAT_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_DEMUX_CFG", "VFE_INPUT_FORMAT_CONFIG"},
+	{VFE_CMD_FOV_CFG, VFE_FOV_CROP, QDSP_CMDQUEUE,
+		"VFE_CMD_FOV_CFG", "VFE_FOV_CROP"},
+	{VFE_CMD_MAIN_SCALER_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_WB_CFG, VFE_WHITE_BALANCE_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_WB_CFG", "VFE_WHITE_BALANCE_CONFIG"},
+	{VFE_CMD_COLOR_COR_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_RGB_G_CFG, VFE_RGB_GAMMA_CONFIG, QDSP_TABLEQUEUE,
+		"VFE_CMD_RGB_G_CFG", "VFE_RGB_GAMMA_CONFIG"},
+	{VFE_CMD_LA_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CHROMA_EN_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CHROMA_SUP_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_MCE_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_SK_ENHAN_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_ASF_CFG, VFE_ADAPTIVE_FILTER_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_ASF_CFG", "VFE_ADAPTIVE_FILTER_CONFIG"},
+	{VFE_CMD_S2Y_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_S2CbCr_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CHROMA_SUBS_CFG, VFE_CHROMA_SUBSAMPLE_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_CHROMA_SUBS_CFG", "VFE_CHROMA_SUBSAMPLE_CONFIG"},
+	{VFE_CMD_OUT_CLAMP_CFG, VFE_OUTPUT_CLAMP_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_OUT_CLAMP_CFG", "VFE_OUTPUT_CLAMP_CONFIG"},
+	{VFE_CMD_FRAME_SKIP_CFG, VFE_FRAME_SKIP_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_FRAME_SKIP_CFG", "VFE_FRAME_SKIP_CONFIG"},
+	{VFE_CMD_DUMMY_1, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DUMMY_2, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DUMMY_3, VFE_MAX, VFE_MAX},
+	{VFE_CMD_UPDATE, VFE_UPDATE, QDSP_CMDQUEUE,
+		"VFE_CMD_UPDATE", "VFE_UPDATE"},
+	{VFE_CMD_BL_LVL_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DEMUX_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_FOV_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_MAIN_SCALER_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_WB_UPDATE, VFE_WHITE_BALANCE_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_WB_UPDATE", "VFE_WHITE_BALANCE_CONFIG"},
+	{VFE_CMD_COLOR_COR_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_RGB_G_UPDATE, VFE_RGB_GAMMA_CONFIG, QDSP_TABLEQUEUE,
+		"VFE_CMD_RGB_G_UPDATE", "VFE_RGB_GAMMA_CONFIG"},
+	{VFE_CMD_LA_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CHROMA_EN_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CHROMA_SUP_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_MCE_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_SK_ENHAN_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_S2CbCr_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_S2Y_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_ASF_UPDATE, VFE_ADAPTIVE_FILTER_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_ASF_UPDATE", "VFE_ADAPTIVE_FILTER_CONFIG"},
+	{VFE_CMD_FRAME_SKIP_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CAMIF_FRAME_UPDATE, VFE_UPDATE_CAMIF_FRAME_CONFIG,
+		QDSP_CMDQUEUE, "VFE_CMD_CAMIF_FRAME_UPDATE",
+		"VFE_UPDATE_CAMIF_FRAME_CONFIG"},
+	{VFE_CMD_STATS_AF_UPDATE, VFE_STATS_AUTOFOCUS_UPDATE, QDSP_CMDQUEUE,
+		"VFE_CMD_STATS_AF_UPDATE", "VFE_STATS_AUTOFOCUS_UPDATE"},
+	{VFE_CMD_STATS_AE_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AWB_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_RS_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_CS_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_SKIN_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_IHIST_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DUMMY_4, VFE_MAX, VFE_MAX},
+	{VFE_CMD_EPOCH1_ACK, VFE_EPOCH1_ACK, QDSP_CMDQUEUE,
+			"VFE_CMD_EPOCH1_ACK", "VFE_EPOCH1_ACK"},
+	{VFE_CMD_EPOCH2_ACK, VFE_EPOCH2_ACK, QDSP_CMDQUEUE,
+			"VFE_CMD_EPOCH2_ACK", "VFE_EPOCH2_ACK"},
+	{VFE_CMD_START_RECORDING, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STOP_RECORDING, VFE_MAX , VFE_MAX},
+	{VFE_CMD_DUMMY_5, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DUMMY_6, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CAPTURE, VFE_START, QDSP_CMDQUEUE,
+			"VFE_CMD_CAPTURE", "VFE_START"},
+	{VFE_CMD_DUMMY_7, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STOP, VFE_STOP, QDSP_CMDQUEUE, "VFE_CMD_STOP", "VFE_STOP"},
+	{VFE_CMD_GET_HW_VERSION, VFE_MAX, VFE_MAX},
+	{VFE_CMD_GET_FRAME_SKIP_COUNTS, VFE_MAX, VFE_MAX},
+	{VFE_CMD_OUTPUT1_BUFFER_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_OUTPUT2_BUFFER_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_OUTPUT3_BUFFER_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_JPEG_OUT_BUF_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_RAW_OUT_BUF_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_RAW_IN_BUF_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AF_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AE_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AWB_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_RS_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_CS_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_SKIN_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_IHIST_ENQ, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DUMMY_8, VFE_MAX, VFE_MAX},
+	{VFE_CMD_JPEG_ENC_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DUMMY_9, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AF_START, VFE_STATS_AUTOFOCUS_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_STATS_AF_START", "VFE_STATS_AUTOFOCUS_CONFIG"},
+	{VFE_CMD_STATS_AF_STOP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AE_START, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AE_STOP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AWB_START, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_AWB_STOP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_RS_START, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_RS_STOP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_CS_START, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_CS_STOP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_SKIN_START, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_SKIN_STOP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_STATS_IHIST_START, VFE_STATS_HISTOGRAM_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_STATS_IHIST_START", "VFE_STATS_HISTOGRAM_CONFIG"},
+	{VFE_CMD_STATS_IHIST_STOP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DUMMY_10, VFE_MAX, VFE_MAX},
+	{VFE_CMD_SYNC_TIMER_SETTING, VFE_MAX, VFE_MAX},
+	{VFE_CMD_ASYNC_TIMER_SETTING, VFE_MAX, VFE_MAX},
+	{VFE_CMD_LIVESHOT, VFE_MAX, VFE_MAX},
+	{VFE_CMD_LA_SETUP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_LINEARIZATION_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DEMOSAICV3, VFE_DEMOSAICv3_CFG, QDSP_TABLEQUEUE,
+		"VFE_CMD_DEMOSAICV3", "VFE_DEMOSAICv3_CFG"},
+	{VFE_CMD_DEMOSAICV3_ABCC_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DEMOSAICV3_DBCC_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DEMOSAICV3_DBPC_CFG, VFE_DEMOSAICv3_BPC_CFG, QDSP_TABLEQUEUE,
+		"VFE_CMD_DEMOSAICV3_DBPC_CFG", "VFE_DEMOSAICv3_BPC_CFG"},
+	{VFE_CMD_DEMOSAICV3_ABF_CFG, VFE_DEMOSAICv3_ABF_CFG, QDSP_TABLEQUEUE,
+		"VFE_CMD_DEMOSAICV3_ABF_CFG", "VFE_DEMOSAICv3_ABF_CFG"},
+	{VFE_CMD_DEMOSAICV3_ABCC_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DEMOSAICV3_DBCC_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DEMOSAICV3_DBPC_UPDATE, VFE_DEMOSAICv3_BPC_UPDATE,
+		QDSP_CMDQUEUE, "VFE_CMD_DEMOSAICV3_DBPC_UPDATE",
+		"VFE_DEMOSAICv3_BPC_UPDATE"},
+	{VFE_CMD_XBAR_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_MODULE_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_ZSL, VFE_MAX, VFE_MAX},
+	{VFE_CMD_LINEARIZATION_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DEMOSAICV3_ABF_UPDATE, VFE_DEMOSAICv3_ABF_CFG,
+		QDSP_TABLEQUEUE, "VFE_CMD_DEMOSAICV3_ABF_UPDATE",
+		"VFE_DEMOSAICv3_ABF_CFG"},
+	{VFE_CMD_CLF_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CLF_LUMA_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_CLF_CHROMA_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_PCA_ROLL_OFF_CFG, VFE_MAX, VFE_MAX},
+	{VFE_CMD_PCA_ROLL_OFF_UPDATE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_GET_REG_DUMP, VFE_MAX, VFE_MAX},
+	{VFE_CMD_GET_LINEARIZATON_TABLE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_GET_MESH_ROLLOFF_TABLE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_GET_PCA_ROLLOFF_TABLE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_GET_RGB_G_TABLE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_GET_LA_TABLE, VFE_MAX, VFE_MAX},
+	{VFE_CMD_DEMOSAICV3_UPDATE, VFE_DEMOSAICv3_CFG, QDSP_TABLEQUEUE,
+		"VFE_CMD_DEMOSAICV3_UPDATE", "VFE_DEMOSAICv3_CFG"},
+	{VFE_CMD_ACTIVE_REGION_CFG, VFE_ACTIVE_REGION_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_ACTIVE_REGION_CFG", "VFE_ACTIVE_REGION_CONFIG"},
+	{VFE_CMD_COLOR_PROCESSING_CONFIG, VFE_COLOR_PROCESSING_CONFIG,
+		QDSP_CMDQUEUE, "VFE_CMD_COLOR_PROCESSING_CONFIG",
+		"VFE_COLOR_PROCESSING_CONFIG"},
+	{VFE_CMD_STATS_WB_AEC_CONFIG, VFE_STATS_WB_EXP_CONFIG, QDSP_CMDQUEUE,
+		"VFE_CMD_STATS_WB_AEC_CONFIG", "VFE_STATS_WB_EXP_CONFIG"},
+	{VFE_CMD_STATS_WB_AEC_UPDATE, VFE_STATS_WB_EXP_UPDATE, QDSP_CMDQUEUE,
+		"VFE_CMD_STATS_WB_AEC_UPDATE", "VFE_STATS_WB_EXP_UPDATE"},
+	{VFE_CMD_Y_GAMMA_CONFIG, VFE_Y_GAMMA_CONFIG, QDSP_TABLEQUEUE,
+		"VFE_CMD_Y_GAMMA_CONFIG", "VFE_Y_GAMMA_CONFIG"},
+	{VFE_CMD_SCALE_OUTPUT1_CONFIG, VFE_SCALE_OUTPUT1_CONFIG,
+		QDSP_SCALEQUEUE, "VFE_CMD_SCALE_OUTPUT1_CONFIG",
+		"VFE_SCALE_OUTPUT1_CONFIG"},
+	{VFE_CMD_SCALE_OUTPUT2_CONFIG, VFE_SCALE_OUTPUT2_CONFIG,
+		QDSP_SCALEQUEUE, "VFE_CMD_SCALE_OUTPUT2_CONFIG",
+		"VFE_SCALE_OUTPUT2_CONFIG"},
+};
+
+
+static struct msm_adsp_module *qcam_mod;
+static struct msm_adsp_module *vfe_mod;
+static void *extdata;
+static uint32_t extlen;
+
+struct mutex vfe_lock;
+static void     *vfe_syncdata;
+static uint8_t vfestopped;
+
+static struct stop_event stopevent;
+
+static uint32_t op_mode;
+static uint32_t raw_mode;
+static struct vfe2x_ctrl_type *vfe2x_ctrl;
+
+static void vfe2x_send_isp_msg(
+	struct vfe2x_ctrl_type *vctrl,
+	uint32_t isp_msg_id)
+{
+	struct isp_msg_event isp_msg_evt;
+
+	isp_msg_evt.msg_id = isp_msg_id;
+	isp_msg_evt.sof_count = vfe2x_ctrl->vfeFrameId;
+	v4l2_subdev_notify(&vctrl->subdev,
+			NOTIFY_ISP_MSG_EVT,
+			(void *)&isp_msg_evt);
+}
+
+static void vfe_send_outmsg(struct v4l2_subdev *sd, uint8_t msgid,
+		uint32_t ch0_paddr, uint32_t ch1_paddr)
+{
+	struct isp_msg_output msg;
+
+	msg.output_id = msgid;
+	msg.buf.ch_paddr[0]     = ch0_paddr;
+	msg.buf.ch_paddr[1]     = ch1_paddr;
+	msg.frameCounter = vfe2x_ctrl->vfeFrameId;
+
+	v4l2_subdev_notify(&vfe2x_ctrl->subdev,
+			NOTIFY_VFE_MSG_OUT,
+			&msg);
+	return;
+}
+
+static void vfe_send_stats_msg(uint32_t buf_addr, uint32_t msg_id)
+{
+	struct isp_msg_stats msg_stats;
+
+	msg_stats.frameCounter = vfe2x_ctrl->vfeFrameId;
+	msg_stats.buffer       = buf_addr;
+	msg_stats.id           = msg_id;
+
+	v4l2_subdev_notify(&vfe2x_ctrl->subdev,
+				NOTIFY_VFE_MSG_STATS,
+				&msg_stats);
+}
+
+static void vfe_7x_ops(void *driver_data, unsigned id, size_t len,
+		void (*getevent)(void *ptr, size_t len))
+{
+	uint32_t evt_buf[3];
+	void *data;
+	struct buf_info *outch = NULL;
+	uint32_t y_phy, cbcr_phy;
+	struct table_cmd *table_pending = NULL;
+	unsigned long flags;
+	void   *cmd_data = NULL;
+	unsigned char buf[256];
+	struct msm_free_buf *free_buf = NULL;
+	struct vfe_outputack fack;
+
+	CDBG("%s:id=%d\n", __func__, id);
+
+	if (id != VFE_ADSP_EVENT) {
+		data = kzalloc(len, GFP_KERNEL);
+		if (!data) {
+			pr_err("%s: rp: cannot allocate buffer\n", __func__);
+			return;
+		}
+	}
+	if (id == VFE_ADSP_EVENT) {
+		/* event */
+		getevent(evt_buf, sizeof(evt_buf));
+		CDBG("%s:event:msg_id=%d\n", __func__, id);
+	} else {
+		/* messages */
+		getevent(data, len);
+		CDBG("%s:messages:msg_id=%d\n", __func__, id);
+
+		switch (id) {
+		case MSG_SNAPSHOT:
+			msm_camio_set_perf_lvl(S_PREVIEW);
+			vfe_7x_ops(driver_data, MSG_OUTPUT_S, len, getevent);
+			if (!raw_mode)
+				vfe_7x_ops(driver_data, MSG_OUTPUT_T,
+						len, getevent);
+			vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_SNAPSHOT_DONE);
+			return;
+		case MSG_OUTPUT_S:
+			outch = &vfe2x_ctrl->snap;
+			y_phy = outch->ping.ch_paddr[0];
+			cbcr_phy = outch->ping.ch_paddr[1];
+			CDBG("MSG_OUTPUT_S: %x %x\n",
+				(unsigned int)y_phy, (unsigned int)cbcr_phy);
+			vfe_send_outmsg(&vfe2x_ctrl->subdev, MSG_ID_OUTPUT_S,
+							y_phy, cbcr_phy);
+			break;
+		case MSG_OUTPUT_T:
+			outch = &vfe2x_ctrl->thumb;
+			y_phy = outch->ping.ch_paddr[0];
+			cbcr_phy = outch->ping.ch_paddr[1];
+			CDBG("MSG_OUTPUT_T: %x %x\n",
+				(unsigned int)y_phy, (unsigned int)cbcr_phy);
+			vfe_send_outmsg(&vfe2x_ctrl->subdev, MSG_ID_OUTPUT_T,
+							y_phy, cbcr_phy);
+			break;
+		case MSG_OUTPUT1:
+		case MSG_OUTPUT2:
+			if (op_mode & SNAPSHOT_MASK_MODE) {
+				kfree(data);
+				return;
+			} else {
+				free_buf = vfe2x_check_free_buffer(
+					VFE_MSG_OUTPUT_IRQ,
+					VFE_MSG_OUTPUT_P);
+			      CDBG("free_buf = %x\n", (unsigned int) free_buf);
+			      if (free_buf) {
+					fack.header = VFE_OUTPUT2_ACK;
+
+					fack.output2newybufferaddress =
+						(void *)(free_buf->ch_paddr[0]);
+
+					fack.output2newcbcrbufferaddress =
+						(void *)(free_buf->ch_paddr[1]);
+
+					cmd_data = &fack;
+					len = sizeof(fack);
+					msm_adsp_write(vfe_mod, QDSP_CMDQUEUE,
+							cmd_data, len);
+			      } else {
+					fack.header = VFE_OUTPUT2_ACK;
+					fack.output2newybufferaddress =
+					(void *)
+				((struct vfe_endframe *)data)->y_address;
+					fack.output2newcbcrbufferaddress =
+					(void *)
+				((struct vfe_endframe *)data)->cbcr_address;
+					cmd_data = &fack;
+					len = sizeof(fack);
+					msm_adsp_write(vfe_mod, QDSP_CMDQUEUE,
+						cmd_data, len);
+				}
+			}
+			y_phy = ((struct vfe_endframe *)data)->y_address;
+			cbcr_phy = ((struct vfe_endframe *)data)->cbcr_address;
+
+
+			CDBG("vfe_7x_convert, y_phy = 0x%x, cbcr_phy = 0x%x\n",
+				 y_phy, cbcr_phy);
+
+			memcpy(((struct vfe_frame_extra *)extdata),
+				&((struct vfe_endframe *)data)->extra,
+				sizeof(struct vfe_frame_extra));
+
+			vfe2x_ctrl->vfeFrameId =
+				((struct vfe_frame_extra *)extdata)->frame_id;
+			vfe_send_outmsg(&vfe2x_ctrl->subdev,
+							MSG_ID_OUTPUT_P,
+							y_phy, cbcr_phy);
+			break;
+		case MSG_RESET_ACK:
+		case MSG_START_ACK:
+		case MSG_UPDATE_ACK:
+		case MSG_VFE_ERROR:
+		case MSG_SYNC_TIMER1_DONE:
+		case MSG_SYNC_TIMER2_DONE:
+			vfe2x_send_isp_msg(vfe2x_ctrl, msgs_map[id].isp_id);
+			if (id == MSG_START_ACK)
+				vfe2x_ctrl->vfe_started = 1;
+			break;
+		case MSG_SOF:
+			vfe2x_ctrl->vfeFrameId++;
+			if (vfe2x_ctrl->vfeFrameId == 0)
+				vfe2x_ctrl->vfeFrameId = 1; /* wrapped back */
+			vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_SOF_ACK);
+			if (raw_mode)
+				vfe2x_send_isp_msg(vfe2x_ctrl,
+						MSG_ID_START_ACK);
+			break;
+		case MSG_STOP_ACK:
+			stopevent.state = 1;
+			vfe2x_ctrl->vfe_started = 0;
+			wake_up(&stopevent.wait);
+			vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_STOP_ACK);
+			break;
+		case MSG_STATS_AF:
+		case MSG_STATS_WE:
+			vfe_send_stats_msg(*(uint32_t *)data,
+						msgs_map[id].isp_id);
+			break;
+		default:
+			vfe2x_send_isp_msg(vfe2x_ctrl, msgs_map[id].isp_id);
+			break;
+		}
+	}
+	if (MSG_TABLE_CMD_ACK == id) {
+		spin_lock_irqsave(&vfe2x_ctrl->table_lock, flags);
+		if (list_empty(&vfe2x_ctrl->table_q)) {
+			if (vfe2x_ctrl->start_pending) {
+				CDBG("Send START\n");
+				cmd_data = buf;
+				*(uint32_t *)cmd_data = VFE_START;
+				memcpy(((char *)cmd_data) + 4,
+					&vfe2x_ctrl->start_cmd,
+					sizeof(vfe2x_ctrl->start_cmd));
+				/* Send Start cmd here */
+				len  = sizeof(vfe2x_ctrl->start_cmd) + 4;
+				msm_adsp_write(vfe_mod, QDSP_CMDQUEUE,
+						cmd_data, len);
+				vfe2x_ctrl->start_pending = 0;
+			}
+			vfe2x_ctrl->tableack_pending = 0;
+			spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
+			return;
+		}
+		table_pending = list_first_entry(&vfe2x_ctrl->table_q,
+					struct table_cmd, list);
+		if (!table_pending) {
+			vfe2x_ctrl->tableack_pending = 0;
+			spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
+			return;
+		}
+		msm_adsp_write(vfe_mod, table_pending->queue,
+				table_pending->cmd, table_pending->size);
+		list_del(&table_pending->list);
+		kfree(table_pending->cmd);
+		vfe2x_ctrl->tableack_pending = 1;
+		spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
+	} else if (!vfe2x_ctrl->tableack_pending) {
+		if (!list_empty(&vfe2x_ctrl->table_q))
+			return;
+	}
+}
+
+static struct msm_adsp_ops vfe_7x_sync = {
+	.event = vfe_7x_ops,
+};
+
+static int vfe_7x_config_axi(int mode,
+	struct buf_info *ad, struct axiout *ao)
+{
+	unsigned long *bptr;
+	int    cnt;
+	int rc = 0;
+
+
+	if (mode == OUTPUT_1) {
+		ao->output1buffer1_y_phy = ad->ping.ch_paddr[0];
+		ao->output1buffer1_cbcr_phy = ad->ping.ch_paddr[1];
+		ao->output1buffer2_y_phy = ad->pong.ch_paddr[0];
+		ao->output1buffer2_cbcr_phy = ad->pong.ch_paddr[1];
+		bptr = &ao->output1buffer3_y_phy;
+		for (cnt = 0; cnt < 6; cnt++) {
+			*bptr = ad->pong.ch_paddr[0];
+			bptr++;
+			*bptr = ad->pong.ch_paddr[1];
+			bptr++;
+		}
+	}
+
+	if (mode == OUTPUT_2) {
+		ao->output2buffer1_y_phy = ad->ping.ch_paddr[0];
+		ao->output2buffer1_cbcr_phy = ad->ping.ch_paddr[1];
+		ao->output2buffer2_y_phy = ad->pong.ch_paddr[0];
+		ao->output2buffer2_cbcr_phy = ad->pong.ch_paddr[1];
+		ao->output2buffer3_y_phy = ad->free_buf.ch_paddr[0];
+		ao->output2buffer3_cbcr_phy = ad->free_buf.ch_paddr[1];
+		bptr = &ao->output2buffer4_y_phy;
+		for (cnt = 0; cnt < 5; cnt++) {
+			*bptr = ad->pong.ch_paddr[0];
+			bptr++;
+			*bptr = ad->pong.ch_paddr[1];
+			bptr++;
+		}
+	}
+
+	if (mode == OUTPUT_1_AND_2) {
+		if (raw_mode) {
+			ao->output2buffer1_y_phy = ad->ping.ch_paddr[0];
+			ao->output2buffer1_cbcr_phy = ad->ping.ch_paddr[0];
+			ao->output2buffer2_y_phy = ad->pong.ch_paddr[0];
+			ao->output2buffer2_cbcr_phy = ad->pong.ch_paddr[0];
+		} else {
+			ao->output2buffer1_y_phy = ad->ping.ch_paddr[0];
+			ao->output2buffer1_cbcr_phy = ad->ping.ch_paddr[1];
+			ao->output2buffer2_y_phy = ad->pong.ch_paddr[0];
+			ao->output2buffer2_cbcr_phy = ad->pong.ch_paddr[1];
+	}
+		bptr = &ao->output2buffer3_y_phy;
+		for (cnt = 0; cnt < 6; cnt++) {
+			*bptr = ad->pong.ch_paddr[0];
+			bptr++;
+			*bptr = ad->pong.ch_paddr[0];
+			bptr++;
+		}
+	}
+
+	return rc;
+}
+
+static void vfe2x_subdev_notify(int id, int path)
+{
+	struct msm_vfe_resp *rp;
+	unsigned long flags = 0;
+	spin_lock_irqsave(&vfe2x_ctrl->sd_notify_lock, flags);
+	rp = msm_isp_sync_alloc(sizeof(struct msm_vfe_resp), GFP_ATOMIC);
+	if (!rp) {
+		CDBG("rp: cannot allocate buffer\n");
+		return;
+	}
+	CDBG("vfe2x_subdev_notify : msgId = %d\n", id);
+	rp->evt_msg.type   = MSM_CAMERA_MSG;
+	rp->evt_msg.msg_id = path;
+	rp->type	   = id;
+	v4l2_subdev_notify(&vfe2x_ctrl->subdev, NOTIFY_VFE_BUF_EVT, rp);
+	spin_unlock_irqrestore(&vfe2x_ctrl->sd_notify_lock, flags);
+}
+
+static struct msm_free_buf *vfe2x_check_free_buffer(int id, int path)
+{
+	struct buf_info *outch = NULL;
+
+	vfe2x_subdev_notify(id, path);
+	if (op_mode & SNAPSHOT_MASK_MODE) {
+		if (path == VFE_MSG_OUTPUT_S)
+			outch = &vfe2x_ctrl->snap;
+		else if (path == VFE_MSG_OUTPUT_T)
+			outch = &vfe2x_ctrl->thumb;
+	} else {
+		if (path == VFE_MSG_OUTPUT_P)
+			outch = &vfe2x_ctrl->prev;
+	}
+	if (outch->free_buf.ch_paddr[0])
+		return &outch->free_buf;
+
+	return NULL;
+}
+
+static int vfe2x_configure_pingpong_buffers(int id, int path)
+{
+	struct buf_info *outch = NULL;
+	int rc = 0;
+
+	vfe2x_subdev_notify(id, path);
+
+	CDBG("Opmode = %d\n", op_mode);
+	if (op_mode & SNAPSHOT_MASK_MODE) {
+		if (path == VFE_MSG_OUTPUT_S)
+			outch = &vfe2x_ctrl->snap;
+		else if (path == VFE_MSG_OUTPUT_T)
+			outch = &vfe2x_ctrl->thumb;
+	} else {
+		if (path == VFE_MSG_OUTPUT_P)
+			outch = &vfe2x_ctrl->prev;
+	}
+	if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
+		/* Configure Preview Ping Pong */
+		CDBG("%s Configure ping/pong address for %d",
+						__func__, path);
+	} else {
+		pr_err("%s ping/pong addr is null!!", __func__);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+static struct buf_info *vfe2x_get_ch(int path)
+{
+	struct buf_info *ch = NULL;
+
+	CDBG("path = %d op_mode = %d\n", path, op_mode);
+	if (op_mode & SNAPSHOT_MASK_MODE) {
+		if (path == VFE_MSG_OUTPUT_T)
+			ch = &vfe2x_ctrl->thumb;
+		else if (path == VFE_MSG_OUTPUT_S)
+			ch = &vfe2x_ctrl->snap;
+	} else {
+		if (path == VFE_MSG_OUTPUT_P)
+			ch = &vfe2x_ctrl->prev;
+	}
+
+	BUG_ON(ch == NULL);
+	return ch;
+}
+
+static long msm_vfe_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int subdev_cmd, void *arg)
+{
+	struct msm_isp_cmd vfecmd;
+	struct msm_camvfe_params *vfe_params =
+		(struct msm_camvfe_params *)arg;
+	struct msm_vfe_cfg_cmd *cmd = vfe_params->vfe_cfg;
+	struct table_cmd *table_pending;
+	long rc = 0;
+	void *data = vfe_params->data;
+
+	struct msm_pmem_region *regptr;
+	unsigned char buf[256];
+
+	struct vfe_stats_ack sack;
+	struct axidata *axid;
+	uint32_t i;
+	uint32_t header = 0;
+	uint32_t queue = 0;
+	struct vfe_stats_we_cfg *scfg = NULL;
+	struct vfe_stats_af_cfg *sfcfg = NULL;
+
+	struct axiout *axio = NULL;
+	void   *cmd_data = NULL;
+	void   *cmd_data_alloc = NULL;
+	unsigned long flags;
+	struct msm_free_buf *free_buf = NULL;
+	struct vfe_outputack fack;
+
+	CDBG("msm_vfe_subdev_ioctl is called\n");
+	if (cmd->cmd_type != CMD_FRAME_BUF_RELEASE &&
+	    cmd->cmd_type != CMD_STATS_BUF_RELEASE &&
+	    cmd->cmd_type != CMD_STATS_AF_BUF_RELEASE &&
+		cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
+		cmd->cmd_type != CMD_CONFIG_PONG_ADDR &&
+		cmd->cmd_type != CMD_CONFIG_FREE_BUF_ADDR &&
+		cmd->cmd_type != CMD_VFE_BUFFER_RELEASE) {
+		if (copy_from_user(&vfecmd,
+				(void __user *)(cmd->value),
+				sizeof(vfecmd))) {
+			pr_err("copy_from_user in msm_vfe_subdev_ioctl fail\n");
+			return -EFAULT;
+		}
+	}
+
+	switch (cmd->cmd_type) {
+	case CMD_VFE_BUFFER_RELEASE: {
+		if (!(vfe2x_ctrl->vfe_started) || op_mode == 1)
+			return 0;
+		if (op_mode & SNAPSHOT_MASK_MODE) {
+			free_buf = vfe2x_check_free_buffer(
+					VFE_MSG_OUTPUT_IRQ,
+					VFE_MSG_OUTPUT_T);
+		} else {
+			free_buf = vfe2x_check_free_buffer(
+					VFE_MSG_OUTPUT_IRQ,
+					VFE_MSG_OUTPUT_P);
+			if (free_buf) {
+				fack.header = VFE_OUTPUT2_ACK;
+
+				fack.output2newybufferaddress =
+						(void *)(free_buf->ch_paddr[0]);
+
+				fack.output2newcbcrbufferaddress =
+						(void *)(free_buf->ch_paddr[1]);
+
+				cmd_data = &fack;
+				vfecmd.length = sizeof(fack) - 4;
+				queue = QDSP_CMDQUEUE;
+			}
+		}
+	}
+	break;
+	case CMD_CONFIG_PING_ADDR: {
+		int path = *((int *)cmd->value);
+		struct buf_info *outch = vfe2x_get_ch(path);
+		outch->ping = *((struct msm_free_buf *)data);
+	}
+		return 0;
+	case CMD_CONFIG_PONG_ADDR: {
+		int path = *((int *)cmd->value);
+		struct buf_info *outch = vfe2x_get_ch(path);
+		outch->pong = *((struct msm_free_buf *)data);
+	}
+		return 0;
+
+	case CMD_CONFIG_FREE_BUF_ADDR: {
+		int path = *((int *)cmd->value);
+		struct buf_info *outch = vfe2x_get_ch(path);
+		outch->free_buf = *((struct msm_free_buf *)data);
+	}
+		return 0;
+
+	case CMD_STATS_AEC_AWB_ENABLE:
+	case CMD_STATS_AXI_CFG: {
+		axid = data;
+		if (!axid) {
+			rc = -EFAULT;
+			goto config_failure;
+		}
+
+		scfg =
+			kmalloc(sizeof(struct vfe_stats_we_cfg),
+				GFP_ATOMIC);
+		if (!scfg) {
+			rc = -ENOMEM;
+			goto config_failure;
+		}
+
+		if (copy_from_user((char *)scfg + 4,
+					(void __user *)(vfecmd.value),
+					vfecmd.length)) {
+
+			rc = -EFAULT;
+			goto config_done;
+		}
+
+		CDBG("STATS_ENABLE: bufnum = %d, enabling = %d\n",
+			axid->bufnum1, scfg->wb_expstatsenable);
+
+		header = cmds_map[vfecmd.id].vfe_id;
+		queue = cmds_map[vfecmd.id].queue;
+		if (header == -1 && queue == -1) {
+			rc = -EFAULT;
+			goto config_failure;
+		}
+		*(uint32_t *)scfg = header;
+		if (axid->bufnum1 > 0) {
+			regptr = axid->region;
+
+			for (i = 0; i < axid->bufnum1; i++) {
+
+				CDBG("STATS_ENABLE, phy = 0x%lx\n",
+					regptr->paddr);
+
+				scfg->wb_expstatoutputbuffer[i] =
+					(void *)regptr->paddr;
+				regptr++;
+			}
+
+			cmd_data = scfg;
+
+		} else {
+			rc = -EINVAL;
+			goto config_done;
+		}
+	}
+		break;
+	case CMD_STATS_AF_ENABLE:
+	case CMD_STATS_AF_AXI_CFG: {
+		axid = data;
+		if (!axid) {
+			rc = -EFAULT;
+			goto config_failure;
+		}
+
+		sfcfg =
+			kmalloc(sizeof(struct vfe_stats_af_cfg),
+				GFP_ATOMIC);
+
+		if (!sfcfg) {
+			rc = -ENOMEM;
+			goto config_failure;
+		}
+
+		if (copy_from_user((char *)sfcfg + 4,
+					(void __user *)(vfecmd.value),
+					vfecmd.length)) {
+
+			rc = -EFAULT;
+			goto config_done;
+		}
+
+		CDBG("AF_ENABLE: bufnum = %d, enabling = %d\n",
+			axid->bufnum1, sfcfg->af_enable);
+
+		header = cmds_map[vfecmd.id].vfe_id;
+		queue = cmds_map[vfecmd.id].queue;
+		if (header == -1 && queue == -1) {
+			rc = -EFAULT;
+			goto config_failure;
+		}
+		*(uint32_t *)sfcfg = header;
+		if (axid->bufnum1 > 0) {
+			regptr = &axid->region[0];
+
+			for (i = 0; i < axid->bufnum1; i++) {
+
+				CDBG("STATS_ENABLE, phy = 0x%lx\n",
+					regptr->paddr);
+
+				sfcfg->af_outbuf[i] =
+					(void *)regptr->paddr;
+
+				regptr++;
+			}
+
+			cmd_data = sfcfg;
+
+		} else {
+			rc = -EINVAL;
+			goto config_done;
+		}
+	}
+		break;
+	case CMD_SNAP_BUF_RELEASE:
+		break;
+	case CMD_STATS_BUF_RELEASE: {
+		CDBG("vfe_7x_config: CMD_STATS_BUF_RELEASE\n");
+		if (!data) {
+			rc = -EFAULT;
+			goto config_failure;
+		}
+
+		sack.header = VFE_STATS_WB_EXP_ACK;
+		sack.bufaddr = (void *)*(uint32_t *)data;
+
+		queue  = QDSP_CMDQUEUE;
+		vfecmd.length = sizeof(struct vfe_stats_ack) - 4;
+		cmd_data = &sack;
+	}
+		break;
+	case CMD_STATS_AF_BUF_RELEASE: {
+		CDBG("vfe_7x_config: CMD_STATS_AF_BUF_RELEASE\n");
+		if (!data) {
+			rc = -EFAULT;
+			goto config_failure;
+		}
+
+		sack.header = VFE_STATS_AUTOFOCUS_ACK;
+		sack.bufaddr = (void *)*(uint32_t *)data;
+
+		queue  = QDSP_CMDQUEUE;
+		vfecmd.length = sizeof(struct vfe_stats_ack) - 4;
+		cmd_data = &sack;
+	}
+		break;
+	case CMD_GENERAL:
+	case CMD_STATS_DISABLE: {
+		CDBG("CMD_GENERAL:%d %d\n", vfecmd.id, vfecmd.length);
+		if (vfecmd.id == VFE_CMD_OPERATION_CFG) {
+			if (copy_from_user(&vfe2x_ctrl->start_cmd,
+						(void __user *)(vfecmd.value),
+							vfecmd.length))
+				rc = -EFAULT;
+			op_mode = vfe2x_ctrl->start_cmd.mode_of_operation;
+			return rc;
+		}
+		if (vfecmd.length > 256 - 4) {
+			cmd_data_alloc =
+			cmd_data = kmalloc(vfecmd.length + 4, GFP_ATOMIC);
+			if (!cmd_data) {
+				rc = -ENOMEM;
+				goto config_failure;
+			}
+		} else
+			cmd_data = buf;
+
+		if (copy_from_user(((char *)cmd_data) + 4,
+					(void __user *)(vfecmd.value),
+					vfecmd.length)) {
+
+			rc = -EFAULT;
+			goto config_done;
+		}
+		header = cmds_map[vfecmd.id].vfe_id;
+		queue = cmds_map[vfecmd.id].queue;
+		if (header == -1 && queue == -1) {
+			rc = -EFAULT;
+			goto config_done;
+		}
+		CDBG("%s %s\n", cmds_map[vfecmd.id].isp_id_name,
+			cmds_map[vfecmd.id].vfe_id_name);
+		*(uint32_t *)cmd_data = header;
+		if (queue == QDSP_CMDQUEUE) {
+			switch (vfecmd.id) {
+			case VFE_CMD_RESET:
+				msm_adsp_enable(qcam_mod);
+				msm_adsp_enable(vfe_mod);
+				msm_camio_vfe_blk_reset();
+				vfestopped = 0;
+				break;
+			case VFE_CMD_START:
+			case VFE_CMD_CAPTURE:
+				spin_lock_irqsave(&vfe2x_ctrl->table_lock,
+									flags);
+				if (!list_empty(&vfe2x_ctrl->table_q)) {
+					vfe2x_ctrl->start_pending = 1;
+					spin_unlock_irqrestore(
+						&vfe2x_ctrl->table_lock,
+								flags);
+					return 0;
+				}
+				spin_unlock_irqrestore(&vfe2x_ctrl->table_lock,
+									flags);
+				vfecmd.length = sizeof(vfe2x_ctrl->start_cmd);
+				memcpy(((char *)cmd_data) + 4,
+					&vfe2x_ctrl->start_cmd,
+					sizeof(vfe2x_ctrl->start_cmd));
+				if (op_mode & SNAPSHOT_MASK_MODE)
+					msm_camio_set_perf_lvl(S_CAPTURE);
+				else
+					msm_camio_set_perf_lvl(S_PREVIEW);
+				vfestopped = 0;
+				break;
+			case VFE_CMD_STOP:
+				vfestopped = 1;
+				vfe2x_ctrl->vfe_started = 0;
+				goto config_send;
+
+			default:
+				break;
+			}
+		} /* QDSP_CMDQUEUE */
+	}
+		break;
+	case CMD_AXI_CFG_PREVIEW: {
+		CDBG("CMD_AXI_CFG_PREVIEW\n");
+		raw_mode = 0;
+		axio = kmalloc(sizeof(struct axiout), GFP_ATOMIC);
+		if (!axio) {
+			pr_err("NULL axio\n");
+			rc = -ENOMEM;
+			goto config_failure;
+		}
+
+		if (copy_from_user((char *)axio + 4,
+					(void __user *)(vfecmd.value),
+					sizeof(struct axiout))) {
+			pr_err("copy_from_user failed\n");
+			rc = -EFAULT;
+			goto config_done;
+		}
+		rc = vfe2x_configure_pingpong_buffers(VFE_MSG_V2X_PREVIEW,
+							VFE_MSG_OUTPUT_P);
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers"
+				" for preview", __func__);
+			rc = -EINVAL;
+			goto config_done;
+		}
+
+		free_buf = vfe2x_check_free_buffer(
+					VFE_MSG_OUTPUT_IRQ,
+					VFE_MSG_OUTPUT_P);
+		header = cmds_map[vfecmd.id].vfe_id;
+		queue = cmds_map[vfecmd.id].queue;
+		if (header == -1 && queue == -1) {
+			rc = -EFAULT;
+			goto config_done;
+		}
+		*(uint32_t *)axio = header;
+		vfe_7x_config_axi(OUTPUT_2, &vfe2x_ctrl->prev, axio);
+		cmd_data = axio;
+	}
+		break;
+	case CMD_RAW_PICT_AXI_CFG: {
+		CDBG("CMD_RAW_PICT_AXI_CFG:%d\n", op_mode);
+		raw_mode = 1;
+		axio = kmalloc(sizeof(struct axiout), GFP_ATOMIC);
+		if (!axio) {
+			rc = -ENOMEM;
+			goto config_failure;
+		}
+
+		if (copy_from_user((char *)axio + 4,
+					(void __user *)(vfecmd.value),
+					sizeof(struct axiout))) {
+			rc = -EFAULT;
+			goto config_done;
+		}
+		header = cmds_map[vfecmd.id].vfe_id;
+		queue = cmds_map[vfecmd.id].queue;
+		rc = vfe2x_configure_pingpong_buffers(VFE_MSG_V2X_CAPTURE,
+							VFE_MSG_OUTPUT_S);
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers"
+				" for preview", __func__);
+			rc = -EINVAL;
+			goto config_done;
+		}
+		if (header == -1 && queue == -1) {
+			rc = -EFAULT;
+			goto config_done;
+		}
+		*(uint32_t *)axio = header;
+		vfe_7x_config_axi(OUTPUT_1_AND_2, &vfe2x_ctrl->snap, axio);
+		cmd_data = axio;
+	}
+		break;
+	case CMD_AXI_CFG_SNAP: {
+		raw_mode = 0;
+		CDBG("CMD_AXI_CFG_SNAP :%d\n", op_mode);
+		axio = kmalloc(sizeof(struct axiout), GFP_ATOMIC);
+		if (!axio) {
+			rc = -ENOMEM;
+			goto config_failure;
+		}
+
+		if (copy_from_user((char *)axio + 4,
+					(void __user *)(vfecmd.value),
+					sizeof(struct axiout))) {
+			rc = -EFAULT;
+			goto config_done;
+		}
+		header = cmds_map[vfecmd.id].vfe_id;
+		queue = cmds_map[vfecmd.id].queue;
+		rc = vfe2x_configure_pingpong_buffers(VFE_MSG_V2X_CAPTURE,
+							VFE_MSG_OUTPUT_S);
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers"
+				" for preview", __func__);
+			rc = -EINVAL;
+			goto config_done;
+		}
+		if (header == -1 && queue == -1) {
+			rc = -EFAULT;
+			goto config_done;
+		}
+		*(uint32_t *)axio = header;
+		vfe_7x_config_axi(OUTPUT_1_AND_2, &vfe2x_ctrl->snap, axio);
+		rc = vfe2x_configure_pingpong_buffers(VFE_MSG_V2X_CAPTURE,
+							VFE_MSG_OUTPUT_T);
+		if (rc < 0) {
+			pr_err("%s error configuring pingpong buffers"
+				" for preview", __func__);
+			rc = -EINVAL;
+			goto config_done;
+		}
+		vfe_7x_config_axi(OUTPUT_1, &vfe2x_ctrl->thumb, axio);
+		cmd_data = axio;
+	}
+		break;
+	default:
+		break;
+	}
+
+	if (vfestopped)
+		goto config_done;
+
+config_send:
+	CDBG("send adsp command = %d\n", *(uint32_t *)cmd_data);
+	if (queue == QDSP_TABLEQUEUE &&
+			vfe2x_ctrl->tableack_pending) {
+		table_pending = kzalloc(sizeof(struct table_cmd), GFP_ATOMIC);
+		if (!table_pending) {
+			rc = -ENOMEM;
+			goto config_done;
+		}
+		table_pending->cmd = kzalloc(vfecmd.length + 4, GFP_ATOMIC);
+		if (!table_pending->cmd) {
+			kfree(table_pending);
+			rc = -ENOMEM;
+			goto config_done;
+		}
+		memcpy(table_pending->cmd, cmd_data, vfecmd.length + 4);
+		table_pending->queue = queue;
+		table_pending->size = vfecmd.length + 4;
+		spin_lock_irqsave(&vfe2x_ctrl->table_lock, flags);
+		list_add_tail(&table_pending->list, &vfe2x_ctrl->table_q);
+		spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
+	} else {
+		if (queue == QDSP_TABLEQUEUE) {
+			spin_lock_irqsave(&vfe2x_ctrl->table_lock, flags);
+			rc = msm_adsp_write(vfe_mod, queue,
+				cmd_data, vfecmd.length + 4);
+			vfe2x_ctrl->tableack_pending = 1;
+			spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
+		} else {
+			if (*(uint32_t *)cmd_data == VFE_OUTPUT2_ACK) {
+				uint32_t *ptr = cmd_data;
+				CDBG("%x %x %x\n", ptr[0], ptr[1], ptr[2]);
+			}
+			rc = msm_adsp_write(vfe_mod, queue,
+				cmd_data, vfecmd.length + 4);
+			CDBG("%x\n", vfecmd.length + 4);
+		}
+	}
+
+config_done:
+	kfree(cmd_data_alloc);
+
+config_failure:
+	kfree(scfg);
+	kfree(axio);
+	return rc;
+}
+
+static struct msm_cam_clk_info vfe2x_clk_info[] = {
+	{"vfe_clk", 192000000},
+};
+
+int msm_vfe_subdev_init(struct v4l2_subdev *sd, void *data,
+	struct platform_device *pdev)
+{
+	int rc = 0;
+	v4l2_set_subdev_hostdata(sd, data);
+	vfe_syncdata = data;
+
+	spin_lock_init(&vfe2x_ctrl->sd_notify_lock);
+	spin_lock_init(&vfe2x_ctrl->table_lock);
+	spin_lock_init(&vfe2x_ctrl->vfe_msg_lock);
+	init_waitqueue_head(&stopevent.wait);
+	INIT_LIST_HEAD(&vfe2x_ctrl->table_q);
+	INIT_LIST_HEAD(&vfe2x_ctrl->vfe_msg_q);
+	stopevent.timeout = 200;
+	stopevent.state = 0;
+	vfe2x_ctrl->vfe_started = 0;
+
+
+	CDBG("msm_cam_clk_enable: enable vfe_clk\n");
+	rc = msm_cam_clk_enable(&vfe2x_ctrl->pdev->dev, vfe2x_clk_info,
+			vfe2x_ctrl->vfe_clk, ARRAY_SIZE(vfe2x_clk_info), 1);
+	if (rc < 0)
+		return rc;
+
+	msm_camio_set_perf_lvl(S_INIT);
+
+	/* TODO : check is it required */
+	extlen = sizeof(struct vfe_frame_extra);
+
+	extdata = kmalloc(extlen, GFP_ATOMIC);
+	if (!extdata) {
+		rc = -ENOMEM;
+		goto init_fail;
+	}
+
+	rc = msm_adsp_get("QCAMTASK", &qcam_mod, &vfe_7x_sync, NULL);
+	if (rc) {
+		rc = -EBUSY;
+		goto get_qcam_fail;
+	}
+
+	rc = msm_adsp_get("VFETASK", &vfe_mod, &vfe_7x_sync, NULL);
+	if (rc) {
+		rc = -EBUSY;
+		goto get_vfe_fail;
+	}
+	return 0;
+
+get_vfe_fail:
+	msm_adsp_put(qcam_mod);
+get_qcam_fail:
+	kfree(extdata);
+init_fail:
+	extlen = 0;
+	return rc;
+}
+
+int msm_vpe_subdev_init(struct v4l2_subdev *sd, void *data,
+	struct platform_device *pdev)
+{
+	return 0;
+}
+
+void msm_vpe_subdev_release(struct platform_device *pdev)
+{
+	return;
+}
+
+void msm_vfe_subdev_release(struct platform_device *pdev)
+{
+	msm_cam_clk_enable(&vfe2x_ctrl->pdev->dev, vfe2x_clk_info,
+			vfe2x_ctrl->vfe_clk, ARRAY_SIZE(vfe2x_clk_info), 0);
+	vfe_syncdata = NULL;
+
+	msm_adsp_disable(qcam_mod);
+	msm_adsp_disable(vfe_mod);
+
+	msm_adsp_put(qcam_mod);
+	msm_adsp_put(vfe_mod);
+
+	kfree(extdata);
+	msm_camio_set_perf_lvl(S_EXIT);
+	return;
+}
+
+static const struct v4l2_subdev_core_ops msm_vfe_subdev_core_ops = {
+	.ioctl = msm_vfe_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_vfe_subdev_ops = {
+	.core = &msm_vfe_subdev_core_ops,
+};
+
+static int __devinit vfe2x_probe(struct platform_device *pdev)
+{
+	CDBG("%s: device id = %d\n", __func__, pdev->id);
+	vfe2x_ctrl = kzalloc(sizeof(struct vfe2x_ctrl_type), GFP_KERNEL);
+	if (!vfe2x_ctrl) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	v4l2_subdev_init(&vfe2x_ctrl->subdev, &msm_vfe_subdev_ops);
+	snprintf(vfe2x_ctrl->subdev.name,
+			 sizeof(vfe2x_ctrl->subdev.name), "vfe2.x");
+	v4l2_set_subdevdata(&vfe2x_ctrl->subdev, vfe2x_ctrl);
+	platform_set_drvdata(pdev, &vfe2x_ctrl->subdev);
+
+	vfe2x_ctrl->pdev = pdev;
+	return 0;
+}
+
+static struct platform_driver vfe2x_driver = {
+	.probe = vfe2x_probe,
+	.driver = {
+		.name = MSM_VFE_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_vfe2x_init_module(void)
+{
+	return platform_driver_register(&vfe2x_driver);
+}
+
+static void __exit msm_vfe2x_exit_module(void)
+{
+	platform_driver_unregister(&vfe2x_driver);
+}
+
+module_init(msm_vfe2x_init_module);
+module_exit(msm_vfe2x_exit_module);
+MODULE_DESCRIPTION("VFE 2.x driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.h b/drivers/media/video/msm/msm_vfe7x27a_v4l2.h
new file mode 100644
index 0000000..0f7fb60
--- /dev/null
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.h
@@ -0,0 +1,385 @@
+/* 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_VFE7X_H__
+#define __MSM_VFE7X_H__
+#include <media/msm_camera.h>
+#include <mach/camera.h>
+#include <linux/list.h>
+#include "msm.h"
+
+struct cmd_id_map {
+	uint32_t isp_id;
+	uint32_t vfe_id;
+	uint32_t queue;
+	char isp_id_name[64];
+	char vfe_id_name[64];
+} __packed;
+
+struct msg_id_map {
+	uint32_t vfe_id;
+	uint32_t isp_id;
+} __packed;
+
+struct table_cmd {
+	struct list_head list;
+	void *cmd;
+	int size;
+	int queue;
+} __packed;
+
+struct vfe_msg {
+	struct list_head list;
+	void *cmd;
+	int len;
+	int id;
+} __packed;
+
+struct buf_info {
+	/* Buffer */
+	struct msm_free_buf ping;
+	struct msm_free_buf pong;
+	struct msm_free_buf free_buf;
+} __packed;
+
+struct vfe_cmd_start {
+	uint32_t input_source:1;
+	uint32_t mode_of_operation:1;
+	uint32_t snap_number:4;
+	uint32_t /* reserved */ : 26;
+
+	/* Image Pipeline Modules */
+	uint32_t blacklevel_correction_enable:1;
+	uint32_t lens_rolloff_correction_enable:1;
+	uint32_t white_balance_enable:1;
+	uint32_t rgb_gamma_enable:1;
+	uint32_t luma_noise_reductionpath_enable:1;
+	uint32_t adaptive_spatialfilter_enable:1;
+	uint32_t chroma_subsample_enable:1;
+	uint32_t /* reserved */ : 25;
+
+	/* The dimension fed to the statistics module */
+	uint32_t last_pixel:12;
+	uint32_t /* reserved */ : 4;
+	uint32_t last_line:12;
+	uint32_t /* reserved */ : 4;
+} __packed;
+
+struct vfe2x_ctrl_type {
+	struct buf_info prev;
+	struct buf_info snap;
+	struct buf_info raw;
+	struct buf_info thumb;
+
+	spinlock_t  table_lock;
+	struct list_head table_q;
+	uint32_t tableack_pending;
+	uint32_t vfeFrameId;
+
+	spinlock_t vfe_msg_lock;
+	struct list_head vfe_msg_q;
+
+	struct vfe_cmd_start start_cmd;
+	uint32_t start_pending;
+	uint32_t vfe_started;
+
+	/* v4l2 subdev */
+	struct v4l2_subdev subdev;
+	struct platform_device *pdev;
+	struct clk *vfe_clk[3];
+	spinlock_t  sd_notify_lock;
+} __packed;
+
+struct vfe_frame_extra {
+	uint32_t	bl_evencol:23;
+	uint32_t	rvd1:9;
+	uint32_t	bl_oddcol:23;
+	uint32_t	rvd2:9;
+
+	uint32_t	d_dbpc_stats_hot:16;
+	uint32_t	d_dbpc_stats_cold:16;
+
+	uint32_t	d_dbpc_stats_0_hot:10;
+	uint32_t	rvd3:6;
+	uint32_t	d_dbpc_stats_0_cold:10;
+	uint32_t	rvd4:6;
+	uint32_t	d_dbpc_stats_1_hot:10;
+	uint32_t	rvd5:6;
+	uint32_t	d_dbpc_stats_1_cold:10;
+	uint32_t	rvd6:6;
+
+	uint32_t	asf_max_edge;
+
+	uint32_t	e_y_wm_pm_stats_0:21;
+	uint32_t	rvd7:11;
+	uint32_t	e_y_wm_pm_stats_1_bl:8;
+	uint32_t	rvd8:8;
+	uint32_t	e_y_wm_pm_stats_1_nl:12;
+	uint32_t	rvd9:4;
+
+	uint32_t	e_cbcr_wm_pm_stats_0:21;
+	uint32_t	rvd10:11;
+	uint32_t	e_cbcr_wm_pm_stats_1_bl:8;
+	uint32_t	rvd11:8;
+	uint32_t	e_cbcr_wm_pm_stats_1_nl:12;
+	uint32_t	rvd12:4;
+
+	uint32_t	v_y_wm_pm_stats_0:21;
+	uint32_t	rvd13:11;
+	uint32_t	v_y_wm_pm_stats_1_bl:8;
+	uint32_t	rvd14:8;
+	uint32_t	v_y_wm_pm_stats_1_nl:12;
+	uint32_t	rvd15:4;
+
+	uint32_t	v_cbcr_wm_pm_stats_0:21;
+	uint32_t	rvd16:11;
+	uint32_t	v_cbcr_wm_pm_stats_1_bl:8;
+	uint32_t	rvd17:8;
+	uint32_t	v_cbcr_wm_pm_stats_1_nl:12;
+	uint32_t	rvd18:4;
+
+	uint32_t      frame_id;
+} __packed;
+
+struct vfe_endframe {
+	uint32_t      y_address;
+	uint32_t      cbcr_address;
+
+	struct vfe_frame_extra extra;
+} __packed;
+
+struct vfe_outputack {
+	uint32_t  header;
+	void      *output2newybufferaddress;
+	void      *output2newcbcrbufferaddress;
+} __packed;
+
+struct vfe_stats_ack {
+	uint32_t header;
+	/* MUST BE 64 bit ALIGNED */
+	void     *bufaddr;
+} __packed;
+
+/* AXI Output Config Command sent to DSP */
+struct axiout {
+	uint32_t            cmdheader:32;
+	int                 outputmode:3;
+	uint8_t             format:2;
+	uint32_t            /* reserved */ : 27;
+
+	/* AXI Output 1 Y Configuration, Part 1 */
+	uint32_t            out1yimageheight:12;
+	uint32_t            /* reserved */ : 4;
+	uint32_t            out1yimagewidthin64bitwords:10;
+	uint32_t            /* reserved */ : 6;
+
+	/* AXI Output 1 Y Configuration, Part 2 */
+	uint8_t             out1yburstlen:2;
+	uint32_t            out1ynumrows:12;
+	uint32_t            out1yrowincin64bitincs:12;
+	uint32_t            /* reserved */ : 6;
+
+	/* AXI Output 1 CbCr Configuration, Part 1 */
+	uint32_t            out1cbcrimageheight:12;
+	uint32_t            /* reserved */ : 4;
+	uint32_t            out1cbcrimagewidthin64bitwords:10;
+	uint32_t            /* reserved */ : 6;
+
+	/* AXI Output 1 CbCr Configuration, Part 2 */
+	uint8_t             out1cbcrburstlen:2;
+	uint32_t            out1cbcrnumrows:12;
+	uint32_t            out1cbcrrowincin64bitincs:12;
+	uint32_t            /* reserved */ : 6;
+
+	/* AXI Output 2 Y Configuration, Part 1 */
+	uint32_t            out2yimageheight:12;
+	uint32_t            /* reserved */ : 4;
+	uint32_t            out2yimagewidthin64bitwords:10;
+	uint32_t            /* reserved */ : 6;
+
+	/* AXI Output 2 Y Configuration, Part 2 */
+	uint8_t             out2yburstlen:2;
+	uint32_t            out2ynumrows:12;
+	uint32_t            out2yrowincin64bitincs:12;
+	uint32_t            /* reserved */ : 6;
+
+	/* AXI Output 2 CbCr Configuration, Part 1 */
+	uint32_t            out2cbcrimageheight:12;
+	uint32_t            /* reserved */ : 4;
+	uint32_t            out2cbcrimagewidtein64bitwords:10;
+	uint32_t            /* reserved */ : 6;
+
+	/* AXI Output 2 CbCr Configuration, Part 2 */
+	uint8_t             out2cbcrburstlen:2;
+	uint32_t            out2cbcrnumrows:12;
+	uint32_t            out2cbcrrowincin64bitincs:12;
+	uint32_t            /* reserved */ : 6;
+
+	/* Address configuration:
+	 * output1 phisycal address */
+	unsigned long   output1buffer1_y_phy;
+	unsigned long   output1buffer1_cbcr_phy;
+	unsigned long   output1buffer2_y_phy;
+	unsigned long   output1buffer2_cbcr_phy;
+	unsigned long   output1buffer3_y_phy;
+	unsigned long   output1buffer3_cbcr_phy;
+	unsigned long   output1buffer4_y_phy;
+	unsigned long   output1buffer4_cbcr_phy;
+	unsigned long   output1buffer5_y_phy;
+	unsigned long   output1buffer5_cbcr_phy;
+	unsigned long   output1buffer6_y_phy;
+	unsigned long   output1buffer6_cbcr_phy;
+	unsigned long   output1buffer7_y_phy;
+	unsigned long   output1buffer7_cbcr_phy;
+	unsigned long   output1buffer8_y_phy;
+	unsigned long   output1buffer8_cbcr_phy;
+
+	/* output2 phisycal address */
+	unsigned long   output2buffer1_y_phy;
+	unsigned long   output2buffer1_cbcr_phy;
+	unsigned long   output2buffer2_y_phy;
+	unsigned long   output2buffer2_cbcr_phy;
+	unsigned long   output2buffer3_y_phy;
+	unsigned long   output2buffer3_cbcr_phy;
+	unsigned long   output2buffer4_y_phy;
+	unsigned long   output2buffer4_cbcr_phy;
+	unsigned long   output2buffer5_y_phy;
+	unsigned long   output2buffer5_cbcr_phy;
+	unsigned long   output2buffer6_y_phy;
+	unsigned long   output2buffer6_cbcr_phy;
+	unsigned long   output2buffer7_y_phy;
+	unsigned long   output2buffer7_cbcr_phy;
+	unsigned long   output2buffer8_y_phy;
+	unsigned long   output2buffer8_cbcr_phy;
+} __packed;
+
+struct vfe_stats_we_cfg {
+	uint32_t       header;
+
+	/* White Balance/Exposure Statistic Selection */
+	uint8_t        wb_expstatsenable:1;
+	uint8_t        wb_expstatbuspriorityselection:1;
+	unsigned int   wb_expstatbuspriorityvalue:4;
+	unsigned int   /* reserved */ : 26;
+
+	/* White Balance/Exposure Statistic Configuration, Part 1 */
+	uint8_t        exposurestatregions:1;
+	uint8_t        exposurestatsubregions:1;
+	unsigned int   /* reserved */ : 14;
+
+	unsigned int   whitebalanceminimumy:8;
+	unsigned int   whitebalancemaximumy:8;
+
+	/* White Balance/Exposure Statistic Configuration, Part 2 */
+	uint8_t wb_expstatslopeofneutralregionline[
+		NUM_WB_EXP_NEUTRAL_REGION_LINES];
+
+	/* White Balance/Exposure Statistic Configuration, Part 3 */
+	unsigned int   wb_expstatcrinterceptofneutralregionline2:12;
+	unsigned int   /* reserved */ : 4;
+	unsigned int   wb_expstatcbinterceptofneutralreginnline1:12;
+	unsigned int    /* reserved */ : 4;
+
+	/* White Balance/Exposure Statistic Configuration, Part 4 */
+	unsigned int   wb_expstatcrinterceptofneutralregionline4:12;
+	unsigned int   /* reserved */ : 4;
+	unsigned int   wb_expstatcbinterceptofneutralregionline3:12;
+	unsigned int   /* reserved */ : 4;
+
+	/* White Balance/Exposure Statistic Output Buffer Header */
+	unsigned int   wb_expmetricheaderpattern:8;
+	unsigned int   /* reserved */ : 24;
+
+	/* White Balance/Exposure Statistic Output Buffers-MUST
+	* BE 64 bit ALIGNED */
+	void  *wb_expstatoutputbuffer[NUM_WB_EXP_STAT_OUTPUT_BUFFERS];
+} __packed;
+
+struct vfe_stats_af_cfg {
+	uint32_t header;
+
+	/* Autofocus Statistic Selection */
+	uint8_t       af_enable:1;
+	uint8_t       af_busprioritysel:1;
+	unsigned int  af_buspriorityval:4;
+	unsigned int  /* reserved */ : 26;
+
+	/* Autofocus Statistic Configuration, Part 1 */
+	unsigned int  af_singlewinvoffset:12;
+	unsigned int  /* reserved */ : 4;
+	unsigned int  af_singlewinhoffset:12;
+	unsigned int  /* reserved */ : 3;
+	uint8_t       af_winmode:1;
+
+	/* Autofocus Statistic Configuration, Part 2 */
+	unsigned int  af_singglewinvh:11;
+	unsigned int  /* reserved */ : 5;
+	unsigned int  af_singlewinhw:11;
+	unsigned int  /* reserved */ : 5;
+
+	/* Autofocus Statistic Configuration, Parts 3-6 */
+	uint8_t       af_multiwingrid[NUM_AUTOFOCUS_MULTI_WINDOW_GRIDS];
+
+	/* Autofocus Statistic Configuration, Part 7 */
+	signed int    af_metrichpfcoefa00:5;
+	signed int    af_metrichpfcoefa04:5;
+	unsigned int  af_metricmaxval:11;
+	uint8_t       af_metricsel:1;
+	unsigned int  /* reserved */ : 10;
+
+	/* Autofocus Statistic Configuration, Part 8 */
+	signed int    af_metrichpfcoefa20:5;
+	signed int    af_metrichpfcoefa21:5;
+	signed int    af_metrichpfcoefa22:5;
+	signed int    af_metrichpfcoefa23:5;
+	signed int    af_metrichpfcoefa24:5;
+	unsigned int  /* reserved */ : 7;
+
+	/* Autofocus Statistic Output Buffer Header */
+	unsigned int  af_metrichp:8;
+	unsigned int  /* reserved */ : 24;
+
+	/* Autofocus Statistic Output Buffers - MUST BE 64 bit ALIGNED!!! */
+	void *af_outbuf[NUM_AF_STAT_OUTPUT_BUFFERS];
+} __packed; /* VFE_StatsAutofocusConfigCmdType */
+
+struct msm_camera_frame_msg {
+	unsigned long   output_y_address;
+	unsigned long   output_cbcr_address;
+
+	unsigned int    blacklevelevenColumn:23;
+	uint16_t        reserved1:9;
+	unsigned int    blackleveloddColumn:23;
+	uint16_t        reserved2:9;
+
+	uint16_t        greendefectpixelcount:8;
+	uint16_t        reserved3:8;
+	uint16_t        redbluedefectpixelcount:8;
+	uint16_t        reserved4:8;
+} __packed;
+
+/* New one for 7k */
+struct msm_vfe_command_7k {
+	uint16_t queue;
+	uint16_t length;
+	void     *value;
+};
+
+struct stop_event {
+	wait_queue_head_t wait;
+	int state;
+	int timeout;
+};
+
+static struct msm_free_buf *vfe2x_check_free_buffer(int id, int path);
+
+#endif /* __MSM_VFE7X_H__ */
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/sensors/Makefile b/drivers/media/video/msm/sensors/Makefile
index 7b22592..33db124 100644
--- a/drivers/media/video/msm/sensors/Makefile
+++ b/drivers/media/video/msm/sensors/Makefile
@@ -6,3 +6,7 @@
 obj-$(CONFIG_IMX074) += imx074_v4l2.o
 obj-$(CONFIG_MT9M114) += mt9m114_v4l2.o
 obj-$(CONFIG_OV2720) += ov2720.o
+obj-$(CONFIG_S5K4E1) += s5k4e1_v4l2.o
+obj-$(CONFIG_MT9E013) += mt9e013_v4l2.o
+obj-$(CONFIG_WEBCAM_OV9726) += ov9726_v4l2.o
+obj-$(CONFIG_S5K3L1YX) += s5k3l1yx.o
diff --git a/drivers/media/video/msm/sensors/imx074_v4l2.c b/drivers/media/video/msm/sensors/imx074_v4l2.c
index c77cfc3..f31aece 100644
--- a/drivers/media/video/msm/sensors/imx074_v4l2.c
+++ b/drivers/media/video/msm/sensors/imx074_v4l2.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
@@ -331,6 +331,7 @@
 	.sensor_v4l2_subdev_info_size = ARRAY_SIZE(imx074_subdev_info),
 	.sensor_v4l2_subdev_ops = &imx074_subdev_ops,
 	.func_tbl = &imx074_func_tbl,
+	.clk_rate = MSM_SENSOR_MCLK_24HZ,
 };
 
 module_init(msm_sensor_init_module);
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index d31de14..1b57350 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.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
@@ -172,6 +172,42 @@
 	return 0;
 }
 
+int32_t msm_sensor_setting1(struct msm_sensor_ctrl_t *s_ctrl,
+			int update_type, int res)
+{
+	int32_t rc = 0;
+	static int csi_config;
+
+	s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
+	msleep(30);
+	if (update_type == MSM_SENSOR_REG_INIT) {
+		CDBG("Register INIT\n");
+		s_ctrl->curr_csi_params = NULL;
+		msm_sensor_enable_debugfs(s_ctrl);
+		msm_sensor_write_init_settings(s_ctrl);
+		csi_config = 0;
+	} else if (update_type == MSM_SENSOR_UPDATE_PERIODIC) {
+		CDBG("PERIODIC : %d\n", res);
+		msm_sensor_write_conf_array(
+			s_ctrl->sensor_i2c_client,
+			s_ctrl->msm_sensor_reg->mode_settings, res);
+		msleep(30);
+		if (!csi_config) {
+			s_ctrl->curr_csic_params = s_ctrl->csic_params[res];
+			CDBG("CSI config in progress\n");
+			v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
+				NOTIFY_CSIC_CFG,
+				s_ctrl->curr_csic_params);
+			CDBG("CSI config is done\n");
+			mb();
+			msleep(30);
+			csi_config = 1;
+		}
+		s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
+		msleep(50);
+	}
+	return rc;
+}
 int32_t msm_sensor_setting(struct msm_sensor_ctrl_t *s_ctrl,
 			int update_type, int res)
 {
@@ -409,26 +445,85 @@
 	return rc;
 }
 
+static struct msm_cam_clk_info cam_clk_info[] = {
+	{"cam_clk", MSM_SENSOR_MCLK_24HZ},
+};
+
 int32_t msm_sensor_power_up(struct msm_sensor_ctrl_t *s_ctrl)
 {
 	int32_t rc = 0;
 	struct msm_camera_sensor_info *data = s_ctrl->sensordata;
 	CDBG("%s: %d\n", __func__, __LINE__);
-	msm_sensor_probe_on(&s_ctrl->sensor_i2c_client->client->dev);
-	msm_camio_clk_rate_set(MSM_SENSOR_MCLK_24HZ);
-	rc = gpio_request(data->sensor_platform_info->sensor_reset,
-		"SENSOR_NAME");
-	if (!rc) {
-		CDBG("%s: reset sensor\n", __func__);
-		gpio_direction_output(data->sensor_platform_info->sensor_reset,
-			 0);
-		usleep_range(1000, 2000);
-		gpio_set_value_cansleep(data->sensor_platform_info->
-			sensor_reset, 1);
-		usleep_range(4000, 5000);
-	} else {
-		CDBG("%s: gpio request fail", __func__);
+	s_ctrl->reg_ptr = kzalloc(sizeof(struct regulator *)
+			* data->sensor_platform_info->num_vreg, GFP_KERNEL);
+	if (!s_ctrl->reg_ptr) {
+		pr_err("%s: could not allocate mem for regulators\n",
+			__func__);
+		return -ENOMEM;
 	}
+
+	rc = msm_camera_request_gpio_table(data, 1);
+	if (rc < 0) {
+		pr_err("%s: request gpio failed\n", __func__);
+		goto request_gpio_failed;
+	}
+
+	rc = msm_camera_config_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+			s_ctrl->sensordata->sensor_platform_info->cam_vreg,
+			s_ctrl->sensordata->sensor_platform_info->num_vreg,
+			s_ctrl->reg_ptr, 1);
+	if (rc < 0) {
+		pr_err("%s: regulator on failed\n", __func__);
+		goto config_vreg_failed;
+	}
+
+	rc = msm_camera_enable_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+			s_ctrl->sensordata->sensor_platform_info->cam_vreg,
+			s_ctrl->sensordata->sensor_platform_info->num_vreg,
+			s_ctrl->reg_ptr, 1);
+	if (rc < 0) {
+		pr_err("%s: enable regulator failed\n", __func__);
+		goto enable_vreg_failed;
+	}
+
+	rc = msm_camera_config_gpio_table(data, 1);
+	if (rc < 0) {
+		pr_err("%s: config gpio failed\n", __func__);
+		goto config_gpio_failed;
+	}
+
+	if (s_ctrl->clk_rate != 0)
+		cam_clk_info->clk_rate = s_ctrl->clk_rate;
+
+	rc = msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->dev,
+		cam_clk_info, &s_ctrl->cam_clk, ARRAY_SIZE(cam_clk_info), 1);
+	if (rc < 0) {
+		pr_err("%s: clk enable failed\n", __func__);
+		goto enable_clk_failed;
+	}
+
+	usleep_range(1000, 2000);
+	if (data->sensor_platform_info->ext_power_ctrl != NULL)
+		data->sensor_platform_info->ext_power_ctrl(1);
+
+	return rc;
+enable_clk_failed:
+		msm_camera_config_gpio_table(data, 0);
+config_gpio_failed:
+	msm_camera_enable_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+			s_ctrl->sensordata->sensor_platform_info->cam_vreg,
+			s_ctrl->sensordata->sensor_platform_info->num_vreg,
+			s_ctrl->reg_ptr, 0);
+
+enable_vreg_failed:
+	msm_camera_config_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+		s_ctrl->sensordata->sensor_platform_info->cam_vreg,
+		s_ctrl->sensordata->sensor_platform_info->num_vreg,
+		s_ctrl->reg_ptr, 0);
+config_vreg_failed:
+	msm_camera_request_gpio_table(data, 0);
+request_gpio_failed:
+	kfree(s_ctrl->reg_ptr);
 	return rc;
 }
 
@@ -436,10 +531,21 @@
 {
 	struct msm_camera_sensor_info *data = s_ctrl->sensordata;
 	CDBG("%s\n", __func__);
-	msm_sensor_probe_off(&s_ctrl->sensor_i2c_client->client->dev);
-	gpio_set_value_cansleep(data->sensor_platform_info->sensor_reset, 0);
-	usleep_range(1000, 2000);
-	gpio_free(data->sensor_platform_info->sensor_reset);
+	if (data->sensor_platform_info->ext_power_ctrl != NULL)
+		data->sensor_platform_info->ext_power_ctrl(0);
+	msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->dev,
+		cam_clk_info, &s_ctrl->cam_clk, ARRAY_SIZE(cam_clk_info), 0);
+	msm_camera_config_gpio_table(data, 0);
+	msm_camera_enable_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+		s_ctrl->sensordata->sensor_platform_info->cam_vreg,
+		s_ctrl->sensordata->sensor_platform_info->num_vreg,
+		s_ctrl->reg_ptr, 0);
+	msm_camera_config_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+		s_ctrl->sensordata->sensor_platform_info->cam_vreg,
+		s_ctrl->sensordata->sensor_platform_info->num_vreg,
+		s_ctrl->reg_ptr, 0);
+	msm_camera_request_gpio_table(data, 0);
+	kfree(s_ctrl->reg_ptr);
 	return 0;
 }
 
@@ -494,6 +600,10 @@
 	}
 
 	s_ctrl->sensordata = client->dev.platform_data;
+	if (s_ctrl->sensordata == NULL) {
+		pr_err("%s: NULL sensor data\n", __func__);
+		return -EFAULT;
+	}
 
 	rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
 	if (rc < 0)
@@ -532,6 +642,8 @@
 probe_fail:
 	CDBG("%s_i2c_probe failed\n", client->name);
 power_down:
+	if (rc > 0)
+		rc = 0;
 	s_ctrl->func_tbl->sensor_power_down(s_ctrl);
 	return rc;
 }
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/video/msm/sensors/msm_sensor.h
index e06f628..2b1be1e 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.h
+++ b/drivers/media/video/msm/sensors/msm_sensor.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
@@ -158,12 +158,17 @@
 	struct mutex *msm_sensor_mutex;
 	struct msm_camera_csi2_params *curr_csi_params;
 	struct msm_camera_csi2_params **csi_params;
+	struct msm_camera_csi_params **csic_params;
+	struct msm_camera_csi_params *curr_csic_params;
 
 	struct v4l2_subdev sensor_v4l2_subdev;
 	struct v4l2_subdev_info *sensor_v4l2_subdev_info;
 	uint8_t sensor_v4l2_subdev_info_size;
 	struct v4l2_subdev_ops *sensor_v4l2_subdev_ops;
 	struct msm_sensor_fn_t *func_tbl;
+	struct regulator **reg_ptr;
+	struct clk *cam_clk;
+	long clk_rate;
 };
 
 void msm_sensor_start_stream(struct msm_sensor_ctrl_t *s_ctrl);
@@ -218,6 +223,9 @@
 int32_t msm_sensor_setting(struct msm_sensor_ctrl_t *s_ctrl,
 			int update_type, int res);
 
+int32_t msm_sensor_setting1(struct msm_sensor_ctrl_t *s_ctrl,
+			int update_type, int res);
+
 int msm_sensor_enable_debugfs(struct msm_sensor_ctrl_t *s_ctrl);
 
 long msm_sensor_subdev_ioctl(struct v4l2_subdev *sd,
diff --git a/drivers/media/video/msm/sensors/mt9e013_v4l2.c b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
new file mode 100644
index 0000000..924cbc9
--- /dev/null
+++ b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
@@ -0,0 +1,507 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_sensor.h"
+#define SENSOR_NAME "mt9e013"
+#define PLATFORM_DRIVER_NAME "msm_camera_mt9e013"
+#define mt9e013_obj mt9e013_##obj
+
+DEFINE_MUTEX(mt9e013_mut);
+static struct msm_sensor_ctrl_t mt9e013_s_ctrl;
+
+static struct msm_camera_i2c_reg_conf mt9e013_groupon_settings[] = {
+	{0x0104, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_groupoff_settings[] = {
+	{0x0104, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_prev_settings[] = {
+	{0x0300, 0x0004},/*VT_PIX_CLK_DIV*/
+	{0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
+	{0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
+	{0x0306, 0x003A},/*PLL_MULTIPLIER*/
+	{0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
+	{0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
+	/*Output Size (1632x1224)*/
+	{0x0344, 0x0008},/*X_ADDR_START*/
+	{0x0348, 0x0CC9},/*X_ADDR_END*/
+	{0x0346, 0x0008},/*Y_ADDR_START*/
+	{0x034A, 0x0999},/*Y_ADDR_END*/
+	{0x034C, 0x0660},/*X_OUTPUT_SIZE*/
+	{0x034E, 0x04C8},/*Y_OUTPUT_SIZE*/
+	{0x306E, 0xFCB0},/*DATAPATH_SELECT*/
+	{0x3040, 0x04C3},/*READ_MODE*/
+	{0x3178, 0x0000},/*ANALOG_CONTROL5*/
+	{0x3ED0, 0x1E24},/*DAC_LD_4_5*/
+	{0x0400, 0x0002},/*SCALING_MODE*/
+	{0x0404, 0x0010},/*SCALE_M*/
+	/*Timing configuration*/
+	{0x0342, 0x1018},/*LINE_LENGTH_PCK*/
+	{0x0340, 0x055B},/*FRAME_LENGTH_LINES*/
+	{0x0202, 0x0557},/*COARSE_INTEGRATION_TIME*/
+	{0x3014, 0x0846},/*FINE_INTEGRATION_TIME_*/
+	{0x3010, 0x0130},/*FINE_CORRECTION*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_snap_settings[] = {
+	{0x0300, 0x0004},/*VT_PIX_CLK_DIV*/
+	{0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
+	{0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
+	{0x0306, 0x003A},/*PLL_MULTIPLIER*/
+	{0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
+	{0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
+	/*Output Size (3264x2448)*/
+	{0x0344, 0x0000},/*X_ADDR_START */
+	{0x0348, 0x0CCF},/*X_ADDR_END*/
+	{0x0346, 0x0000},/*Y_ADDR_START */
+	{0x034A, 0x099F},/*Y_ADDR_END*/
+	{0x034C, 0x0CD0},/*X_OUTPUT_SIZE*/
+	{0x034E, 0x09A0},/*Y_OUTPUT_SIZE*/
+	{0x306E, 0xFC80},/*DATAPATH_SELECT*/
+	{0x3040, 0x0041},/*READ_MODE*/
+	{0x3178, 0x0000},/*ANALOG_CONTROL5*/
+	{0x3ED0, 0x1E24},/*DAC_LD_4_5*/
+	{0x0400, 0x0000},/*SCALING_MODE*/
+	{0x0404, 0x0010},/*SCALE_M*/
+	/*Timing configuration*/
+	{0x0342, 0x13F8},/*LINE_LENGTH_PCK*/
+	{0x0340, 0x0A2F},/*FRAME_LENGTH_LINES*/
+	{0x0202, 0x0A1F},/*COARSE_INTEGRATION_TIME*/
+	{0x3014, 0x03F6},/*FINE_INTEGRATION_TIME_ */
+	{0x3010, 0x0078},/*FINE_CORRECTION*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_hfr60_settings[] = {
+	{0x0300, 0x0005},/*VT_PIX_CLK_DIV*/
+	{0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
+	{0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
+	{0x0306, 0x0029},/*PLL_MULTIPLIER*/
+	{0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
+	{0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
+	{0x0344, 0x0008},/*X_ADDR_START*/
+	{0x0348, 0x0685},/*X_ADDR_END*/
+	{0x0346, 0x013a},/*Y_ADDR_START*/
+	{0x034A, 0x055B},/*Y_ADDR_END*/
+	{0x034C, 0x0340},/*X_OUTPUT_SIZE*/
+	{0x034E, 0x0212},/*Y_OUTPUT_SIZE*/
+	{0x306E, 0xFC80},/*DATAPATH_SELECT*/
+	{0x3040, 0x00C3},/*READ_MODE*/
+	{0x3178, 0x0000},/*ANALOG_CONTROL5*/
+	{0x3ED0, 0x1E24},/*DAC_LD_4_5*/
+	{0x0400, 0x0000},/*SCALING_MODE*/
+	{0x0404, 0x0010},/*SCALE_M*/
+	/*Timing configuration*/
+	{0x0342, 0x0970},/*LINE_LENGTH_PCK*/
+	{0x0340, 0x02A1},/*FRAME_LENGTH_LINES*/
+	{0x0202, 0x02A1},/*COARSE_INTEGRATION_TIME*/
+	{0x3014, 0x03F6},/*FINE_INTEGRATION_TIME_*/
+	{0x3010, 0x0078},/*FINE_CORRECTION*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_hfr90_settings[] = {
+	{0x0300, 0x0005},/*VT_PIX_CLK_DIV*/
+	{0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
+	{0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
+	{0x0306, 0x003D},/*PLL_MULTIPLIER*/
+	{0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
+	{0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
+	{0x0344, 0x0008},/*X_ADDR_START*/
+	{0x0348, 0x0685},/*X_ADDR_END*/
+	{0x0346, 0x013a},/*Y_ADDR_START*/
+	{0x034A, 0x055B},/*Y_ADDR_END*/
+	{0x034C, 0x0340},/*X_OUTPUT_SIZE*/
+	{0x034E, 0x0212},/*Y_OUTPUT_SIZE*/
+	{0x306E, 0xFC80},/*DATAPATH_SELECT*/
+	{0x3040, 0x00C3},/*READ_MODE*/
+	{0x3178, 0x0000},/*ANALOG_CONTROL5*/
+	{0x3ED0, 0x1E24},/*DAC_LD_4_5*/
+	{0x0400, 0x0000},/*SCALING_MODE*/
+	{0x0404, 0x0010},/*SCALE_M*/
+	/*Timing configuration*/
+	{0x0342, 0x0970},/*LINE_LENGTH_PCK*/
+	{0x0340, 0x02A1},/*FRAME_LENGTH_LINES*/
+	{0x0202, 0x02A1},/*COARSE_INTEGRATION_TIME*/
+	{0x3014, 0x03F6},/*FINE_INTEGRATION_TIME_*/
+	{0x3010, 0x0078},/*FINE_CORRECTION*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_hfr120_settings[] = {
+	{0x0300, 0x0005},/*VT_PIX_CLK_DIV*/
+	{0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
+	{0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
+	{0x0306, 0x0052},/*PLL_MULTIPLIER*/
+	{0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
+	{0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
+	{0x0344, 0x0008},/*X_ADDR_START*/
+	{0x0348, 0x0685},/*X_ADDR_END*/
+	{0x0346, 0x013a},/*Y_ADDR_START*/
+	{0x034A, 0x055B},/*Y_ADDR_END*/
+	{0x034C, 0x0340},/*X_OUTPUT_SIZE*/
+	{0x034E, 0x0212},/*Y_OUTPUT_SIZE*/
+	{0x306E, 0xFC80},/*DATAPATH_SELECT*/
+	{0x3040, 0x00C3},/*READ_MODE*/
+	{0x3178, 0x0000},/*ANALOG_CONTROL5*/
+	{0x3ED0, 0x1E24},/*DAC_LD_4_5*/
+	{0x0400, 0x0000},/*SCALING_MODE*/
+	{0x0404, 0x0010},/*SCALE_M*/
+	/*Timing configuration*/
+	{0x0342, 0x0970},/*LINE_LENGTH_PCK*/
+	{0x0340, 0x02A1},/*FRAME_LENGTH_LINES*/
+	{0x0202, 0x02A1},/*COARSE_INTEGRATION_TIME*/
+	{0x3014, 0x03F6},/*FINE_INTEGRATION_TIME_*/
+	{0x3010, 0x0078},/*FINE_CORRECTION*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_recommend_settings[] = {
+	/*Disable embedded data*/
+	{0x3064, 0x7800},/*SMIA_TEST*/
+	/*configure 2-lane MIPI*/
+	{0x31AE, 0x0202},/*SERIAL_FORMAT*/
+	{0x31B8, 0x0E3F},/*MIPI_TIMING_2*/
+	/*set data to RAW10 format*/
+	{0x0112, 0x0A0A},/*CCP_DATA_FORMAT*/
+	{0x30F0, 0x8000},/*VCM CONTROL*/
+
+	{0x3044, 0x0590},
+	{0x306E, 0xFC80},
+	{0x30B2, 0xC000},
+	{0x30D6, 0x0800},
+	{0x316C, 0xB42F},
+	{0x316E, 0x869C},
+	{0x3170, 0x210E},
+	{0x317A, 0x010E},
+	{0x31E0, 0x1FB9},
+	{0x31E6, 0x07FC},
+	{0x37C0, 0x0000},
+	{0x37C2, 0x0000},
+	{0x37C4, 0x0000},
+	{0x37C6, 0x0000},
+	{0x3E02, 0x8801},
+	{0x3E04, 0x2301},
+	{0x3E06, 0x8449},
+	{0x3E08, 0x6841},
+	{0x3E0A, 0x400C},
+	{0x3E0C, 0x1001},
+	{0x3E0E, 0x2103},
+	{0x3E10, 0x4B41},
+	{0x3E12, 0x4B26},
+	{0x3E16, 0x8802},
+	{0x3E18, 0x84FF},
+	{0x3E1A, 0x8601},
+	{0x3E1C, 0x8401},
+	{0x3E1E, 0x840A},
+	{0x3E20, 0xFF00},
+	{0x3E22, 0x8401},
+	{0x3E24, 0x00FF},
+	{0x3E26, 0x0088},
+	{0x3E28, 0x2E8A},
+	{0x3E32, 0x8801},
+	{0x3E34, 0x4024},
+	{0x3E38, 0x8469},
+	{0x3E3C, 0x2301},
+	{0x3E3E, 0x3E25},
+	{0x3E40, 0x1C01},
+	{0x3E42, 0x8486},
+	{0x3E44, 0x8401},
+	{0x3E46, 0x00FF},
+	{0x3E48, 0x8401},
+	{0x3E4A, 0x8601},
+	{0x3E4C, 0x8402},
+	{0x3E4E, 0x00FF},
+	{0x3E50, 0x6623},
+	{0x3E52, 0x8340},
+	{0x3E54, 0x00FF},
+	{0x3E56, 0x4A42},
+	{0x3E58, 0x2203},
+	{0x3E5A, 0x674D},
+	{0x3E5C, 0x3F25},
+	{0x3E5E, 0x846A},
+	{0x3E60, 0x4C01},
+	{0x3E62, 0x8401},
+	{0x3E66, 0x3901},
+	{0x3ECC, 0x00EB},
+	{0x3ED0, 0x1E24},
+	{0x3ED4, 0xAFC4},
+	{0x3ED6, 0x909B},
+	{0x3ED8, 0x0006},
+	{0x3EDA, 0xCFC6},
+	{0x3EDC, 0x4FE4},
+	{0x3EE0, 0x2424},
+	{0x3EE2, 0x9797},
+	{0x3EE4, 0xC100},
+	{0x3EE6, 0x0540}
+};
+
+static struct v4l2_subdev_info mt9e013_subdev_info[] = {
+	{
+	.code   = V4L2_MBUS_FMT_SBGGR10_1X10,
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	.fmt    = 1,
+	.order    = 0,
+	},
+	/* more can be supported, to be added later */
+};
+
+static struct msm_camera_i2c_conf_array mt9e013_init_conf[] = {
+	{&mt9e013_recommend_settings[0],
+	ARRAY_SIZE(mt9e013_recommend_settings), 0, MSM_CAMERA_I2C_WORD_DATA}
+};
+
+static struct msm_camera_i2c_conf_array mt9e013_confs[] = {
+	{&mt9e013_snap_settings[0],
+	ARRAY_SIZE(mt9e013_snap_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{&mt9e013_prev_settings[0],
+	ARRAY_SIZE(mt9e013_prev_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{&mt9e013_hfr60_settings[0],
+	ARRAY_SIZE(mt9e013_hfr60_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{&mt9e013_hfr90_settings[0],
+	ARRAY_SIZE(mt9e013_hfr90_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+	{&mt9e013_hfr120_settings[0],
+	ARRAY_SIZE(mt9e013_hfr120_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+};
+
+static struct msm_sensor_output_info_t mt9e013_dimensions[] = {
+	{
+		.x_output = 0xCD0,
+		.y_output = 0x9A0,
+		.line_length_pclk = 0x13F8,
+		.frame_length_lines = 0xA2F,
+		.vt_pixel_clk = 174000000,
+		.op_pixel_clk = 174000000,
+		.binning_factor = 1,
+	},
+	{
+		.x_output = 0x660,
+		.y_output = 0x4C8,
+		.line_length_pclk = 0x1018,
+		.frame_length_lines = 0x55B,
+		.vt_pixel_clk = 174000000,
+		.op_pixel_clk = 174000000,
+		.binning_factor = 1,
+	},
+	{
+		.x_output = 0x340,
+		.y_output = 0x212,
+		.line_length_pclk = 0x970,
+		.frame_length_lines = 0x2A1,
+		.vt_pixel_clk = 98400000,
+		.op_pixel_clk = 98400000,
+		.binning_factor = 1,
+	},
+	{
+		.x_output = 0x340,
+		.y_output = 0x212,
+		.line_length_pclk = 0x970,
+		.frame_length_lines = 0x2A1,
+		.vt_pixel_clk = 146400000,
+		.op_pixel_clk = 146400000,
+		.binning_factor = 1,
+	},
+	{
+		.x_output = 0x340,
+		.y_output = 0x212,
+		.line_length_pclk = 0x970,
+		.frame_length_lines = 0x2A1,
+		.vt_pixel_clk = 196800000,
+		.op_pixel_clk = 196800000,
+		.binning_factor = 1,
+	},
+};
+
+static struct msm_camera_csi_params mt9e013_csi_params = {
+	.data_format = CSI_10BIT,
+	.lane_cnt    = 2,
+	.lane_assign = 0xe4,
+	.dpcm_scheme = 0,
+	.settle_cnt  = 0x18,
+};
+
+static struct msm_camera_csi_params *mt9e013_csi_params_array[] = {
+	&mt9e013_csi_params,
+	&mt9e013_csi_params,
+	&mt9e013_csi_params,
+	&mt9e013_csi_params,
+	&mt9e013_csi_params,
+};
+
+static struct msm_sensor_output_reg_addr_t mt9e013_reg_addr = {
+	.x_output = 0x34C,
+	.y_output = 0x34E,
+	.line_length_pclk = 0x342,
+	.frame_length_lines = 0x340,
+};
+
+static struct msm_sensor_id_info_t mt9e013_id_info = {
+	.sensor_id_reg_addr = 0x0,
+	.sensor_id = 0x4B00,
+};
+
+static struct msm_sensor_exp_gain_info_t mt9e013_exp_gain_info = {
+	.coarse_int_time_addr = 0x202,
+	.global_gain_addr = 0x305E,
+	.vert_offset = 0,
+};
+
+static int32_t mt9e013_write_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
+		uint16_t gain, uint32_t line)
+{
+	uint32_t fl_lines;
+	fl_lines =
+		(s_ctrl->curr_frame_length_lines * s_ctrl->fps_divider) / Q10;
+
+	s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->global_gain_addr, gain | 0x1000,
+		MSM_CAMERA_I2C_WORD_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->coarse_int_time_addr, line,
+		MSM_CAMERA_I2C_WORD_DATA);
+	s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+	return 0;
+}
+
+static int32_t mt9e013_write_exp_snapshot_gain(struct msm_sensor_ctrl_t *s_ctrl,
+		uint16_t gain, uint32_t line)
+{
+	uint32_t fl_lines;
+	fl_lines =
+		(s_ctrl->curr_frame_length_lines * s_ctrl->fps_divider) / Q10;
+
+	s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->global_gain_addr, gain | 0x1000,
+		MSM_CAMERA_I2C_WORD_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->coarse_int_time_addr, line,
+		MSM_CAMERA_I2C_WORD_DATA);
+	s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x301A, (0x065C|0x2), MSM_CAMERA_I2C_WORD_DATA);
+
+	return 0;
+}
+static void mt9e013_start_stream(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x301A, 0x8250, MSM_CAMERA_I2C_WORD_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x301A, 0x8650, MSM_CAMERA_I2C_WORD_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x301A, 0x8658, MSM_CAMERA_I2C_WORD_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x0104, 0x00, MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x301A, 0x065C, MSM_CAMERA_I2C_WORD_DATA);
+}
+
+static void mt9e013_stop_stream(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x301A, 0x0058, MSM_CAMERA_I2C_WORD_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x301A, 0x0050, MSM_CAMERA_I2C_WORD_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		0x0104, 0x01, MSM_CAMERA_I2C_BYTE_DATA);
+}
+
+static const struct i2c_device_id mt9e013_i2c_id[] = {
+	{SENSOR_NAME, (kernel_ulong_t)&mt9e013_s_ctrl},
+	{ }
+};
+
+static struct i2c_driver mt9e013_i2c_driver = {
+	.id_table = mt9e013_i2c_id,
+	.probe  = msm_sensor_i2c_probe,
+	.driver = {
+		.name = SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client mt9e013_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static int __init msm_sensor_init_module(void)
+{
+	return i2c_add_driver(&mt9e013_i2c_driver);
+}
+
+static struct v4l2_subdev_core_ops mt9e013_subdev_core_ops = {
+	.ioctl = msm_sensor_subdev_ioctl,
+	.s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops mt9e013_subdev_video_ops = {
+	.enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops mt9e013_subdev_ops = {
+	.core = &mt9e013_subdev_core_ops,
+	.video  = &mt9e013_subdev_video_ops,
+};
+
+static struct msm_sensor_fn_t mt9e013_func_tbl = {
+	.sensor_start_stream = mt9e013_start_stream,
+	.sensor_stop_stream = mt9e013_stop_stream,
+	.sensor_group_hold_on = msm_sensor_group_hold_on,
+	.sensor_group_hold_off = msm_sensor_group_hold_off,
+	.sensor_set_fps = msm_sensor_set_fps,
+	.sensor_write_exp_gain = mt9e013_write_exp_gain,
+	.sensor_write_snapshot_exp_gain = mt9e013_write_exp_snapshot_gain,
+	.sensor_setting = msm_sensor_setting1,
+	.sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+	.sensor_mode_init = msm_sensor_mode_init,
+	.sensor_get_output_info = msm_sensor_get_output_info,
+	.sensor_config = msm_sensor_config,
+	.sensor_power_up = msm_sensor_power_up,
+	.sensor_power_down = msm_sensor_power_down,
+};
+
+static struct msm_sensor_reg_t mt9e013_regs = {
+	.default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+	.group_hold_on_conf = mt9e013_groupon_settings,
+	.group_hold_on_conf_size = ARRAY_SIZE(mt9e013_groupon_settings),
+	.group_hold_off_conf = mt9e013_groupoff_settings,
+	.group_hold_off_conf_size =
+		ARRAY_SIZE(mt9e013_groupoff_settings),
+	.init_settings = &mt9e013_init_conf[0],
+	.init_size = ARRAY_SIZE(mt9e013_init_conf),
+	.mode_settings = &mt9e013_confs[0],
+	.output_settings = &mt9e013_dimensions[0],
+	.num_conf = ARRAY_SIZE(mt9e013_confs),
+};
+
+static struct msm_sensor_ctrl_t mt9e013_s_ctrl = {
+	.msm_sensor_reg = &mt9e013_regs,
+	.sensor_i2c_client = &mt9e013_sensor_i2c_client,
+	.sensor_i2c_addr = 0x6C,
+	.sensor_output_reg_addr = &mt9e013_reg_addr,
+	.sensor_id_info = &mt9e013_id_info,
+	.sensor_exp_gain_info = &mt9e013_exp_gain_info,
+	.cam_mode = MSM_SENSOR_MODE_INVALID,
+	.csic_params = &mt9e013_csi_params_array[0],
+	.msm_sensor_mutex = &mt9e013_mut,
+	.sensor_i2c_driver = &mt9e013_i2c_driver,
+	.sensor_v4l2_subdev_info = mt9e013_subdev_info,
+	.sensor_v4l2_subdev_info_size = ARRAY_SIZE(mt9e013_subdev_info),
+	.sensor_v4l2_subdev_ops = &mt9e013_subdev_ops,
+	.func_tbl = &mt9e013_func_tbl,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Aptina 8MP Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
+
+
diff --git a/drivers/media/video/msm/sensors/ov2720.c b/drivers/media/video/msm/sensors/ov2720.c
index 6389498..246900e 100644
--- a/drivers/media/video/msm/sensors/ov2720.c
+++ b/drivers/media/video/msm/sensors/ov2720.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
@@ -492,6 +492,7 @@
 	.sensor_v4l2_subdev_info_size = ARRAY_SIZE(ov2720_subdev_info),
 	.sensor_v4l2_subdev_ops = &ov2720_subdev_ops,
 	.func_tbl = &ov2720_func_tbl,
+	.clk_rate = MSM_SENSOR_MCLK_24HZ,
 };
 
 module_init(msm_sensor_init_module);
diff --git a/drivers/media/video/msm/sensors/ov9726_v4l2.c b/drivers/media/video/msm/sensors/ov9726_v4l2.c
new file mode 100644
index 0000000..e345717
--- /dev/null
+++ b/drivers/media/video/msm/sensors/ov9726_v4l2.c
@@ -0,0 +1,280 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_sensor.h"
+#define SENSOR_NAME "ov9726"
+#define PLATFORM_DRIVER_NAME "msm_camera_ov9726"
+#define ov9726_obj ov9726_##obj
+
+DEFINE_MUTEX(ov9726_mut);
+static struct msm_sensor_ctrl_t ov9726_s_ctrl;
+
+static struct msm_camera_i2c_reg_conf ov9726_start_settings[] = {
+	{0x0100, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf ov9726_stop_settings[] = {
+	{0x0100, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf ov9726_groupon_settings[] = {
+	{0x0104, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf ov9726_groupoff_settings[] = {
+	{0x0104, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf ov9726_prev_settings[] = {
+};
+
+static struct msm_camera_i2c_reg_conf ov9726_recommend_settings[] = {
+	{0x0103, 0x01}, /* SOFTWARE_RESET */
+	{0x3026, 0x00}, /* OUTPUT_SELECT01 */
+	{0x3027, 0x00}, /* OUTPUT_SELECT02 */
+	{0x3002, 0xe8}, /* IO_CTRL00 */
+	{0x3004, 0x03}, /* IO_CTRL01 */
+	{0x3005, 0xff}, /* IO_CTRL02 */
+	{0x3703, 0x42},
+	{0x3704, 0x10},
+	{0x3705, 0x45},
+	{0x3603, 0xaa},
+	{0x3632, 0x2f},
+	{0x3620, 0x66},
+	{0x3621, 0xc0},
+	{0x0340, 0x03}, /* FRAME_LENGTH_LINES_HI */
+	{0x0341, 0xC1}, /* FRAME_LENGTH_LINES_LO */
+	{0x0342, 0x06}, /* LINE_LENGTH_PCK_HI */
+	{0x0343, 0x80}, /* LINE_LENGTH_PCK_LO */
+	{0x0202, 0x03}, /* COARSE_INTEGRATION_TIME_HI */
+	{0x0203, 0x43}, /* COARSE_INTEGRATION_TIME_LO */
+	{0x3833, 0x04},
+	{0x3835, 0x02},
+	{0x4702, 0x04},
+	{0x4704, 0x00}, /* DVP_CTRL01 */
+	{0x4706, 0x08},
+	{0x5052, 0x01},
+	{0x3819, 0x6e},
+	{0x3817, 0x94},
+	{0x3a18, 0x00}, /* AEC_GAIN_CEILING_HI */
+	{0x3a19, 0x7f}, /* AEC_GAIN_CEILING_LO */
+	{0x404e, 0x7e},
+	{0x3631, 0x52},
+	{0x3633, 0x50},
+	{0x3630, 0xd2},
+	{0x3604, 0x08},
+	{0x3601, 0x40},
+	{0x3602, 0x14},
+	{0x3610, 0xa0},
+	{0x3612, 0x20},
+	{0x034c, 0x05}, /* X_OUTPUT_SIZE_HI */
+	{0x034d, 0x10}, /* X_OUTPUT_SIZE_LO */
+	{0x034e, 0x03}, /* Y_OUTPUT_SIZE_HI */
+	{0x034f, 0x28}, /* Y_OUTPUT_SIZE_LO */
+	{0x0340, 0x03}, /* FRAME_LENGTH_LINES_HI */
+	{0x0341, 0xC1}, /* FRAME_LENGTH_LINES_LO */
+	{0x0342, 0x06}, /* LINE_LENGTH_PCK_HI */
+	{0x0343, 0x80}, /* LINE_LENGTH_PCK_LO */
+	{0x0202, 0x03}, /* COARSE_INTEGRATION_TIME_HI */
+	{0x0203, 0x43}, /* COARSE_INTEGRATION_TIME_LO */
+	{0x0303, 0x01}, /* VT_SYS_CLK_DIV_LO */
+	{0x3002, 0x00}, /* IO_CTRL00 */
+	{0x3004, 0x00}, /* IO_CTRL01 */
+	{0x3005, 0x00}, /* IO_CTRL02 */
+	{0x4801, 0x0f}, /* MIPI_CTRL01 */
+	{0x4803, 0x05}, /* MIPI_CTRL03 */
+	{0x4601, 0x16}, /* VFIFO_READ_CONTROL */
+	{0x3014, 0x05}, /* SC_CMMN_MIPI / SC_CTRL00 */
+	{0x3104, 0x80},
+	{0x0305, 0x04}, /* PRE_PLL_CLK_DIV_LO */
+	{0x0307, 0x64}, /* PLL_MULTIPLIER_LO */
+	{0x300c, 0x02},
+	{0x300d, 0x20},
+	{0x300e, 0x01},
+	{0x3010, 0x01},
+	{0x460e, 0x81}, /* VFIFO_CONTROL00 */
+	{0x0101, 0x01}, /* IMAGE_ORIENTATION */
+	{0x3707, 0x14},
+	{0x3622, 0x9f},
+	{0x5047, 0x3D}, /* ISP_CTRL47 */
+	{0x4002, 0x45}, /* BLC_CTRL02 */
+	{0x5000, 0x06}, /* ISP_CTRL0 */
+	{0x5001, 0x00}, /* ISP_CTRL1 */
+	{0x3406, 0x00}, /* AWB_MANUAL_CTRL */
+	{0x3503, 0x13}, /* AEC_ENABLE */
+	{0x4005, 0x18}, /* BLC_CTRL05 */
+	{0x4837, 0x21},
+	{0x0100, 0x01}, /* MODE_SELECT */
+	{0x3a0f, 0x64}, /* AEC_CTRL0F */
+	{0x3a10, 0x54}, /* AEC_CTRL10 */
+	{0x3a11, 0xc2}, /* AEC_CTRL11 */
+	{0x3a1b, 0x64}, /* AEC_CTRL1B */
+	{0x3a1e, 0x54}, /* AEC_CTRL1E */
+	{0x3a1a, 0x05}, /* AEC_DIFF_MAX */
+};
+
+static struct v4l2_subdev_info ov9726_subdev_info[] = {
+	{
+	.code   = V4L2_MBUS_FMT_SBGGR10_1X10,
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	.fmt    = 1,
+	.order    = 0,
+	},
+	/* more can be supported, to be added later */
+};
+
+static struct msm_camera_i2c_conf_array ov9726_init_conf[] = {
+	{&ov9726_recommend_settings[0],
+	ARRAY_SIZE(ov9726_recommend_settings), 0, MSM_CAMERA_I2C_BYTE_DATA}
+};
+
+static struct msm_camera_i2c_conf_array ov9726_confs[] = {
+	{&ov9726_prev_settings[0],
+	ARRAY_SIZE(ov9726_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+};
+
+static struct msm_sensor_output_info_t ov9726_dimensions[] = {
+	{
+		.x_output = 0x510, /* 1296 */
+		.y_output = 0x328, /* 808 */
+		.line_length_pclk = 0x680, /* 1664 */
+		.frame_length_lines = 0x3C1, /* 961 */
+		.vt_pixel_clk = 320000000,
+		.op_pixel_clk = 320000000,
+		.binning_factor = 1,
+	},
+};
+
+static struct msm_camera_csi_params ov9726_csi_params = {
+	       .data_format = CSI_10BIT,
+	       .lane_cnt    = 1,
+	       .lane_assign = 0xe4,
+	       .dpcm_scheme = 0,
+	       .settle_cnt  = 7,
+};
+
+static struct msm_camera_csi_params *ov9726_csi_params_array[] = {
+	&ov9726_csi_params,
+};
+
+static struct msm_sensor_output_reg_addr_t ov9726_reg_addr = {
+	.x_output = 0x034c,
+	.y_output = 0x034e,
+	.line_length_pclk = 0x0342,
+	.frame_length_lines = 0x0340,
+};
+
+static struct msm_sensor_id_info_t ov9726_id_info = {
+	.sensor_id_reg_addr = 0x0000,
+	.sensor_id = 0x9726,
+};
+
+static struct msm_sensor_exp_gain_info_t ov9726_exp_gain_info = {
+	.coarse_int_time_addr = 0x0202,
+	.global_gain_addr = 0x0204,
+	.vert_offset = 6,
+};
+
+static const struct i2c_device_id ov9726_i2c_id[] = {
+	{SENSOR_NAME, (kernel_ulong_t)&ov9726_s_ctrl},
+	{ }
+};
+
+static struct i2c_driver ov9726_i2c_driver = {
+	.id_table = ov9726_i2c_id,
+	.probe  = msm_sensor_i2c_probe,
+	.driver = {
+		.name = SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client ov9726_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static int __init msm_sensor_init_module(void)
+{
+	return i2c_add_driver(&ov9726_i2c_driver);
+}
+
+static struct v4l2_subdev_core_ops ov9726_subdev_core_ops = {
+	.ioctl = msm_sensor_subdev_ioctl,
+	.s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops ov9726_subdev_video_ops = {
+	.enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops ov9726_subdev_ops = {
+	.core = &ov9726_subdev_core_ops,
+	.video  = &ov9726_subdev_video_ops,
+};
+
+static struct msm_sensor_fn_t ov9726_func_tbl = {
+	.sensor_start_stream = msm_sensor_start_stream,
+	.sensor_stop_stream = msm_sensor_stop_stream,
+	.sensor_group_hold_on = msm_sensor_group_hold_on,
+	.sensor_group_hold_off = msm_sensor_group_hold_off,
+	.sensor_set_fps = msm_sensor_set_fps,
+	.sensor_write_exp_gain = msm_sensor_write_exp_gain1,
+	.sensor_write_snapshot_exp_gain = msm_sensor_write_exp_gain1,
+	.sensor_setting = msm_sensor_setting1,
+	.sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+	.sensor_mode_init = msm_sensor_mode_init,
+	.sensor_get_output_info = msm_sensor_get_output_info,
+	.sensor_config = msm_sensor_config,
+	.sensor_power_up = msm_sensor_power_up,
+	.sensor_power_down = msm_sensor_power_down,
+};
+
+static struct msm_sensor_reg_t ov9726_regs = {
+	.default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+	.start_stream_conf = ov9726_start_settings,
+	.start_stream_conf_size = ARRAY_SIZE(ov9726_start_settings),
+	.stop_stream_conf = ov9726_stop_settings,
+	.stop_stream_conf_size = ARRAY_SIZE(ov9726_stop_settings),
+	.group_hold_on_conf = ov9726_groupon_settings,
+	.group_hold_on_conf_size = ARRAY_SIZE(ov9726_groupon_settings),
+	.group_hold_off_conf = ov9726_groupoff_settings,
+	.group_hold_off_conf_size =
+		ARRAY_SIZE(ov9726_groupoff_settings),
+	.init_settings = &ov9726_init_conf[0],
+	.init_size = ARRAY_SIZE(ov9726_init_conf),
+	.mode_settings = &ov9726_confs[0],
+	.output_settings = &ov9726_dimensions[0],
+	.num_conf = ARRAY_SIZE(ov9726_confs),
+};
+
+static struct msm_sensor_ctrl_t ov9726_s_ctrl = {
+	.msm_sensor_reg = &ov9726_regs,
+	.sensor_i2c_client = &ov9726_sensor_i2c_client,
+	.sensor_i2c_addr = 0x20,
+	.sensor_output_reg_addr = &ov9726_reg_addr,
+	.sensor_id_info = &ov9726_id_info,
+	.sensor_exp_gain_info = &ov9726_exp_gain_info,
+	.cam_mode = MSM_SENSOR_MODE_INVALID,
+	.csic_params = &ov9726_csi_params_array[0],
+	.msm_sensor_mutex = &ov9726_mut,
+	.sensor_i2c_driver = &ov9726_i2c_driver,
+	.sensor_v4l2_subdev_info = ov9726_subdev_info,
+	.sensor_v4l2_subdev_info_size = ARRAY_SIZE(ov9726_subdev_info),
+	.sensor_v4l2_subdev_ops = &ov9726_subdev_ops,
+	.func_tbl = &ov9726_func_tbl,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Omnivision WXGA Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
+
+
diff --git a/drivers/media/video/msm/sensors/s5k3l1yx.c b/drivers/media/video/msm/sensors/s5k3l1yx.c
new file mode 100644
index 0000000..2177991
--- /dev/null
+++ b/drivers/media/video/msm/sensors/s5k3l1yx.c
@@ -0,0 +1,695 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_sensor.h"
+#define SENSOR_NAME "s5k3l1yx"
+#define PLATFORM_DRIVER_NAME "msm_camera_s5k3l1yx"
+
+DEFINE_MUTEX(s5k3l1yx_mut);
+static struct msm_sensor_ctrl_t s5k3l1yx_s_ctrl;
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_start_settings[] = {
+	{0x0100, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_stop_settings[] = {
+	{0x0100, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_groupon_settings[] = {
+	{0x104, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_groupoff_settings[] = {
+	{0x104, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_snap_settings[] = {
+	{0x0501, 0x00}, /* compression_algorithim_L(1d) */
+	{0x0112, 0x0A}, /* CCP_data_format_H */
+	{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+	{0x0306, 0x00}, /* pll_multiplier */
+	{0x0307, 0xA5}, /* pll_multiplier */
+	{0x0202, 0x09}, /* coarse_integration_time */
+	{0x0203, 0x32}, /* coarse_integration_time */
+	{0x0340, 0x0B}, /* frame_length_lines */
+	{0x0341, 0xEC}, /* frame_length_lines */
+	{0x0342, 0x14}, /* line_length_pck */
+	{0x0343, 0xD8}, /* line_length_pck */
+	{0x0344, 0x00}, /* x_addr_start */
+	{0x0345, 0x08}, /* x_addr_start */
+	{0x0346, 0x00}, /* y_addr_start */
+	{0x0347, 0x00}, /* y_addr_start */
+	{0x0348, 0x0F}, /* x_addr_end */
+	{0x0349, 0xA7}, /* x_addr_end */
+	{0x034A, 0x0B}, /* y_addr_end */
+	{0x034B, 0xC7}, /* y_addr_end */
+	{0x034C, 0x0F}, /* x_output_size */
+	{0x034D, 0xA0}, /* x_output_size */
+	{0x034E, 0x0B}, /* y_output_size */
+	{0x034F, 0xC8}, /* y_output_size */
+	{0x0380, 0x00}, /* x_even_inc */
+	{0x0381, 0x01}, /* x_even_inc */
+	{0x0382, 0x00}, /* x_odd_inc */
+	{0x0383, 0x01}, /* x_odd_inc */
+	{0x0384, 0x00}, /* y_even_inc */
+	{0x0385, 0x01}, /* y_even_inc */
+	{0x0386, 0x00}, /* y_odd_inc */
+	{0x0387, 0x01}, /* y_odd_inc */
+	{0x0900, 0x00}, /* binning_mode */
+	{0x0901, 0x22}, /* binning_type */
+	{0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_prev_settings[] = {
+	{0x0501, 0x00}, /* compression_algorithim_L(1d) */
+	{0x0112, 0x0A}, /* CCP_data_format_H */
+	{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+	{0x0306, 0x00}, /* pll_multiplier */
+	{0x0307, 0xA5}, /* pll_multiplier */
+	{0x0202, 0x06}, /* coarse_integration_time */
+	{0x0203, 0x00}, /* coarse_integration_time */
+	{0x0340, 0x09}, /* frame_length_lines */
+	{0x0341, 0x98}, /* frame_length_lines */
+	{0x0342, 0x11}, /* line_length_pck */
+	{0x0343, 0x80}, /* line_length_pck */
+	{0x0344, 0x00}, /* x_addr_start */
+	{0x0345, 0x18}, /* x_addr_start */
+	{0x0346, 0x00}, /* y_addr_start */
+	{0x0347, 0x00}, /* y_addr_start */
+	{0x0348, 0x0F}, /* x_addr_end */
+	{0x0349, 0x97}, /* x_addr_end */
+	{0x034A, 0x0B}, /* y_addr_end */
+	{0x034B, 0xC7}, /* y_addr_end */
+	{0x034C, 0x07}, /* x_output_size */
+	{0x034D, 0xC0}, /* x_output_size */
+	{0x034E, 0x05}, /* y_output_size */
+	{0x034F, 0xE4}, /* y_output_size */
+	{0x0380, 0x00}, /* x_even_inc */
+	{0x0381, 0x01}, /* x_even_inc */
+	{0x0382, 0x00}, /* x_odd_inc */
+	{0x0383, 0x03}, /* x_odd_inc */
+	{0x0384, 0x00}, /* y_even_inc */
+	{0x0385, 0x01}, /* y_even_inc */
+	{0x0386, 0x00}, /* y_odd_inc */
+	{0x0387, 0x03}, /* y_odd_inc */
+	{0x0900, 0x01}, /* binning_mode */
+	{0x0901, 0x22}, /* binning_type */
+	{0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_video_60fps_settings[] = {
+	{0x0501, 0x00}, /* compression_algorithim_L(1d) */
+	{0x0112, 0x0A}, /* CCP_data_format_H */
+	{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+	{0x0306, 0x00}, /* pll_multiplier */
+	{0x0307, 0xA5}, /* pll_multiplier */
+	{0x0202, 0x02}, /* coarse_integration_time */
+	{0x0203, 0x1C}, /* coarse_integration_time */
+	{0x0340, 0x03}, /* frame_length_lines */
+	{0x0341, 0xE0}, /* frame_length_lines */
+	{0x0342, 0x14}, /* line_length_pck */
+	{0x0343, 0xD8}, /* line_length_pck */
+	{0x0344, 0x01}, /* x_addr_start */
+	{0x0345, 0x20}, /* x_addr_start */
+	{0x0346, 0x02}, /* y_addr_start */
+	{0x0347, 0x23}, /* y_addr_start */
+	{0x0348, 0x0E}, /* x_addr_end */
+	{0x0349, 0xA0}, /* x_addr_end */
+	{0x034A, 0x09}, /* y_addr_end */
+	{0x034B, 0xA4}, /* y_addr_end */
+	{0x034C, 0x03}, /* x_output_size */
+	{0x034D, 0x60}, /* x_output_size */
+	{0x034E, 0x01}, /* y_output_size */
+	{0x034F, 0xE0}, /* y_output_size */
+	{0x0380, 0x00}, /* x_even_inc */
+	{0x0381, 0x01}, /* x_even_inc */
+	{0x0382, 0x00}, /* x_odd_inc */
+	{0x0383, 0x07}, /* x_odd_inc */
+	{0x0384, 0x00}, /* y_even_inc */
+	{0x0385, 0x01}, /* y_even_inc */
+	{0x0386, 0x00}, /* y_odd_inc */
+	{0x0387, 0x07}, /* y_odd_inc */
+	{0x0900, 0x01}, /* binning_mode */
+	{0x0901, 0x44}, /* binning_type */
+	{0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_video_90fps_settings[] = {
+	{0x0501, 0x00}, /* compression_algorithim_L(1d) */
+	{0x0112, 0x0A}, /* CCP_data_format_H */
+	{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+	{0x0306, 0x00}, /* pll_multiplier */
+	{0x0307, 0xA5}, /* pll_multiplier */
+	{0x0202, 0x02}, /* coarse_integration_time */
+	{0x0203, 0x1C}, /* coarse_integration_time */
+	{0x0340, 0x02}, /* frame_length_lines */
+	{0x0341, 0x98}, /* frame_length_lines */
+	{0x0342, 0x14}, /* line_length_pck */
+	{0x0343, 0xD8}, /* line_length_pck */
+	{0x0344, 0x01}, /* x_addr_start */
+	{0x0345, 0x20}, /* x_addr_start */
+	{0x0346, 0x02}, /* y_addr_start */
+	{0x0347, 0x23}, /* y_addr_start */
+	{0x0348, 0x0E}, /* x_addr_end */
+	{0x0349, 0xA0}, /* x_addr_end */
+	{0x034A, 0x09}, /* y_addr_end */
+	{0x034B, 0xA4}, /* y_addr_end */
+	{0x034C, 0x03}, /* x_output_size */
+	{0x034D, 0x60}, /* x_output_size */
+	{0x034E, 0x01}, /* y_output_size */
+	{0x034F, 0xE0}, /* y_output_size */
+	{0x0380, 0x00}, /* x_even_inc */
+	{0x0381, 0x01}, /* x_even_inc */
+	{0x0382, 0x00}, /* x_odd_inc */
+	{0x0383, 0x07}, /* x_odd_inc */
+	{0x0384, 0x00}, /* y_even_inc */
+	{0x0385, 0x01}, /* y_even_inc */
+	{0x0386, 0x00}, /* y_odd_inc */
+	{0x0387, 0x07}, /* y_odd_inc */
+	{0x0900, 0x01}, /* binning_mode */
+	{0x0901, 0x44}, /* binning_type */
+	{0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_video_120fps_settings[] = {
+	{0x0501, 0x00}, /* compression_algorithim_L(1d) */
+	{0x0112, 0x0A}, /* CCP_data_format_H */
+	{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+	{0x0306, 0x00}, /* pll_multiplier */
+	{0x0307, 0xA5}, /* pll_multiplier */
+	{0x0202, 0x02}, /* coarse_integration_time */
+	{0x0203, 0x1C}, /* coarse_integration_time */
+	{0x0340, 0x02}, /* frame_length_lines */
+	{0x0341, 0x0D}, /* frame_length_lines */
+	{0x0342, 0x14}, /* line_length_pck */
+	{0x0343, 0xD8}, /* line_length_pck */
+	{0x0344, 0x01}, /* x_addr_start */
+	{0x0345, 0x20}, /* x_addr_start */
+	{0x0346, 0x02}, /* y_addr_start */
+	{0x0347, 0x23}, /* y_addr_start */
+	{0x0348, 0x0E}, /* x_addr_end */
+	{0x0349, 0xA0}, /* x_addr_end */
+	{0x034A, 0x09}, /* y_addr_end */
+	{0x034B, 0xA4}, /* y_addr_end */
+	{0x034C, 0x03}, /* x_output_size */
+	{0x034D, 0x60}, /* x_output_size */
+	{0x034E, 0x01}, /* y_output_size */
+	{0x034F, 0xE0}, /* y_output_size */
+	{0x0380, 0x00}, /* x_even_inc */
+	{0x0381, 0x01}, /* x_even_inc */
+	{0x0382, 0x00}, /* x_odd_inc */
+	{0x0383, 0x07}, /* x_odd_inc */
+	{0x0384, 0x00}, /* y_even_inc */
+	{0x0385, 0x01}, /* y_even_inc */
+	{0x0386, 0x00}, /* y_odd_inc */
+	{0x0387, 0x07}, /* y_odd_inc */
+	{0x0900, 0x01}, /* binning_mode */
+	{0x0901, 0x44}, /* binning_type */
+	{0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_dpcm_settings[] = {
+	{0x0501, 0x01}, /* compression_algorithim_L(1d) */
+	{0x0112, 0x0A}, /* CCP_data_format_H */
+	{0x0113, 0x08}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+	{0x0306, 0x00}, /* pll_multiplier */
+	{0x0307, 0xA0}, /* pll_multiplier */
+	{0x0202, 0x09}, /* coarse_integration_time */
+	{0x0203, 0x32}, /* coarse_integration_time */
+	{0x0340, 0x0B}, /* frame_length_lines */
+	{0x0341, 0xEC}, /* frame_length_lines */
+	{0x0342, 0x11}, /* line_length_pck */
+	{0x0343, 0x80}, /* line_length_pck */
+	{0x0344, 0x00}, /* x_addr_start */
+	{0x0345, 0x08}, /* x_addr_start */
+	{0x0346, 0x00}, /* y_addr_start */
+	{0x0347, 0x00}, /* y_addr_start */
+	{0x0348, 0x0F}, /* x_addr_end */
+	{0x0349, 0xA7}, /* x_addr_end */
+	{0x034A, 0x0B}, /* y_addr_end */
+	{0x034B, 0xC7}, /* y_addr_end */
+	{0x034C, 0x0F}, /* x_output_size */
+	{0x034D, 0xA0}, /* x_output_size */
+	{0x034E, 0x0B}, /* y_output_size */
+	{0x034F, 0xC8}, /* y_output_size */
+	{0x0380, 0x00}, /* x_even_inc */
+	{0x0381, 0x01}, /* x_even_inc */
+	{0x0382, 0x00}, /* x_odd_inc */
+	{0x0383, 0x01}, /* x_odd_inc */
+	{0x0384, 0x00}, /* y_even_inc */
+	{0x0385, 0x01}, /* y_even_inc */
+	{0x0386, 0x00}, /* y_odd_inc */
+	{0x0387, 0x01}, /* y_odd_inc */
+	{0x0900, 0x00}, /* binning_mode */
+	{0x0901, 0x22}, /* binning_type */
+	{0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_recommend_settings[] = {
+	{0x0100, 0x00},
+	{0x0103, 0x01}, /* software_reset */
+	{0x0104, 0x00}, /* grouped_parameter_hold */
+	{0x0114, 0x03}, /* CSI_lane_mode, 4 lane setting */
+	{0x0120, 0x00}, /* gain_mode, global analogue gain*/
+	{0x0121, 0x00}, /* exposure_mode, global exposure */
+	{0x0136, 0x18}, /* Extclk_frequency_mhz */
+	{0x0137, 0x00}, /* Extclk_frequency_mhz */
+	{0x0200, 0x08}, /* fine_integration_time */
+	{0x0201, 0x88}, /* fine_integration_time */
+	{0x0204, 0x00}, /* analogue_gain_code_global */
+	{0x0205, 0x20}, /* analogue_gain_code_global */
+	{0x020E, 0x01}, /* digital_gain_greenR */
+	{0x020F, 0x00}, /* digital_gain_greenR */
+	{0x0210, 0x01}, /* digital_gain_red */
+	{0x0211, 0x00}, /* digital_gain_red */
+	{0x0212, 0x01}, /* digital_gain_blue */
+	{0x0213, 0x00}, /* digital_gain_blue */
+	{0x0214, 0x01}, /* digital_gain_greenB */
+	{0x0215, 0x00}, /* digital_gain_greenB */
+	{0x0300, 0x00}, /* vt_pix_clk_div */
+	{0x0301, 0x02}, /* vt_pix_clk_div */
+	{0x0302, 0x00}, /* vt_sys_clk_div */
+	{0x0303, 0x01}, /* vt_sys_clk_div */
+	{0x0304, 0x00}, /* pre_pll_clk_div */
+	{0x0305, 0x06}, /* pre_pll_clk_div */
+	{0x0308, 0x00}, /* op_pix_clk_div */
+	{0x0309, 0x02}, /* op_pix_clk_div */
+	{0x030A, 0x00}, /* op_sys_clk_div */
+	{0x030B, 0x01}, /* op_sys_clk_div */
+	{0x0800, 0x00}, /* tclk_post for D-PHY control */
+	{0x0801, 0x00}, /* ths_prepare for D-PHY control */
+	{0x0802, 0x00}, /* ths_zero_min for D-PHY control */
+	{0x0803, 0x00}, /* ths_trail for D-PHY control */
+	{0x0804, 0x00}, /* tclk_trail_min for D-PHY control */
+	{0x0805, 0x00}, /* tclk_prepare for D-PHY control */
+	{0x0806, 0x00}, /* tclk_zero_zero for D-PHY control */
+	{0x0807, 0x00}, /* tlpx for D-PHY control */
+	{0x0820, 0x02}, /* requested_link_bit_rate_mbps */
+	{0x0821, 0x94}, /* requested_link_bit_rate_mbps */
+	{0x0822, 0x00}, /* requested_link_bit_rate_mbps */
+	{0x0823, 0x00}, /* requested_link_bit_rate_mbps */
+	{0x3000, 0x0A},
+	{0x3001, 0xF7},
+	{0x3002, 0x0A},
+	{0x3003, 0xF7},
+	{0x3004, 0x08},
+	{0x3005, 0xF8},
+	{0x3006, 0x5B},
+	{0x3007, 0x73},
+	{0x3008, 0x49},
+	{0x3009, 0x0C},
+	{0x300A, 0xF8},
+	{0x300B, 0x4E},
+	{0x300C, 0x64},
+	{0x300D, 0x5C},
+	{0x300E, 0x71},
+	{0x300F, 0x0C},
+	{0x3010, 0x6A},
+	{0x3011, 0x14},
+	{0x3012, 0x14},
+	{0x3013, 0x0C},
+	{0x3014, 0x24},
+	{0x3015, 0x4F},
+	{0x3016, 0x86},
+	{0x3017, 0x0E},
+	{0x3018, 0x2C},
+	{0x3019, 0x30},
+	{0x301A, 0x31},
+	{0x301B, 0x32},
+	{0x301C, 0xFF},
+	{0x301D, 0x33},
+	{0x301E, 0x5C},
+	{0x301F, 0xFA},
+	{0x3020, 0x36},
+	{0x3021, 0x46},
+	{0x3022, 0x92},
+	{0x3023, 0xF5},
+	{0x3024, 0x6E},
+	{0x3025, 0x19},
+	{0x3026, 0x32},
+	{0x3027, 0x4B},
+	{0x3028, 0x04},
+	{0x3029, 0x50},
+	{0x302A, 0x0C},
+	{0x302B, 0x04},
+	{0x302C, 0xEF},
+	{0x302D, 0xC1},
+	{0x302E, 0x74},
+	{0x302F, 0x40},
+	{0x3030, 0x00},
+	{0x3031, 0x00},
+	{0x3032, 0x00},
+	{0x3033, 0x00},
+	{0x3034, 0x0F},
+	{0x3035, 0x01},
+	{0x3036, 0x00},
+	{0x3037, 0x00},
+	{0x3038, 0x88},
+	{0x3039, 0x98},
+	{0x303A, 0x1F},
+	{0x303B, 0x01},
+	{0x303C, 0x00},
+	{0x303D, 0x03},
+	{0x303E, 0x2F},
+	{0x303F, 0x09},
+	{0x3040, 0xFF},
+	{0x3041, 0x22},
+	{0x3042, 0x03},
+	{0x3043, 0x03},
+	{0x3044, 0x20},
+	{0x3045, 0x10},
+	{0x3046, 0x10},
+	{0x3047, 0x08},
+	{0x3048, 0x10},
+	{0x3049, 0x01},
+	{0x304A, 0x00},
+	{0x304B, 0x80},
+	{0x304C, 0x80},
+	{0x304D, 0x00},
+	{0x304E, 0x00},
+	{0x304F, 0x00},
+	{0x3051, 0x09},
+	{0x3052, 0xC4},
+	{0x305A, 0xE0},
+	{0x323D, 0x04},
+	{0x323E, 0x38},
+	{0x3305, 0xDD},
+	{0x3050, 0x01},
+	{0x3202, 0x01},
+	{0x3203, 0x01},
+	{0x3204, 0x01},
+	{0x3205, 0x01},
+	{0x3206, 0x01},
+	{0x3207, 0x01},
+	{0x320A, 0x05},
+	{0x320B, 0x20},
+	{0x3235, 0xB7},
+	{0x324C, 0x04},
+	{0x324A, 0x07},
+	{0x3902, 0x01},
+	{0x3915, 0x70},
+	{0x3916, 0x80},
+	{0x3A00, 0x01},
+	{0x3A06, 0x03},
+	{0x3B29, 0x01},
+	{0x3C11, 0x08},
+	{0x3C12, 0x7B},
+	{0x3C13, 0xC0},
+	{0x3C14, 0x70},
+	{0x3C15, 0x80},
+	{0x3C20, 0x00},
+	{0x3C23, 0x03},
+	{0x3C24, 0x00},
+	{0x3C50, 0x72},
+	{0x3C51, 0x85},
+	{0x3C53, 0x40},
+	{0x3C55, 0xA0},
+	{0x3D00, 0x00},
+	{0x3D01, 0x00},
+	{0x3D11, 0x01},
+	{0x3486, 0x05},
+	{0x3B35, 0x06},
+	{0x3A05, 0x01},
+	{0x3A07, 0x2B},
+	{0x3A09, 0x01},
+	{0x3940, 0xFF},
+	{0x3300, 0x00},
+	{0x3900, 0xFF},
+	{0x3914, 0x08},
+	{0x3A01, 0x0F},
+	{0x3A02, 0xA0},
+	{0x3A03, 0x0B},
+	{0x3A04, 0xC8},
+	{0x3701, 0x00},
+	{0x3702, 0x00},
+	{0x3703, 0x00},
+	{0x3704, 0x00},
+	{0x0101, 0x00}, /* image_orientation, mirror & flip off*/
+	{0x0105, 0x01}, /* mask_corrupted_frames */
+	{0x0110, 0x00}, /* CSI-2_channel_identifier */
+	{0x3942, 0x01}, /* [0] 1:mipi, 0:pvi */
+	{0x0B00, 0x00},
+};
+
+static struct v4l2_subdev_info s5k3l1yx_subdev_info[] = {
+	{
+	.code   = V4L2_MBUS_FMT_SBGGR10_1X10,
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	.fmt    = 1,
+	.order    = 0,
+	},
+	/* more can be supported, to be added later */
+};
+
+static struct msm_camera_i2c_conf_array s5k3l1yx_init_conf[] = {
+	{&s5k3l1yx_recommend_settings[0],
+	ARRAY_SIZE(s5k3l1yx_recommend_settings), 0, MSM_CAMERA_I2C_BYTE_DATA}
+};
+
+static struct msm_camera_i2c_conf_array s5k3l1yx_confs[] = {
+	{&s5k3l1yx_snap_settings[0],
+	ARRAY_SIZE(s5k3l1yx_snap_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&s5k3l1yx_prev_settings[0],
+	ARRAY_SIZE(s5k3l1yx_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&s5k3l1yx_video_60fps_settings[0],
+	ARRAY_SIZE(s5k3l1yx_video_60fps_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&s5k3l1yx_video_90fps_settings[0],
+	ARRAY_SIZE(s5k3l1yx_video_90fps_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&s5k3l1yx_video_120fps_settings[0],
+	ARRAY_SIZE(s5k3l1yx_video_120fps_settings), 0,
+					MSM_CAMERA_I2C_BYTE_DATA},
+	{&s5k3l1yx_dpcm_settings[0],
+	ARRAY_SIZE(s5k3l1yx_dpcm_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+};
+
+static struct msm_sensor_output_info_t s5k3l1yx_dimensions[] = {
+	/* 20 fps snapshot */
+	{
+		.x_output = 4000,
+		.y_output = 3016,
+		.line_length_pclk = 5336,
+		.frame_length_lines = 3052,
+		.vt_pixel_clk = 330000000,
+		.op_pixel_clk = 320000000,
+		.binning_factor = 1,
+	},
+	/* 30 fps preview */
+	{
+		.x_output = 1984,
+		.y_output = 1508,
+		.line_length_pclk = 4480,
+		.frame_length_lines = 2456,
+		.vt_pixel_clk = 330000000,
+		.op_pixel_clk = 320000000,
+		.binning_factor = 1,
+	},
+	/* 60 fps video */
+	{
+		.x_output = 864,
+		.y_output = 480,
+		.line_length_pclk = 5336,
+		.frame_length_lines = 992,
+		.vt_pixel_clk = 330000000,
+		.op_pixel_clk = 320000000,
+		.binning_factor = 1,
+	},
+	/* 90 fps video */
+	{
+		.x_output = 864,
+		.y_output = 480,
+		.line_length_pclk = 5336,
+		.frame_length_lines = 664,
+		.vt_pixel_clk = 330000000,
+		.op_pixel_clk = 320000000,
+		.binning_factor = 1,
+	},
+	/* 120 fps video */
+	{
+		.x_output = 864,
+		.y_output = 480,
+		.line_length_pclk = 5336,
+		.frame_length_lines = 525,
+		.vt_pixel_clk = 330000000,
+		.op_pixel_clk = 320000000,
+		.binning_factor = 1,
+	},
+	/* 24 fps snapshot */
+	{
+		.x_output = 4000,
+		.y_output = 3016,
+		.line_length_pclk = 4480,
+		.frame_length_lines = 3052,
+		.vt_pixel_clk = 330000000,
+		.op_pixel_clk = 320000000,
+		.binning_factor = 1,
+	},
+};
+
+static struct msm_camera_csid_vc_cfg s5k3l1yx_cid_cfg[] = {
+	{0, CSI_RAW10, CSI_DECODE_10BIT},
+};
+
+static struct msm_camera_csi2_params s5k3l1yx_csi_params = {
+	.csid_params = {
+		.lane_assign = 0xe4,
+		.lane_cnt = 4,
+		.lut_params = {
+			.num_cid = ARRAY_SIZE(s5k3l1yx_cid_cfg),
+			.vc_cfg = s5k3l1yx_cid_cfg,
+		},
+	},
+	.csiphy_params = {
+		.lane_cnt = 4,
+		.settle_cnt = 0x1B,
+	},
+};
+
+static struct msm_camera_csid_vc_cfg s5k3l1yx_cid_dpcm_cfg[] = {
+	{0, CSI_RAW8, CSI_DECODE_DPCM_10_8_10},
+};
+
+static struct msm_camera_csi2_params s5k3l1yx_csi_dpcm_params = {
+	.csid_params = {
+		.lane_assign = 0xe4,
+		.lane_cnt = 4,
+		.lut_params = {
+			.num_cid = ARRAY_SIZE(s5k3l1yx_cid_dpcm_cfg),
+			.vc_cfg = s5k3l1yx_cid_dpcm_cfg,
+		},
+	},
+	.csiphy_params = {
+		.lane_cnt = 4,
+		.settle_cnt = 0x1B,
+	},
+};
+
+static struct msm_camera_csi2_params *s5k3l1yx_csi_params_array[] = {
+	&s5k3l1yx_csi_params,
+	&s5k3l1yx_csi_params,
+	&s5k3l1yx_csi_params,
+	&s5k3l1yx_csi_params,
+	&s5k3l1yx_csi_params,
+	&s5k3l1yx_csi_dpcm_params,
+};
+
+static struct msm_sensor_output_reg_addr_t s5k3l1yx_reg_addr = {
+	.x_output = 0x34C,
+	.y_output = 0x34E,
+	.line_length_pclk = 0x342,
+	.frame_length_lines = 0x340,
+};
+
+static struct msm_sensor_id_info_t s5k3l1yx_id_info = {
+	.sensor_id_reg_addr = 0x0,
+	.sensor_id = 0x3121,
+};
+
+static struct msm_sensor_exp_gain_info_t s5k3l1yx_exp_gain_info = {
+	.coarse_int_time_addr = 0x202,
+	.global_gain_addr = 0x204,
+	.vert_offset = 8,
+};
+
+static const struct i2c_device_id s5k3l1yx_i2c_id[] = {
+	{SENSOR_NAME, (kernel_ulong_t)&s5k3l1yx_s_ctrl},
+	{ }
+};
+
+static struct i2c_driver s5k3l1yx_i2c_driver = {
+	.id_table = s5k3l1yx_i2c_id,
+	.probe  = msm_sensor_i2c_probe,
+	.driver = {
+		.name = SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client s5k3l1yx_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static int __init msm_sensor_init_module(void)
+{
+	return i2c_add_driver(&s5k3l1yx_i2c_driver);
+}
+
+static struct v4l2_subdev_core_ops s5k3l1yx_subdev_core_ops = {
+	.ioctl = msm_sensor_subdev_ioctl,
+	.s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops s5k3l1yx_subdev_video_ops = {
+	.enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops s5k3l1yx_subdev_ops = {
+	.core = &s5k3l1yx_subdev_core_ops,
+	.video  = &s5k3l1yx_subdev_video_ops,
+};
+
+static struct msm_sensor_fn_t s5k3l1yx_func_tbl = {
+	.sensor_start_stream = msm_sensor_start_stream,
+	.sensor_stop_stream = msm_sensor_stop_stream,
+	.sensor_group_hold_on = msm_sensor_group_hold_on,
+	.sensor_group_hold_off = msm_sensor_group_hold_off,
+	.sensor_set_fps = msm_sensor_set_fps,
+	.sensor_write_exp_gain = msm_sensor_write_exp_gain1,
+	.sensor_write_snapshot_exp_gain = msm_sensor_write_exp_gain1,
+	.sensor_setting = msm_sensor_setting,
+	.sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+	.sensor_mode_init = msm_sensor_mode_init,
+	.sensor_get_output_info = msm_sensor_get_output_info,
+	.sensor_config = msm_sensor_config,
+	.sensor_power_up = msm_sensor_power_up,
+	.sensor_power_down = msm_sensor_power_down,
+};
+
+static struct msm_sensor_reg_t s5k3l1yx_regs = {
+	.default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+	.start_stream_conf = s5k3l1yx_start_settings,
+	.start_stream_conf_size = ARRAY_SIZE(s5k3l1yx_start_settings),
+	.stop_stream_conf = s5k3l1yx_stop_settings,
+	.stop_stream_conf_size = ARRAY_SIZE(s5k3l1yx_stop_settings),
+	.group_hold_on_conf = s5k3l1yx_groupon_settings,
+	.group_hold_on_conf_size = ARRAY_SIZE(s5k3l1yx_groupon_settings),
+	.group_hold_off_conf = s5k3l1yx_groupoff_settings,
+	.group_hold_off_conf_size =
+		ARRAY_SIZE(s5k3l1yx_groupoff_settings),
+	.init_settings = &s5k3l1yx_init_conf[0],
+	.init_size = ARRAY_SIZE(s5k3l1yx_init_conf),
+	.mode_settings = &s5k3l1yx_confs[0],
+	.output_settings = &s5k3l1yx_dimensions[0],
+	.num_conf = ARRAY_SIZE(s5k3l1yx_confs),
+};
+
+static struct msm_sensor_ctrl_t s5k3l1yx_s_ctrl = {
+	.msm_sensor_reg = &s5k3l1yx_regs,
+	.sensor_i2c_client = &s5k3l1yx_sensor_i2c_client,
+	.sensor_i2c_addr = 0x6E,
+	.sensor_output_reg_addr = &s5k3l1yx_reg_addr,
+	.sensor_id_info = &s5k3l1yx_id_info,
+	.sensor_exp_gain_info = &s5k3l1yx_exp_gain_info,
+	.cam_mode = MSM_SENSOR_MODE_INVALID,
+	.csi_params = &s5k3l1yx_csi_params_array[0],
+	.msm_sensor_mutex = &s5k3l1yx_mut,
+	.sensor_i2c_driver = &s5k3l1yx_i2c_driver,
+	.sensor_v4l2_subdev_info = s5k3l1yx_subdev_info,
+	.sensor_v4l2_subdev_info_size = ARRAY_SIZE(s5k3l1yx_subdev_info),
+	.sensor_v4l2_subdev_ops = &s5k3l1yx_subdev_ops,
+	.func_tbl = &s5k3l1yx_func_tbl,
+	.clk_rate = MSM_SENSOR_MCLK_24HZ,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Samsung 12MP Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/sensors/s5k4e1_v4l2.c b/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
new file mode 100644
index 0000000..1f99119
--- /dev/null
+++ b/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
@@ -0,0 +1,503 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_sensor.h"
+#define SENSOR_NAME "s5k4e1"
+#define PLATFORM_DRIVER_NAME "msm_camera_s5k4e1"
+#define s5k4e1_obj s5k4e1_##obj
+#define MSB                             1
+#define LSB                             0
+
+DEFINE_MUTEX(s5k4e1_mut);
+static struct msm_sensor_ctrl_t s5k4e1_s_ctrl;
+
+static struct msm_camera_i2c_reg_conf s5k4e1_start_settings[] = {
+	{0x0100, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_stop_settings[] = {
+	{0x0100, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_groupon_settings[] = {
+	{0x0104, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_groupoff_settings[] = {
+	{0x0104, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_prev_settings[] = {
+	/* output size (1304 x 980) */
+	{0x30A9, 0x02},/* Horizontal Binning On */
+	{0x300E, 0xEB},/* Vertical Binning On */
+	{0x0387, 0x03},/* y_odd_inc 03(10b AVG) */
+	{0x0344, 0x00},/* x_addr_start 0 */
+	{0x0345, 0x00},
+	{0x0348, 0x0A},/* x_addr_end 2607 */
+	{0x0349, 0x2F},
+	{0x0346, 0x00},/* y_addr_start 0 */
+	{0x0347, 0x00},
+	{0x034A, 0x07},/* y_addr_end 1959 */
+	{0x034B, 0xA7},
+	{0x0380, 0x00},/* x_even_inc 1 */
+	{0x0381, 0x01},
+	{0x0382, 0x00},/* x_odd_inc 1 */
+	{0x0383, 0x01},
+	{0x0384, 0x00},/* y_even_inc 1 */
+	{0x0385, 0x01},
+	{0x0386, 0x00},/* y_odd_inc 3 */
+	{0x0387, 0x03},
+	{0x034C, 0x05},/* x_output_size 1304 */
+	{0x034D, 0x18},
+	{0x034E, 0x03},/* y_output_size 980 */
+	{0x034F, 0xd4},
+	{0x30BF, 0xAB},/* outif_enable[7], data_type[5:0](2Bh = bayer 10bit} */
+	{0x30C0, 0xA0},/* video_offset[7:4] 3260%12 */
+	{0x30C8, 0x06},/* video_data_length 1600 = 1304 * 1.25 */
+	{0x30C9, 0x5E},
+	/* Timing Configuration */
+	{0x0202, 0x03},
+	{0x0203, 0x14},
+	{0x0204, 0x00},
+	{0x0205, 0x80},
+	{0x0340, 0x03},/* Frame Length */
+	{0x0341, 0xE0},
+	{0x0342, 0x0A},/* 2738  Line Length */
+	{0x0343, 0xB2},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_snap_settings[] = {
+	/*Output Size (2608x1960)*/
+	{0x30A9, 0x03},/* Horizontal Binning Off */
+	{0x300E, 0xE8},/* Vertical Binning Off */
+	{0x0387, 0x01},/* y_odd_inc */
+	{0x034C, 0x0A},/* x_output size */
+	{0x034D, 0x30},
+	{0x034E, 0x07},/* y_output size */
+	{0x034F, 0xA8},
+	{0x30BF, 0xAB},/* outif_enable[7], data_type[5:0](2Bh = bayer 10bit} */
+	{0x30C0, 0x80},/* video_offset[7:4] 3260%12 */
+	{0x30C8, 0x0C},/* video_data_length 3260 = 2608 * 1.25 */
+	{0x30C9, 0xBC},
+	/*Timing configuration*/
+	{0x0202, 0x06},
+	{0x0203, 0x28},
+	{0x0204, 0x00},
+	{0x0205, 0x80},
+	{0x0340, 0x07},/* Frame Length */
+	{0x0341, 0xB4},
+	{0x0342, 0x0A},/* 2738 Line Length */
+	{0x0343, 0xB2},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_recommend_settings[] = {
+	/* Reset setting */
+	{0x0103, 0x01},
+	/* MIPI settings */
+	{0x30BD, 0x00},/* SEL_CCP[0] */
+	{0x3084, 0x15},/* SYNC Mode */
+	{0x30BE, 0x1A},/* M_PCLKDIV_AUTO[4], M_DIV_PCLK[3:0] */
+	{0x30C1, 0x01},/* pack video enable [0] */
+	{0x30EE, 0x02},/* DPHY enable [ 1] */
+	{0x3111, 0x86},/* Embedded data off [5] */
+
+	/* REC Settings */
+	/*CDS timing setting ... */
+	{0x3000, 0x05},
+	{0x3001, 0x03},
+	{0x3002, 0x08},
+	{0x3003, 0x0A},
+	{0x3004, 0x50},
+	{0x3005, 0x0E},
+	{0x3006, 0x5E},
+	{0x3007, 0x00},
+	{0x3008, 0x78},
+	{0x3009, 0x78},
+	{0x300A, 0x50},
+	{0x300B, 0x08},
+	{0x300C, 0x14},
+	{0x300D, 0x00},
+	{0x300E, 0xE8},
+	{0x300F, 0x82},
+	{0x301B, 0x77},
+
+	/* CDS option setting ... */
+	{0x3010, 0x00},
+	{0x3011, 0x3A},
+	{0x3029, 0x04},
+	{0x3012, 0x30},
+	{0x3013, 0xA0},
+	{0x3014, 0x00},
+	{0x3015, 0x00},
+	{0x3016, 0x30},
+	{0x3017, 0x94},
+	{0x3018, 0x70},
+	{0x301D, 0xD4},
+	{0x3021, 0x02},
+	{0x3022, 0x24},
+	{0x3024, 0x40},
+	{0x3027, 0x08},
+
+	/* Pixel option setting ...   */
+	{0x301C, 0x04},
+	{0x30D8, 0x3F},
+	{0x302B, 0x01},
+
+	{0x3070, 0x5F},
+	{0x3071, 0x00},
+	{0x3080, 0x04},
+	{0x3081, 0x38},
+
+	/* PLL settings */
+	{0x0305, 0x04},
+	{0x0306, 0x00},
+	{0x0307, 0x44},
+	{0x30B5, 0x00},
+	{0x30E2, 0x01},/* num lanes[1:0] = 2 */
+	{0x30F1, 0xB0},
+};
+
+static struct v4l2_subdev_info s5k4e1_subdev_info[] = {
+	{
+	.code   = V4L2_MBUS_FMT_SGRBG10_1X10,
+	.colorspace = V4L2_COLORSPACE_JPEG,
+	.fmt    = 1,
+	.order    = 0,
+	},
+	/* more can be supported, to be added later */
+};
+
+static struct msm_camera_i2c_conf_array s5k4e1_init_conf[] = {
+	{&s5k4e1_recommend_settings[0],
+	ARRAY_SIZE(s5k4e1_recommend_settings), 0, MSM_CAMERA_I2C_BYTE_DATA}
+};
+
+static struct msm_camera_i2c_conf_array s5k4e1_confs[] = {
+	{&s5k4e1_snap_settings[0],
+	ARRAY_SIZE(s5k4e1_snap_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&s5k4e1_prev_settings[0],
+	ARRAY_SIZE(s5k4e1_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+};
+
+static struct msm_sensor_output_info_t s5k4e1_dimensions[] = {
+	{
+		.x_output = 0xA30,
+		.y_output = 0x7A8,
+		.line_length_pclk = 0xAB2,
+		.frame_length_lines = 0x7B4,
+		.vt_pixel_clk = 816000000,
+		.op_pixel_clk = 816000000,
+		.binning_factor = 0,
+	},
+	{
+		.x_output = 0x518,
+		.y_output = 0x3D4,
+		.line_length_pclk = 0xAB2,
+		.frame_length_lines = 0x3E0,
+		.vt_pixel_clk = 816000000,
+		.op_pixel_clk = 816000000,
+		.binning_factor = 1,
+	},
+};
+
+static struct msm_camera_csi_params s5k4e1_csi_params = {
+	.data_format = CSI_10BIT,
+	.lane_cnt    = 1,
+	.lane_assign = 0xe4,
+	.dpcm_scheme = 0,
+	.settle_cnt  = 24,
+};
+
+static struct msm_camera_csi_params *s5k4e1_csi_params_array[] = {
+	&s5k4e1_csi_params,
+	&s5k4e1_csi_params,
+};
+
+static struct msm_sensor_output_reg_addr_t s5k4e1_reg_addr = {
+	.x_output = 0x034C,
+	.y_output = 0x034E,
+	.line_length_pclk = 0x0342,
+	.frame_length_lines = 0x0340,
+};
+
+static struct msm_sensor_id_info_t s5k4e1_id_info = {
+	.sensor_id_reg_addr = 0x0000,
+	.sensor_id = 0x4E10,
+};
+
+static struct msm_sensor_exp_gain_info_t s5k4e1_exp_gain_info = {
+	.coarse_int_time_addr = 0x0202,
+	.global_gain_addr = 0x0204,
+	.vert_offset = 4,
+};
+
+static inline uint8_t s5k4e1_byte(uint16_t word, uint8_t offset)
+{
+	return word >> (offset * BITS_PER_BYTE);
+}
+
+static int32_t s5k4e1_write_prev_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
+						uint16_t gain, uint32_t line)
+{
+	uint16_t max_legal_gain = 0x0200;
+	int32_t rc = 0;
+	static uint32_t fl_lines, offset;
+
+	pr_info("s5k4e1_write_prev_exp_gain :%d %d\n", gain, line);
+	offset = s_ctrl->sensor_exp_gain_info->vert_offset;
+	if (gain > max_legal_gain) {
+		CDBG("Max legal gain Line:%d\n", __LINE__);
+		gain = max_legal_gain;
+	}
+
+	/* Analogue Gain */
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->global_gain_addr,
+		s5k4e1_byte(gain, MSB),
+		MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->global_gain_addr + 1,
+		s5k4e1_byte(gain, LSB),
+		MSM_CAMERA_I2C_BYTE_DATA);
+
+	if (line > (s_ctrl->curr_frame_length_lines - offset)) {
+		fl_lines = line + offset;
+		s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_output_reg_addr->frame_length_lines,
+			s5k4e1_byte(fl_lines, MSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_output_reg_addr->frame_length_lines + 1,
+			s5k4e1_byte(fl_lines, LSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		/* Coarse Integration Time */
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+			s5k4e1_byte(line, MSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 1,
+			s5k4e1_byte(line, LSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+	} else if (line < (fl_lines - offset)) {
+		fl_lines = line + offset;
+		if (fl_lines < s_ctrl->curr_frame_length_lines)
+			fl_lines = s_ctrl->curr_frame_length_lines;
+
+		s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+		/* Coarse Integration Time */
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+			s5k4e1_byte(line, MSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 1,
+			s5k4e1_byte(line, LSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_output_reg_addr->frame_length_lines,
+			s5k4e1_byte(fl_lines, MSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_output_reg_addr->frame_length_lines + 1,
+			s5k4e1_byte(fl_lines, LSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+	} else {
+		fl_lines = line+4;
+		s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+		/* Coarse Integration Time */
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+			s5k4e1_byte(line, MSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+			s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 1,
+			s5k4e1_byte(line, LSB),
+			MSM_CAMERA_I2C_BYTE_DATA);
+		s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+	}
+	return rc;
+}
+
+static int32_t s5k4e1_write_pict_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
+		uint16_t gain, uint32_t line)
+{
+	uint16_t max_legal_gain = 0x0200;
+	uint16_t min_ll_pck = 0x0AB2;
+	uint32_t ll_pck, fl_lines;
+	uint32_t ll_ratio;
+	uint8_t gain_msb, gain_lsb;
+	uint8_t intg_time_msb, intg_time_lsb;
+	uint8_t ll_pck_msb, ll_pck_lsb;
+
+	if (gain > max_legal_gain) {
+		CDBG("Max legal gain Line:%d\n", __LINE__);
+		gain = max_legal_gain;
+	}
+
+	gain = 32;
+	line = 1465;
+	pr_info("s5k4e1_write_exp_gain : gain = %d line = %d\n", gain, line);
+	line = (uint32_t) (line * s_ctrl->fps_divider);
+	fl_lines = s_ctrl->curr_frame_length_lines * s_ctrl->fps_divider / Q10;
+	ll_pck = s_ctrl->curr_line_length_pclk;
+
+	if (fl_lines < (line / Q10))
+		ll_ratio = (line / (fl_lines - 4));
+	else
+		ll_ratio = Q10;
+
+	ll_pck = ll_pck * ll_ratio / Q10;
+	line = line / ll_ratio;
+	if (ll_pck < min_ll_pck)
+		ll_pck = min_ll_pck;
+
+	gain_msb = (uint8_t) ((gain & 0xFF00) >> 8);
+	gain_lsb = (uint8_t) (gain & 0x00FF);
+
+	intg_time_msb = (uint8_t) ((line & 0xFF00) >> 8);
+	intg_time_lsb = (uint8_t) (line & 0x00FF);
+
+	ll_pck_msb = (uint8_t) ((ll_pck & 0xFF00) >> 8);
+	ll_pck_lsb = (uint8_t) (ll_pck & 0x00FF);
+
+	s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->global_gain_addr,
+		gain_msb,
+		MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->global_gain_addr + 1,
+		gain_lsb,
+		MSM_CAMERA_I2C_BYTE_DATA);
+
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_output_reg_addr->line_length_pclk,
+		ll_pck_msb,
+		MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_output_reg_addr->line_length_pclk + 1,
+		ll_pck_lsb,
+		MSM_CAMERA_I2C_BYTE_DATA);
+
+	/* Coarse Integration Time */
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+		intg_time_msb,
+		MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 1,
+		intg_time_lsb,
+		MSM_CAMERA_I2C_BYTE_DATA);
+	s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+
+	return 0;
+}
+
+static const struct i2c_device_id s5k4e1_i2c_id[] = {
+	{SENSOR_NAME, (kernel_ulong_t)&s5k4e1_s_ctrl},
+	{ }
+};
+
+static struct i2c_driver s5k4e1_i2c_driver = {
+	.id_table = s5k4e1_i2c_id,
+	.probe  = msm_sensor_i2c_probe,
+	.driver = {
+		.name = SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client s5k4e1_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static int __init msm_sensor_init_module(void)
+{
+	return i2c_add_driver(&s5k4e1_i2c_driver);
+}
+
+static struct v4l2_subdev_core_ops s5k4e1_subdev_core_ops = {
+	.ioctl = msm_sensor_subdev_ioctl,
+	.s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops s5k4e1_subdev_video_ops = {
+	.enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops s5k4e1_subdev_ops = {
+	.core = &s5k4e1_subdev_core_ops,
+	.video  = &s5k4e1_subdev_video_ops,
+};
+
+static struct msm_sensor_fn_t s5k4e1_func_tbl = {
+	.sensor_start_stream = msm_sensor_start_stream,
+	.sensor_stop_stream = msm_sensor_stop_stream,
+	.sensor_group_hold_on = msm_sensor_group_hold_on,
+	.sensor_group_hold_off = msm_sensor_group_hold_off,
+	.sensor_set_fps = msm_sensor_set_fps,
+	.sensor_write_exp_gain = s5k4e1_write_prev_exp_gain,
+	.sensor_write_snapshot_exp_gain = s5k4e1_write_pict_exp_gain,
+	.sensor_setting = msm_sensor_setting1,
+	.sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+	.sensor_mode_init = msm_sensor_mode_init,
+	.sensor_get_output_info = msm_sensor_get_output_info,
+	.sensor_config = msm_sensor_config,
+	.sensor_power_up = msm_sensor_power_up,
+	.sensor_power_down = msm_sensor_power_down,
+};
+
+static struct msm_sensor_reg_t s5k4e1_regs = {
+	.default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+	.start_stream_conf = s5k4e1_start_settings,
+	.start_stream_conf_size = ARRAY_SIZE(s5k4e1_start_settings),
+	.stop_stream_conf = s5k4e1_stop_settings,
+	.stop_stream_conf_size = ARRAY_SIZE(s5k4e1_stop_settings),
+	.group_hold_on_conf = s5k4e1_groupon_settings,
+	.group_hold_on_conf_size = ARRAY_SIZE(s5k4e1_groupon_settings),
+	.group_hold_off_conf = s5k4e1_groupoff_settings,
+	.group_hold_off_conf_size =
+		ARRAY_SIZE(s5k4e1_groupoff_settings),
+	.init_settings = &s5k4e1_init_conf[0],
+	.init_size = ARRAY_SIZE(s5k4e1_init_conf),
+	.mode_settings = &s5k4e1_confs[0],
+	.output_settings = &s5k4e1_dimensions[0],
+	.num_conf = ARRAY_SIZE(s5k4e1_confs),
+};
+
+static struct msm_sensor_ctrl_t s5k4e1_s_ctrl = {
+	.msm_sensor_reg = &s5k4e1_regs,
+	.sensor_i2c_client = &s5k4e1_sensor_i2c_client,
+	.sensor_i2c_addr = 0x6C,
+	.sensor_output_reg_addr = &s5k4e1_reg_addr,
+	.sensor_id_info = &s5k4e1_id_info,
+	.sensor_exp_gain_info = &s5k4e1_exp_gain_info,
+	.cam_mode = MSM_SENSOR_MODE_INVALID,
+	.csic_params = &s5k4e1_csi_params_array[0],
+	.msm_sensor_mutex = &s5k4e1_mut,
+	.sensor_i2c_driver = &s5k4e1_i2c_driver,
+	.sensor_v4l2_subdev_info = s5k4e1_subdev_info,
+	.sensor_v4l2_subdev_info_size = ARRAY_SIZE(s5k4e1_subdev_info),
+	.sensor_v4l2_subdev_ops = &s5k4e1_subdev_ops,
+	.func_tbl = &s5k4e1_func_tbl,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Samsung 5MP Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
+
+
diff --git a/drivers/media/video/msm/wfd/Makefile b/drivers/media/video/msm/wfd/Makefile
index 7ea9db3..2b39e66 100644
--- a/drivers/media/video/msm/wfd/Makefile
+++ b/drivers/media/video/msm/wfd/Makefile
@@ -1,5 +1,4 @@
-#obj-$(CONFIG_MSM_WFD_V4L2) += wfd-ioctl.o
-#obj-$(CONFIG_MSM_WFD_V4L2) += enc-subdev.o
 obj-y += mdp-subdev.o
 obj-y += enc-subdev.o
+obj-y += vsg-subdev.o
 obj-y += wfd-ioctl.o
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index abba5d4..e3d9d2d 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -147,7 +147,6 @@
 	struct vb2_buffer *vbuf;
 	struct mem_region *mregion;
 	struct vcd_frame_data *frame_data = (struct vcd_frame_data *)info;
-	struct timespec ts;
 
 	if (!client_ctx) {
 		WFD_MSG_ERR("Client context is NULL\n");
@@ -190,9 +189,8 @@
 			break;
 		}
 
-		ktime_get_ts(&ts);
-		vbuf->v4l2_buf.timestamp.tv_sec = ts.tv_sec;
-		vbuf->v4l2_buf.timestamp.tv_usec = ts.tv_nsec/1000;
+		vbuf->v4l2_buf.timestamp =
+			ns_to_timeval(frame_data->time_stamp);
 
 		WFD_MSG_DBG("bytes used %d, ts: %d.%d, frame type is %d\n",
 				frame_data->data_len,
@@ -403,11 +401,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 +417,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 +905,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) {
@@ -968,8 +940,9 @@
 	vcd_property_hdr.prop_id = VCD_I_FRAME_RATE;
 	vcd_property_hdr.sz =
 				sizeof(struct vcd_property_frame_rate);
-	vcd_frame_rate.fps_denominator = frate->denominator;
-	vcd_frame_rate.fps_numerator = frate->numerator;
+	/* v4l2 passes in "fps" as "spf", so take reciprocal*/
+	vcd_frame_rate.fps_denominator = frate->numerator;
+	vcd_frame_rate.fps_numerator = frate->denominator;
 	rc = vcd_set_property(client_ctx->vcd_handle,
 					&vcd_property_hdr, &vcd_frame_rate);
 	if (rc)
@@ -1014,8 +987,9 @@
 					mregion->offset,
 					32,
 					mregion->size);
-	if (!rc) {
+	if (rc == (u32)false) {
 		WFD_MSG_ERR("Failed to insert outbuf in table\n");
+		rc = -EINVAL;
 		goto err;
 	}
 	WFD_MSG_DBG("size = %u, %p\n", mregion->size, mregion->kvaddr);
@@ -1066,14 +1040,15 @@
 	int rc = 0;
 	struct venc_inst *inst = sd->dev_priv;
 	struct video_client_ctx *client_ctx = &inst->venc_client;
-	struct mem_region *mregion = arg;
+	struct venc_buf_info *venc_buf = arg;
+	struct mem_region *mregion = venc_buf->mregion;
 	struct vcd_frame_data vcd_input_buffer = {0};
 
 	vcd_input_buffer.virtual = mregion->kvaddr;
 	vcd_input_buffer.frm_clnt_data = (u32)mregion;
 	vcd_input_buffer.ip_frm_tag = (u32)mregion;
 	vcd_input_buffer.data_len = mregion->size;
-	vcd_input_buffer.time_stamp = 0; /*TODO: Need to fix this*/
+	vcd_input_buffer.time_stamp = venc_buf->timestamp;
 	vcd_input_buffer.offset = 0;
 
 	rc = vcd_encode_frame(client_ctx->vcd_handle,
@@ -1233,9 +1208,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 +1242,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/enc-subdev.h b/drivers/media/video/msm/wfd/enc-subdev.h
index 890c973..0f7ca5f 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.h
+++ b/drivers/media/video/msm/wfd/enc-subdev.h
@@ -11,6 +11,9 @@
 *
 */
 
+#ifndef _WFD_ENC_SUBDEV_
+#define _WFD_ENC_SUBDEV_
+
 #include <media/v4l2-subdev.h>
 #include <media/videobuf2-core.h>
 #define VENC_MAGIC_IOCTL 'V'
@@ -30,6 +33,12 @@
 	u32 width;
 	u32 size;
 };
+
+struct venc_buf_info {
+	u64 timestamp;
+	struct mem_region *mregion;
+};
+
 struct venc_msg_ops {
 	void *cookie;
 	void *cbdata;
@@ -42,7 +51,7 @@
 #define OPEN  _IOR('V', 1, void *)
 #define CLOSE  _IO('V', 2)
 #define ENCODE_START  _IO('V', 3)
-#define ENCODE_FRAME  _IO('V', 4)
+#define ENCODE_FRAME  _IOW('V', 4, struct venc_buf_info *)
 #define PAUSE  _IO('V', 5)
 #define RESUME  _IO('V', 6)
 #define FLUSH  _IO('V', 7)
@@ -66,3 +75,6 @@
 extern int venc_init(struct v4l2_subdev *sd, u32 val);
 extern int venc_load_fw(struct v4l2_subdev *sd);
 extern long venc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
+
+
+#endif /* _WFD_ENC_SUBDEV_ */
diff --git a/drivers/media/video/msm/wfd/mdp-subdev.c b/drivers/media/video/msm/wfd/mdp-subdev.c
index 9fd8a8e..e519a4d 100644
--- a/drivers/media/video/msm/wfd/mdp-subdev.c
+++ b/drivers/media/video/msm/wfd/mdp-subdev.c
@@ -135,8 +135,9 @@
 	fbdata.priv = (uint32_t)binfo->cookie;
 
 	WFD_MSG_INFO("queue buffer to mdp with offset = %u,"
-			"fd = %u, priv = %u\n",
-			fbdata.offset, fbdata.memory_id, fbdata.priv);
+			"fd = %u, priv = %p, iova = %p\n",
+			fbdata.offset, fbdata.memory_id,
+			(void *)fbdata.priv, (void *)fbdata.iova);
 	rc = msm_fb_writeback_queue_buffer(inst->mdp, &fbdata);
 
 	if (rc)
diff --git a/drivers/media/video/msm/wfd/mdp-subdev.h b/drivers/media/video/msm/wfd/mdp-subdev.h
index a6b3bc4..081fead 100644
--- a/drivers/media/video/msm/wfd/mdp-subdev.h
+++ b/drivers/media/video/msm/wfd/mdp-subdev.h
@@ -11,6 +11,9 @@
 *
 */
 
+#ifndef _WFD_MDP_SUBDEV_
+#define _WFD_MDP_SUBDEV_
+
 #include <linux/videodev2.h>
 #include <media/v4l2-subdev.h>
 
@@ -30,6 +33,17 @@
 	u32 height;
 	u32 width;
 };
+
+static inline bool mdp_buf_info_equals(struct mdp_buf_info *a,
+		struct mdp_buf_info *b)
+{
+	return a->inst == b->inst
+		&& a->fd == b->fd
+		&& a->offset == b->offset
+		&& a->kvaddr == b->kvaddr
+		&& a->paddr == b->paddr;
+}
+
 #define MDP_Q_BUFFER  _IOW(MDP_MAGIC_IOCTL, 1, struct mdp_buf_info *)
 #define MDP_DQ_BUFFER  _IOR(MDP_MAGIC_IOCTL, 2, struct mdp_out_buf *)
 #define MDP_OPEN  _IOR(MDP_MAGIC_IOCTL, 3, void **)
@@ -39,3 +53,6 @@
 #define MDP_STOP  _IOR(MDP_MAGIC_IOCTL, 7, void *)
 extern int mdp_init(struct v4l2_subdev *sd, u32 val);
 extern long mdp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
+
+
+#endif /* _WFD_MDP_SUBDEV_ */
diff --git a/drivers/media/video/msm/wfd/vsg-subdev.c b/drivers/media/video/msm/wfd/vsg-subdev.c
new file mode 100644
index 0000000..53b6e20
--- /dev/null
+++ b/drivers/media/video/msm/wfd/vsg-subdev.c
@@ -0,0 +1,693 @@
+/* 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/hrtimer.h>
+#include <linux/time.h>
+#include <linux/list.h>
+#include <media/videobuf2-core.h>
+#include "enc-subdev.h"
+#include "vsg-subdev.h"
+#include "wfd-util.h"
+
+#define DEFAULT_FRAME_INTERVAL (66*NSEC_PER_MSEC)
+#define DEFAULT_MAX_FRAME_INTERVAL (1*NSEC_PER_SEC)
+#define DEFAULT_MODE ((enum vsg_modes)VSG_MODE_CFR)
+
+static int vsg_release_input_buffer(struct vsg_context *context,
+		struct vsg_buf_info *buf)
+{
+	WFD_MSG_DBG("Releasing frame with ts %lld ms, paddr %p\n",
+			timespec_to_ns(&buf->time),
+			(void *)buf->mdp_buf_info.paddr);
+
+	if (buf->flags & VSG_NEVER_RELEASE)
+		WFD_MSG_WARN("Warning releasing buffer that's"
+				"not supposed to be released\n");
+
+	return context->vmops.release_input_frame(context->vmops.cbdata,
+			buf);
+
+}
+
+static int vsg_encode_frame(struct vsg_context *context,
+		struct vsg_buf_info *buf)
+{
+	WFD_MSG_DBG("Encoding frame with ts %lld ms, paddr %p\n",
+			timespec_to_ns(&buf->time),
+			(void *)buf->mdp_buf_info.paddr);
+
+	return context->vmops.encode_frame(context->vmops.cbdata,
+			buf);
+}
+
+static void vsg_set_last_buffer(struct vsg_context *context,
+		struct vsg_buf_info *buf)
+{
+	if (buf->flags & VSG_NEVER_SET_LAST_BUFFER)
+		WFD_MSG_WARN("Shouldn't be setting this to last buffer\n");
+
+	/* Update the last buffer and memcpy the data into the back up buffer*/
+	context->last_buffer = buf;
+
+	WFD_MSG_DBG("Setting last buffer to paddr %p\n",
+			(void *)buf->mdp_buf_info.paddr);
+
+	if (context->regen_buffer) {
+		int buf_size;
+		void *cookie;
+
+		/*FIXME: Somewhat hacky, looking into cookie */
+		cookie = buf->mdp_buf_info.cookie;
+		buf_size = ((struct mem_region *)cookie)->size;
+
+		memcpy((void *)context->regen_buffer->mdp_buf_info.kvaddr,
+				(void *)buf->mdp_buf_info.kvaddr,
+				buf_size);
+		context->send_regen_buffer = false;
+	}
+}
+
+static void vsg_work_func(struct work_struct *task)
+{
+	struct vsg_work *work =
+		container_of(task, struct vsg_work, work);
+	struct vsg_context *context = work->context;
+	struct vsg_buf_info *buf_info = NULL, *temp = NULL;
+	int rc = 0;
+	mutex_lock(&context->mutex);
+
+	if (list_empty(&context->free_queue.node)) {
+		WFD_MSG_DBG("%s: queue empty doing nothing\n", __func__);
+		goto err_skip_encode;
+	} else if (context->stopped) {
+		WFD_MSG_DBG("%s: vsg is stopped doing nothing\n", __func__);
+		goto err_skip_encode;
+	}
+
+	buf_info = list_first_entry(&context->free_queue.node,
+			struct vsg_buf_info, node);
+	list_del(&buf_info->node);
+	INIT_LIST_HEAD(&buf_info->node);
+
+	ktime_get_ts(&buf_info->time);
+	mod_timer(&context->threshold_timer, jiffies +
+			nsecs_to_jiffies(context->max_frame_interval));
+
+	list_for_each_entry(temp, &context->busy_queue.node, node) {
+		if (mdp_buf_info_equals(&temp->mdp_buf_info,
+					&buf_info->mdp_buf_info)) {
+			WFD_MSG_DBG("Buffer %p already in queue "
+				"to be encoded, delaying encoding\n",
+				(void *)temp->mdp_buf_info.paddr);
+			list_add(&buf_info->node, &context->free_queue.node);
+			/* just skip the push to encoder*/
+			goto err_skip_encode;
+		}
+	}
+
+	mutex_unlock(&context->mutex);
+	rc = vsg_encode_frame(context, buf_info);
+	if (rc < 0) {
+		WFD_MSG_ERR("frame encode failed");
+		goto err_encode_fail;
+	}
+	mutex_lock(&context->mutex);
+
+	list_add_tail(&buf_info->node, &context->busy_queue.node);
+err_skip_encode:
+	mutex_unlock(&context->mutex);
+err_encode_fail:
+	kfree(work);
+}
+
+static void vsg_timer_helper_func(struct work_struct *task)
+{
+	struct vsg_work *work =
+		container_of(task, struct vsg_work, work);
+	struct vsg_work *new_work = NULL;
+	struct vsg_context *context = work->context;
+	int num_bufs_to_queue = 1, c = 0;
+
+	mutex_lock(&context->mutex);
+
+	if (context->stopped)
+		goto err_locked;
+
+	if (list_empty(&context->free_queue.node)
+		&& context->last_buffer) {
+		struct vsg_buf_info *info = NULL, *buf_to_encode = NULL;
+
+		if (context->mode == VSG_MODE_CFR)
+			num_bufs_to_queue = 1;
+		else if (context->mode == VSG_MODE_VFR)
+			num_bufs_to_queue = 2;
+
+		for (c = 0; c < num_bufs_to_queue; ++c) {
+			info = kzalloc(sizeof(*info), GFP_KERNEL);
+
+			if (!info) {
+				WFD_MSG_ERR("Couldn't allocate memory in %s\n",
+					__func__);
+				goto err_locked;
+			}
+
+			if (context->regen_buffer) {
+				if (context->send_regen_buffer) {
+					buf_to_encode =
+						context->regen_buffer;
+				} else {
+					buf_to_encode = context->last_buffer;
+				}
+
+				context->send_regen_buffer =
+					!context->send_regen_buffer;
+			} else {
+				WFD_MSG_WARN("Have no regen buffer\n");
+				buf_to_encode = context->last_buffer;
+			}
+
+			info->mdp_buf_info = buf_to_encode->mdp_buf_info;
+			info->flags = buf_to_encode->flags;
+			INIT_LIST_HEAD(&info->node);
+			list_add_tail(&info->node, &context->free_queue.node);
+			WFD_MSG_DBG("Regenerated frame with paddr %p\n",
+				(void *)info->mdp_buf_info.paddr);
+		}
+	}
+
+	for (c = 0; c < num_bufs_to_queue; ++c) {
+		new_work = kzalloc(sizeof(*new_work), GFP_KERNEL);
+		if (!new_work) {
+			WFD_MSG_ERR("Unable to allocate memory"
+					"to queue buffer\n");
+			goto err_locked;
+		}
+
+		INIT_WORK(&new_work->work, vsg_work_func);
+		new_work->context = context;
+		queue_work(context->work_queue, &new_work->work);
+	}
+
+err_locked:
+	mutex_unlock(&context->mutex);
+	kfree(work);
+}
+
+static void vsg_threshold_timeout_func(unsigned long data)
+{
+	struct vsg_context *context = (struct vsg_context *)data;
+	struct vsg_work *task = kzalloc(sizeof(*task), GFP_ATOMIC);
+
+	if (!task) {
+		WFD_MSG_ERR("Out of memory in %s", __func__);
+		goto threshold_err_bad_param;
+	} else if (!context) {
+		WFD_MSG_ERR("Context not proper in %s", __func__);
+		goto threshold_err_bad_param;
+	}
+
+	mod_timer(&context->threshold_timer, jiffies +
+			nsecs_to_jiffies(context->max_frame_interval));
+
+	INIT_WORK(&task->work, vsg_timer_helper_func);
+	task->context = context;
+
+	queue_work(context->work_queue, &task->work);
+threshold_err_bad_param:
+	return;
+}
+
+int vsg_init(struct v4l2_subdev *sd, u32 val)
+{
+	return 0;
+}
+
+static int vsg_open(struct v4l2_subdev *sd, void *arg)
+{
+	struct vsg_context *context = NULL;
+
+	if (!arg || !sd)
+		return -EINVAL;
+
+	context = kzalloc(sizeof(*context), GFP_KERNEL);
+	INIT_LIST_HEAD(&context->free_queue.node);
+	INIT_LIST_HEAD(&context->busy_queue.node);
+
+	context->vmops = *(struct vsg_msg_ops *)arg;
+	context->work_queue = create_singlethread_workqueue("v4l-vsg");
+
+	context->frame_interval = DEFAULT_FRAME_INTERVAL;
+	context->max_frame_interval = DEFAULT_MAX_FRAME_INTERVAL;
+
+	context->threshold_timer = (struct timer_list)
+		TIMER_INITIALIZER(vsg_threshold_timeout_func,
+				context->max_frame_interval,
+				(unsigned long)context);
+
+	context->last_buffer = context->regen_buffer = NULL;
+	context->send_regen_buffer = false;
+	context->mode = DEFAULT_MODE;
+	context->stopped = false;
+	mutex_init(&context->mutex);
+
+	sd->dev_priv = context;
+	return 0;
+}
+
+static int vsg_close(struct v4l2_subdev *sd)
+{
+	struct vsg_context *context = NULL;
+
+	if (!sd)
+		return -EINVAL;
+
+	context = (struct vsg_context *)sd->dev_priv;
+	destroy_workqueue(context->work_queue);
+	kfree(context->regen_buffer);
+	kfree(context);
+	return 0;
+}
+
+static int vsg_start(struct v4l2_subdev *sd)
+{
+	struct vsg_context *context = NULL;
+
+	if (!sd) {
+		WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+		return -EINVAL;
+	}
+
+	context = (struct vsg_context *)sd->dev_priv;
+	mod_timer(&context->threshold_timer, jiffies +
+			nsecs_to_jiffies(context->max_frame_interval));
+	return 0;
+}
+
+static int vsg_stop(struct v4l2_subdev *sd)
+{
+	struct vsg_context *context = NULL;
+
+	if (!sd) {
+		WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+		return -EINVAL;
+	}
+
+	context = (struct vsg_context *)sd->dev_priv;
+
+	mutex_lock(&context->mutex);
+	context->stopped = true;
+	{ /*delete pending buffers as we're not going to encode them*/
+		struct list_head *pos, *next;
+		list_for_each_safe(pos, next, &context->free_queue.node) {
+			struct vsg_buf_info *temp =
+				list_entry(pos, struct vsg_buf_info, node);
+			list_del(&temp->node);
+			kfree(temp);
+		}
+	}
+
+	del_timer_sync(&context->threshold_timer);
+
+	mutex_unlock(&context->mutex);
+
+	flush_workqueue(context->work_queue);
+	return 0;
+}
+
+static long vsg_queue_buffer(struct v4l2_subdev *sd, void *arg)
+{
+	struct vsg_context *context = NULL;
+	struct vsg_buf_info *buf_info = kzalloc(sizeof(*buf_info), GFP_KERNEL);
+	int rc = 0;
+	bool push = false;
+
+	if (!arg || !sd) {
+		WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+		rc = -EINVAL;
+		goto queue_err_bad_param;
+	} else if (!buf_info) {
+		WFD_MSG_ERR("ERROR, out of memory in %s\n", __func__);
+		rc = -ENOMEM;
+		goto queue_err_bad_param;
+	}
+
+	context = (struct vsg_context *)sd->dev_priv;
+	mutex_lock(&context->mutex);
+
+	*buf_info = *(struct vsg_buf_info *)arg;
+	INIT_LIST_HEAD(&buf_info->node);
+	buf_info->flags = 0;
+	ktime_get_ts(&buf_info->time);
+
+	WFD_MSG_DBG("Queue frame with paddr %p\n",
+			(void *)buf_info->mdp_buf_info.paddr);
+
+	{ /*return pending buffers as we're not going to encode them*/
+		struct list_head *pos, *next;
+		list_for_each_safe(pos, next, &context->free_queue.node) {
+			struct vsg_buf_info *temp =
+				list_entry(pos, struct vsg_buf_info, node);
+			bool is_last_buffer, is_regen_buffer;
+
+			is_last_buffer = context->last_buffer &&
+				mdp_buf_info_equals(
+					&context->last_buffer->mdp_buf_info,
+					&temp->mdp_buf_info);
+
+			is_regen_buffer = context->regen_buffer &&
+				mdp_buf_info_equals(
+					&context->regen_buffer->mdp_buf_info,
+					&temp->mdp_buf_info);
+
+			if (!is_last_buffer && !is_regen_buffer &&
+				!(temp->flags & VSG_NEVER_RELEASE)) {
+				vsg_release_input_buffer(context, temp);
+			}
+
+			list_del(&temp->node);
+			kfree(temp);
+		}
+	}
+
+	list_add_tail(&buf_info->node, &context->free_queue.node);
+
+	if (context->mode == VSG_MODE_VFR) {
+		if (!context->last_buffer)
+			push = true;
+		else {
+			struct timespec diff = timespec_sub(buf_info->time,
+					context->last_buffer->time);
+			struct timespec temp = ns_to_timespec(
+						context->frame_interval);
+
+			if (timespec_compare(&diff, &temp) >= 0)
+				push = true;
+		}
+	}
+
+	if (push) {
+		struct vsg_work *new_work =
+			kzalloc(sizeof(*new_work), GFP_KERNEL);
+
+		INIT_WORK(&new_work->work, vsg_work_func);
+		new_work->context = context;
+		queue_work(context->work_queue, &new_work->work);
+	}
+
+	mutex_unlock(&context->mutex);
+queue_err_bad_param:
+	if (rc < 0)
+		kfree(buf_info);
+
+	return rc;
+}
+
+static long vsg_return_ip_buffer(struct v4l2_subdev *sd, void *arg)
+{
+	struct vsg_context *context = NULL;
+	struct vsg_buf_info *buf_info, *last_buffer,
+			*regen_buffer, *expected_buffer;
+	int rc = 0;
+
+	if (!arg || !sd) {
+		WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+		rc = -EINVAL;
+		goto return_ip_buf_err_bad_param;
+	}
+
+	context = (struct vsg_context *)sd->dev_priv;
+	mutex_lock(&context->mutex);
+	buf_info = (struct vsg_buf_info *)arg;
+	last_buffer = context->last_buffer;
+	regen_buffer = context->regen_buffer;
+
+	expected_buffer = list_first_entry(&context->busy_queue.node,
+			struct vsg_buf_info, node);
+
+	WFD_MSG_DBG("Return frame with paddr %p\n",
+			(void *)buf_info->mdp_buf_info.paddr);
+
+	if (mdp_buf_info_equals(&expected_buffer->mdp_buf_info,
+				&buf_info->mdp_buf_info)) {
+		list_del(&expected_buffer->node);
+
+		if (!(expected_buffer->flags & VSG_NEVER_SET_LAST_BUFFER)) {
+			bool is_same_buffer = context->last_buffer &&
+				mdp_buf_info_equals(
+					&context->last_buffer->mdp_buf_info,
+					&expected_buffer->mdp_buf_info);
+
+			if (!context->last_buffer || !is_same_buffer) {
+				struct vsg_buf_info *old_last_buffer =
+					context->last_buffer;
+				if (context->last_buffer)
+					vsg_release_input_buffer(context,
+							context->last_buffer);
+				vsg_set_last_buffer(context, expected_buffer);
+				kfree(old_last_buffer);
+			}
+		} else
+			WFD_MSG_WARN("Couldn't set the last buffer\n");
+	} else {
+		WFD_MSG_ERR("Returned buffer %p is not latest buffer, "
+				"expected %p\n",
+				(void *)buf_info->mdp_buf_info.paddr,
+				(void *)expected_buffer->mdp_buf_info.paddr);
+		rc = -EINVAL;
+		goto return_ip_buf_bad_buf;
+	}
+
+return_ip_buf_bad_buf:
+	mutex_unlock(&context->mutex);
+return_ip_buf_err_bad_param:
+	return rc;
+}
+
+static long vsg_set_scratch_buffer(struct v4l2_subdev *sd, void *arg)
+{
+	struct vsg_context *context = NULL;
+	struct vsg_buf_info *buf_info;
+	struct vsg_buf_info *regen_buffer =
+		kzalloc(sizeof(*regen_buffer), GFP_KERNEL);
+	int rc = 0;
+
+	if (!arg || !sd) {
+		WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+		rc = -EINVAL;
+		goto set_scratch_buf_err_bad_param;
+	} else if (!regen_buffer) {
+		WFD_MSG_ERR("ERROR, out of memory in %s\n", __func__);
+		rc = -ENOMEM;
+		goto set_scratch_buf_err_bad_param;
+	}
+
+	context = (struct vsg_context *)sd->dev_priv;
+	buf_info = (struct vsg_buf_info *)arg;
+
+	mutex_lock(&context->mutex);
+	*regen_buffer = *buf_info;
+	regen_buffer->flags = VSG_NEVER_RELEASE | VSG_NEVER_SET_LAST_BUFFER;
+	context->regen_buffer = regen_buffer;
+	WFD_MSG_ERR("setting buffer with paddr %p as scratch buffer\n",
+			(void *)regen_buffer->mdp_buf_info.paddr);
+	mutex_unlock(&context->mutex);
+set_scratch_buf_err_bad_param:
+	return rc;
+}
+
+static long vsg_set_frame_interval(struct v4l2_subdev *sd, void *arg)
+{
+	struct vsg_context *context = NULL;
+	int64_t interval;
+
+	if (!arg || !sd) {
+		WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+		return -EINVAL;
+	}
+
+	context = (struct vsg_context *)sd->dev_priv;
+	interval = *(int64_t *)arg;
+
+	if (interval <= 0) {
+		WFD_MSG_ERR("ERROR, invalid interval %lld into %s\n",
+				interval, __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&context->mutex);
+
+	context->frame_interval = interval;
+	if (interval > context->max_frame_interval) {
+		WFD_MSG_WARN("Changing max frame interval from %lld to %lld\n",
+				context->max_frame_interval, interval);
+		context->max_frame_interval = interval;
+	}
+
+	mutex_unlock(&context->mutex);
+	return 0;
+}
+
+static long vsg_get_frame_interval(struct v4l2_subdev *sd, void *arg)
+{
+	struct vsg_context *context = NULL;
+
+	if (!arg || !sd) {
+		WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+		return -EINVAL;
+	}
+
+	context = (struct vsg_context *)sd->dev_priv;
+	mutex_lock(&context->mutex);
+	*(int64_t *)arg = context->frame_interval;
+	mutex_unlock(&context->mutex);
+
+	return 0;
+}
+
+static long vsg_set_max_frame_interval(struct v4l2_subdev *sd, void *arg)
+{
+	struct vsg_context *context = NULL;
+	int64_t interval;
+
+	if (!arg || !sd) {
+		WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+		return -EINVAL;
+	}
+
+	context = (struct vsg_context *)sd->dev_priv;
+	interval = *(int64_t *)arg;
+
+	if (interval <= 0) {
+		WFD_MSG_ERR("ERROR, invalid interval %lld into %s\n",
+				interval, __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&context->mutex);
+
+	context->max_frame_interval = interval;
+	if (interval < context->frame_interval) {
+		WFD_MSG_WARN("Changing frame interval from %lld to %lld\n",
+				context->frame_interval, interval);
+		context->frame_interval = interval;
+	}
+
+	mutex_unlock(&context->mutex);
+
+	return 0;
+}
+
+static long vsg_get_max_frame_interval(struct v4l2_subdev *sd, void *arg)
+{
+	struct vsg_context *context = NULL;
+
+	if (!arg || !sd) {
+		WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+		return -EINVAL;
+	}
+
+	context = (struct vsg_context *)sd->dev_priv;
+	mutex_lock(&context->mutex);
+	*(int64_t *)arg = context->max_frame_interval;
+	mutex_unlock(&context->mutex);
+
+	return 0;
+}
+
+static long vsg_set_mode(struct v4l2_subdev *sd, void *arg)
+{
+	struct vsg_context *context = NULL;
+	enum vsg_modes *mode = NULL;
+	int rc = 0;
+
+	if (!arg || !sd) {
+		WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+		rc = -EINVAL;
+		goto set_mode_err_bad_parm;
+	}
+
+	context = (struct vsg_context *)sd->dev_priv;
+	mutex_lock(&context->mutex);
+	mode = arg;
+
+	switch (*mode) {
+	case VSG_MODE_CFR:
+		context->max_frame_interval = context->frame_interval;
+		/*fall through*/
+	case VSG_MODE_VFR:
+		context->mode = *mode;
+		break;
+	default:
+		context->mode = DEFAULT_MODE;
+		rc = -EINVAL;
+		goto set_mode_err_bad_mode;
+		break;
+	}
+
+set_mode_err_bad_mode:
+	mutex_unlock(&context->mutex);
+set_mode_err_bad_parm:
+	return rc;
+}
+
+long vsg_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+	int rc = 0;
+
+	WFD_MSG_DBG("VSG ioctl: %d\n", cmd);
+	if (sd == NULL)
+		return -EINVAL;
+
+	switch (cmd) {
+	case VSG_OPEN:
+		rc = vsg_open(sd, arg);
+		break;
+	case VSG_CLOSE:
+		rc = vsg_close(sd);
+		break;
+	case VSG_START:
+		rc = vsg_start(sd);
+		break;
+	case VSG_STOP:
+		rc = vsg_stop(sd);
+		break;
+	case VSG_Q_BUFFER:
+		rc = vsg_queue_buffer(sd, arg);
+		break;
+	case VSG_RETURN_IP_BUFFER:
+		rc = vsg_return_ip_buffer(sd, arg);
+		break;
+	case VSG_SET_SCRATCH_BUFFER:
+		rc = vsg_set_scratch_buffer(sd, arg);
+		break;
+	case VSG_GET_FRAME_INTERVAL:
+		rc = vsg_get_frame_interval(sd, arg);
+		break;
+	case VSG_SET_FRAME_INTERVAL:
+		rc = vsg_set_frame_interval(sd, arg);
+		break;
+	case VSG_GET_MAX_FRAME_INTERVAL:
+		rc = vsg_get_max_frame_interval(sd, arg);
+		break;
+	case VSG_SET_MAX_FRAME_INTERVAL:
+		rc = vsg_set_max_frame_interval(sd, arg);
+		break;
+	case VSG_SET_MODE:
+		rc = vsg_set_mode(sd, arg);
+		break;
+	default:
+		rc = -ENOTSUPP;
+		break;
+	}
+
+	return rc;
+}
diff --git a/drivers/media/video/msm/wfd/vsg-subdev.h b/drivers/media/video/msm/wfd/vsg-subdev.h
new file mode 100644
index 0000000..1db45e8
--- /dev/null
+++ b/drivers/media/video/msm/wfd/vsg-subdev.h
@@ -0,0 +1,88 @@
+/* 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 _WFD_VSG_SUBDEV_
+#define _WFD_VSG_SUBDEV_
+
+#include <linux/videodev2.h>
+#include <linux/list.h>
+#include <linux/ktime.h>
+#include <linux/workqueue.h>
+#include <media/v4l2-subdev.h>
+#include "mdp-subdev.h"
+
+#define VSG_MAGIC_IOCTL 'V'
+
+enum vsg_flags {
+	VSG_NEVER_RELEASE = 1<<0,
+	VSG_NEVER_SET_LAST_BUFFER = 1<<1,
+};
+
+enum vsg_modes {
+	VSG_MODE_CFR,
+	VSG_MODE_VFR,
+};
+
+struct vsg_buf_info {
+	struct mdp_buf_info mdp_buf_info;
+	struct timespec time;
+	/* Internal */
+	struct list_head node;
+	uint32_t flags;
+};
+
+struct vsg_msg_ops {
+	void *cbdata;
+	int (*encode_frame)(void *cbdata, struct vsg_buf_info *buffer);
+	int (*release_input_frame)(void *cbdata, struct vsg_buf_info *buffer);
+};
+
+struct vsg_context {
+	struct vsg_buf_info	free_queue, busy_queue;
+	struct vsg_msg_ops vmops;
+	/* All time related values below in nanosecs */
+	int64_t frame_interval, max_frame_interval;
+	struct workqueue_struct *work_queue;
+	struct timer_list threshold_timer;
+	struct mutex mutex;
+	struct vsg_buf_info *last_buffer, *regen_buffer;
+	bool send_regen_buffer;
+	int mode;
+	bool stopped;
+};
+
+struct vsg_work {
+	struct vsg_context *context;
+	struct work_struct work;
+};
+
+#define VSG_OPEN  _IO(VSG_MAGIC_IOCTL, 1)
+#define VSG_CLOSE  _IO(VSG_MAGIC_IOCTL, 2)
+#define VSG_START  _IO(VSG_MAGIC_IOCTL, 3)
+#define VSG_STOP  _IO(VSG_MAGIC_IOCTL, 4)
+#define VSG_Q_BUFFER  _IOW(VSG_MAGIC_IOCTL, 5, struct vsg_buf_info *)
+#define VSG_DQ_BUFFER  _IOR(VSG_MAGIC_IOCTL, 6, struct vsg_out_buf *)
+#define VSG_RETURN_IP_BUFFER _IOW(VSG_MAGIC_IOCTL, 7, struct vsg_buf_info *)
+#define VSG_ENCODE_DONE _IO(VSG_MAGIC_IOCTL, 8)
+#define VSG_SET_SCRATCH_BUFFER _IOW(VSG_MAGIC_IOCTL, 9, struct vsg_buf_info *)
+/* Time related arguments for frame interval ioctls are always in nanosecs*/
+#define VSG_SET_FRAME_INTERVAL _IOW(VSG_MAGIC_IOCTL, 10, int64_t *)
+#define VSG_GET_FRAME_INTERVAL _IOR(VSG_MAGIC_IOCTL, 11, int64_t *)
+#define VSG_SET_MAX_FRAME_INTERVAL _IOW(VSG_MAGIC_IOCTL, 12, int64_t *)
+#define VSG_GET_MAX_FRAME_INTERVAL _IOR(VSG_MAGIC_IOCTL, 13, int64_t *)
+#define VSG_SET_MODE _IOW(VSG_MAGIC_IOCTL, 14, enum vsg_modes *)
+
+extern int vsg_init(struct v4l2_subdev *sd, u32 val);
+extern long vsg_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
+
+#endif /* _WFD_VSG_SUBDEV_ */
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
index 27a8888..315705c 100644
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -21,6 +21,7 @@
 #include <linux/android_pmem.h>
 #include <linux/sched.h>
 #include <linux/kthread.h>
+#include <linux/time.h>
 
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
@@ -31,12 +32,14 @@
 #include "wfd-util.h"
 #include "mdp-subdev.h"
 #include "enc-subdev.h"
+#include "vsg-subdev.h"
 
 #define WFD_VERSION KERNEL_VERSION(0, 0, 1)
 #define DEFAULT_WFD_WIDTH 640
 #define DEFAULT_WFD_HEIGHT 480
-#define MIN_BUF_COUNT 2
-#define VENC_INPUT_BUFFERS 3
+#define VSG_SCRATCH_BUFFERS 1
+#define MDP_WRITEBACK_BUFFERS 3
+#define VENC_INPUT_BUFFERS (VSG_SCRATCH_BUFFERS + MDP_WRITEBACK_BUFFERS)
 
 struct wfd_device {
 	struct platform_device *pdev;
@@ -44,6 +47,7 @@
 	struct video_device *pvdev;
 	struct v4l2_subdev mdp_sdev;
 	struct v4l2_subdev enc_sdev;
+	struct v4l2_subdev vsg_sdev;
 };
 
 struct mem_info {
@@ -116,7 +120,8 @@
 	struct mem_region *mregion;
 	int rc;
 	unsigned long flags;
-	struct mdp_buf_info buf = {0};
+	struct mdp_buf_info mdp_buf = {0};
+	struct vsg_buf_info vsg_buf = {};
 	spin_lock_irqsave(&inst->inst_lock, flags);
 	if (inst->input_bufs_allocated) {
 		spin_unlock_irqrestore(&inst->inst_lock, flags);
@@ -133,27 +138,44 @@
 		if (rc) {
 			WFD_MSG_ERR("Failed to allocate input memory."
 				" This error causes memory leak!!!\n");
-			break;
+			goto alloc_fail;
 		}
 		WFD_MSG_DBG("NOTE: paddr = %p, kvaddr = %p\n", mregion->paddr,
 					mregion->kvaddr);
 		list_add_tail(&mregion->list, &inst->input_mem_list);
-		buf.inst = inst->mdp_inst;
-		buf.cookie = mregion;
-		buf.kvaddr = (u32) mregion->kvaddr;
-		buf.paddr = (u32) mregion->paddr;
-		rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
-				MDP_Q_BUFFER, (void *)&buf);
-		if (rc) {
-			WFD_MSG_ERR("Unable to queue the buffer to mdp\n");
-			break;
+
+		mdp_buf.inst = inst->mdp_inst;
+		mdp_buf.cookie = mregion;
+		mdp_buf.kvaddr = (u32) mregion->kvaddr;
+		mdp_buf.paddr = (u32) mregion->paddr;
+		vsg_buf.mdp_buf_info = mdp_buf;
+
+		if (i < MDP_WRITEBACK_BUFFERS) {
+			rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
+					MDP_Q_BUFFER, (void *)&mdp_buf);
+			if (rc) {
+				WFD_MSG_ERR("Unable to queue the"
+						" buffer to mdp\n");
+				break;
+			}
+		} else /*if (i < VSG_SCRATCH_BUFFERS*/ {
+			rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core, ioctl,
+					VSG_SET_SCRATCH_BUFFER,
+					(void *)&vsg_buf);
+			if (rc) {
+				WFD_MSG_ERR("Unable to set scratch"
+						" buffer to vsg\n");
+				break;
+			}
 		}
 	}
 	rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
 			ALLOC_RECON_BUFFERS, NULL);
-	if (rc)
+	if (rc) {
 		WFD_MSG_ERR("Failed to allocate recon buffers\n");
-
+		goto alloc_fail;
+	}
+alloc_fail:
 	return rc;
 }
 void wfd_free_input_buffers(struct wfd_device *wfd_dev,
@@ -258,7 +280,7 @@
 		rc = wfd_allocate_input_buffers(wfd_dev, inst);
 		if (rc) {
 			WFD_MSG_ERR("Failed to allocate input buffers\n");
-			goto err;
+			goto free_input_bufs;
 		}
 		rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
 				SET_OUTPUT_BUFFER, (void *)&mregion);
@@ -270,7 +292,6 @@
 	return rc;
 free_input_bufs:
 	wfd_free_input_buffers(wfd_dev, inst);
-err:
 	return rc;
 }
 
@@ -294,6 +315,12 @@
 	struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
 	struct mem_info *minfo = vb2_plane_cookie(vb, 0);
 	struct mem_region mregion;
+
+	if (minfo == NULL) {
+		WFD_MSG_ERR("not freeing buffers since allocation failed");
+		return;
+	}
+
 	mregion.fd = minfo->fd;
 	mregion.offset = minfo->offset;
 	mregion.cookie = (u32)vb;
@@ -306,6 +333,7 @@
 	wfd_unregister_out_buf(inst, minfo);
 	wfd_free_input_buffers(wfd_dev, inst);
 }
+
 static int mdp_output_thread(void *data)
 {
 	int rc = 0;
@@ -313,11 +341,13 @@
 	struct wfd_inst *inst = filp->private_data;
 	struct wfd_device *wfd_dev =
 		(struct wfd_device *)video_drvdata(filp);
-	struct mdp_buf_info obuf = {inst->mdp_inst, 0, 0, 0};
+	struct mdp_buf_info obuf_mdp = {inst->mdp_inst, 0, 0, 0};
+	struct mem_region *mregion;
+	struct vsg_buf_info ibuf_vsg;
 	while (!kthread_should_stop()) {
 		WFD_MSG_DBG("waiting for mdp output\n");
 		rc = v4l2_subdev_call(&wfd_dev->mdp_sdev,
-			core, ioctl, MDP_DQ_BUFFER, (void *)&obuf);
+			core, ioctl, MDP_DQ_BUFFER, (void *)&obuf_mdp);
 
 		if (rc) {
 			WFD_MSG_ERR("Either streamoff called or"
@@ -325,8 +355,21 @@
 			break;
 		}
 
-		rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
-			ENCODE_FRAME, obuf.cookie);
+		mregion = obuf_mdp.cookie;
+		if (!mregion) {
+			WFD_MSG_ERR("mdp cookie is null\n");
+			rc = -EINVAL;
+			break;
+		}
+
+		ibuf_vsg.mdp_buf_info = obuf_mdp;
+		ibuf_vsg.mdp_buf_info.inst = inst->mdp_inst;
+		ibuf_vsg.mdp_buf_info.cookie = mregion;
+		ibuf_vsg.mdp_buf_info.kvaddr = (u32) mregion->kvaddr;
+		ibuf_vsg.mdp_buf_info.paddr = (u32) mregion->paddr;
+		rc = v4l2_subdev_call(&wfd_dev->vsg_sdev,
+			core, ioctl, VSG_Q_BUFFER, (void *)&ibuf_vsg);
+
 		if (rc) {
 			WFD_MSG_ERR("Failed to encode frame\n");
 			break;
@@ -348,20 +391,27 @@
 			ENCODE_START, (void *)inst->venc_inst);
 	if (rc) {
 		WFD_MSG_ERR("Failed to start encoder\n");
-		goto err;
+		goto subdev_start_fail;
+	}
+
+	rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core, ioctl,
+			VSG_START, NULL);
+	if (rc) {
+		WFD_MSG_ERR("Failed to start vsg\n");
+		goto subdev_start_fail;
 	}
 
 	inst->mdp_task = kthread_run(mdp_output_thread, priv_data,
 				"mdp_output_thread");
 	if (IS_ERR(inst->mdp_task)) {
 		rc = PTR_ERR(inst->mdp_task);
-		goto err;
+		goto subdev_start_fail;
 	}
 	rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
 			 MDP_START, (void *)inst->mdp_inst);
 	if (rc)
 		WFD_MSG_ERR("Failed to start MDP\n");
-err:
+subdev_start_fail:
 	return rc;
 }
 
@@ -377,6 +427,11 @@
 	if (rc)
 		WFD_MSG_ERR("Failed to stop MDP\n");
 
+	rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core, ioctl,
+			 VSG_STOP, NULL);
+	if (rc)
+		WFD_MSG_ERR("Failed to stop VSG\n");
+
 	kthread_stop(inst->mdp_task);
 	rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
 			ENCODE_STOP, (void *)inst->venc_inst);
@@ -441,8 +496,17 @@
 
 static const struct v4l2_subdev_ops enc_subdev_ops = {
 	.core = &enc_subdev_core_ops,
-}
-;
+};
+
+static const struct v4l2_subdev_core_ops vsg_subdev_core_ops = {
+	.init = vsg_init,
+	.ioctl = vsg_ioctl,
+};
+
+static const struct v4l2_subdev_ops vsg_subdev_ops = {
+	.core = &vsg_subdev_core_ops,
+};
+
 static int wfdioc_querycap(struct file *filp, void *fh,
 		struct v4l2_capability *cap) {
 	WFD_MSG_DBG("wfdioc_querycap: E\n");
@@ -476,6 +540,7 @@
 	spin_unlock_irqrestore(&inst->inst_lock, flags);
 	return 0;
 }
+
 static int wfdioc_s_fmt(struct file *filp, void *fh,
 			struct v4l2_format *fmt)
 {
@@ -490,16 +555,16 @@
 		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,
 				(void *)fmt);
 	if (rc) {
 		WFD_MSG_ERR("Failed to set format on encoder, rc = %d\n", rc);
-		goto err;
+		return rc;
 	}
 	breq.count = VENC_INPUT_BUFFERS;
 	breq.height = fmt->fmt.pix.height;
@@ -508,7 +573,7 @@
 			SET_BUFFER_REQ, (void *)&breq);
 	if (rc) {
 		WFD_MSG_ERR("Failed to set buffer reqs on encoder\n");
-		goto err;
+		return rc;
 	}
 	spin_lock_irqsave(&inst->inst_lock, flags);
 	inst->input_buf_size = breq.size;
@@ -521,7 +586,6 @@
 				(void *)&prop);
 	if (rc)
 		WFD_MSG_ERR("Failed to set height/width property on mdp\n");
-err:
 	return rc;
 }
 static int wfdioc_reqbufs(struct file *filp, void *fh,
@@ -542,13 +606,12 @@
 			GET_BUFFER_REQ, (void *)b);
 	if (rc) {
 		WFD_MSG_ERR("Failed to get buf reqs from encoder\n");
-		goto err;
+		return rc;
 	}
 	spin_lock_irqsave(&inst->inst_lock, flags);
 	inst->buf_count = b->count;
 	spin_unlock_irqrestore(&inst->inst_lock, flags);
 	rc = vb2_reqbufs(&inst->vid_bufq, b);
-err:
 	return rc;
 }
 static int wfd_register_out_buf(struct wfd_inst *inst,
@@ -593,12 +656,11 @@
 	rc = wfd_register_out_buf(inst, b);
 	if (rc) {
 		WFD_MSG_ERR("Failed to register buffer\n");
-		goto err;
+		return rc;
 	}
 	rc = vb2_qbuf(&inst->vid_bufq, b);
 	if (rc)
 		WFD_MSG_ERR("Failed to queue buffer\n");
-err:
 	return rc;
 }
 
@@ -634,6 +696,13 @@
 {
 	struct wfd_inst *inst = filp->private_data;
 	unsigned long flags;
+
+	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		WFD_MSG_ERR("stream off for buffer type = %d is not "
+			"supported.\n", i);
+		return -EINVAL;
+	}
+
 	spin_lock_irqsave(&inst->inst_lock, flags);
 	if (inst->streamoff) {
 		WFD_MSG_ERR("Module is already in streamoff state\n");
@@ -642,11 +711,6 @@
 	}
 	inst->streamoff = true;
 	spin_unlock_irqrestore(&inst->inst_lock, flags);
-	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		WFD_MSG_ERR("stream off for buffer type = %d is not "
-			"supported.\n", i);
-		return -EINVAL;
-	}
 	WFD_MSG_DBG("Calling videobuf_streamoff\n");
 	vb2_streamoff(&inst->vid_bufq, i);
 	return 0;
@@ -680,6 +744,148 @@
 		WFD_MSG_ERR("Failed to set encoder property\n");
 	return rc;
 }
+
+static int wfdioc_g_parm(struct file *filp, void *fh,
+		struct v4l2_streamparm *a)
+{
+	int rc = 0;
+	struct wfd_device *wfd_dev = video_drvdata(filp);
+	struct wfd_inst *inst = filp->private_data;
+	int64_t frame_interval = 0,
+		max_frame_interval = 0; /* both in nsecs*/
+	struct v4l2_qcom_frameskip frameskip, *usr_frameskip;
+
+	usr_frameskip = (struct v4l2_qcom_frameskip *)
+			a->parm.capture.extendedmode;
+
+	if (!usr_frameskip) {
+		rc = -EINVAL;
+		goto get_parm_fail;
+	}
+	rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core,
+			ioctl, VSG_GET_FRAME_INTERVAL, &frame_interval);
+
+	if (rc < 0)
+		goto get_parm_fail;
+
+	rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core,
+			ioctl, VSG_GET_MAX_FRAME_INTERVAL, &max_frame_interval);
+
+	if (rc < 0)
+		goto get_parm_fail;
+
+	frameskip = (struct v4l2_qcom_frameskip) {
+		.maxframeinterval = max_frame_interval,
+	};
+
+	a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->parm.capture = (struct v4l2_captureparm) {
+		.capability = V4L2_CAP_TIMEPERFRAME,
+		.capturemode = 0,
+		.timeperframe = (struct v4l2_fract) {
+			.numerator = frame_interval,
+			.denominator = NSEC_PER_SEC,
+		},
+		.readbuffers = inst->buf_count,
+		.extendedmode = (__u32)usr_frameskip,
+		.reserved = {0}
+	};
+
+	rc = copy_to_user((void *)a->parm.capture.extendedmode,
+			&frameskip, sizeof(frameskip));
+	if (rc < 0)
+		goto get_parm_fail;
+
+get_parm_fail:
+	return rc;
+}
+
+static int wfdioc_s_parm(struct file *filp, void *fh,
+		struct v4l2_streamparm *a)
+{
+	int rc = 0;
+	struct wfd_device *wfd_dev = video_drvdata(filp);
+	struct wfd_inst *inst = filp->private_data;
+	struct v4l2_qcom_frameskip frameskip;
+	int64_t frame_interval, max_frame_interval;
+	void *extendedmode = NULL;
+	enum vsg_modes mode = VSG_MODE_VFR;
+
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		rc = -ENOTSUPP;
+		goto set_parm_fail;
+	}
+
+	if (a->parm.capture.readbuffers == 0 ||
+		a->parm.capture.readbuffers == inst->buf_count) {
+		a->parm.capture.readbuffers = inst->buf_count;
+	} else {
+		rc = -EINVAL;
+		goto set_parm_fail;
+	}
+
+	extendedmode = (void *)a->parm.capture.extendedmode;
+	if (a->parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
+		if (a->parm.capture.timeperframe.denominator == 0) {
+			rc = -EINVAL;
+			goto set_parm_fail;
+		}
+		frame_interval =
+			a->parm.capture.timeperframe.numerator * NSEC_PER_SEC /
+			a->parm.capture.timeperframe.denominator;
+
+		rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core,
+				ioctl, VSG_SET_FRAME_INTERVAL,
+				&frame_interval);
+
+		if (rc)
+			goto set_parm_fail;
+
+		rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core,
+				ioctl, SET_FRAMERATE,
+				&a->parm.capture.timeperframe);
+
+		if (rc)
+			goto set_parm_fail;
+	}
+
+	if (a->parm.capture.capability & V4L2_CAP_QCOM_FRAMESKIP &&
+		extendedmode) {
+		rc = copy_from_user(&frameskip,
+				extendedmode, sizeof(frameskip));
+
+		if (rc)
+			goto set_parm_fail;
+
+		max_frame_interval = (int64_t)frameskip.maxframeinterval;
+		mode = VSG_MODE_VFR;
+
+		rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core,
+				ioctl, VSG_SET_MAX_FRAME_INTERVAL,
+				&max_frame_interval);
+
+		if (rc)
+			goto set_parm_fail;
+
+		rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core,
+				ioctl, VSG_SET_MODE, &mode);
+
+		if (rc)
+			goto set_parm_fail;
+	} else {
+		mode = VSG_MODE_CFR;
+		rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core,
+				ioctl, VSG_SET_MODE, &mode);
+
+		if (rc)
+			goto set_parm_fail;
+	}
+
+set_parm_fail:
+	return rc;
+}
+
 static const struct v4l2_ioctl_ops g_wfd_ioctl_ops = {
 	.vidioc_querycap = wfdioc_querycap,
 	.vidioc_s_fmt_vid_cap = wfdioc_s_fmt,
@@ -691,7 +897,8 @@
 	.vidioc_dqbuf = wfdioc_dqbuf,
 	.vidioc_g_ctrl = wfdioc_g_ctrl,
 	.vidioc_s_ctrl = wfdioc_s_ctrl,
-
+	.vidioc_g_parm = wfdioc_g_parm,
+	.vidioc_s_parm = wfdioc_s_parm,
 };
 static int wfd_set_default_properties(struct file *filp)
 {
@@ -707,37 +914,74 @@
 	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;
 }
-void venc_op_buffer_done(void *cookie, u32 status,
+static void venc_op_buffer_done(void *cookie, u32 status,
 			struct vb2_buffer *buf)
 {
 	WFD_MSG_DBG("yay!! got callback\n");
 	vb2_buffer_done(buf, VB2_BUF_STATE_DONE);
 }
-void venc_ip_buffer_done(void *cookie, u32 status,
+
+static void venc_ip_buffer_done(void *cookie, u32 status,
 			struct mem_region *mregion)
 {
 	struct file *filp = cookie;
 	struct wfd_inst *inst = filp->private_data;
-	struct mdp_buf_info buf = {0};
+	struct vsg_buf_info buf;
+	struct mdp_buf_info mdp_buf = {0};
 	struct wfd_device *wfd_dev =
 		(struct wfd_device *)video_drvdata(filp);
 	int rc = 0;
 	WFD_MSG_DBG("yay!! got ip callback\n");
-	buf.inst = inst->mdp_inst;
-	buf.cookie = mregion;
-	buf.kvaddr = (u32) mregion->kvaddr;
-	buf.paddr = (u32) mregion->paddr;
+	mdp_buf.inst = inst->mdp_inst;
+	mdp_buf.cookie = mregion;
+	mdp_buf.kvaddr = (u32) mregion->kvaddr;
+	mdp_buf.paddr = (u32) mregion->paddr;
+	buf.mdp_buf_info = mdp_buf;
+	rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core,
+			ioctl, VSG_RETURN_IP_BUFFER, (void *)&buf);
+	if (rc)
+		WFD_MSG_ERR("Failed to return buffer to vsg\n");
+}
+
+static int vsg_release_input_frame(void *cookie, struct vsg_buf_info *buf)
+{
+	struct file *filp = cookie;
+	struct wfd_device *wfd_dev =
+		(struct wfd_device *)video_drvdata(filp);
+	int rc = 0;
+
 	rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core,
-			ioctl, MDP_Q_BUFFER, (void *)&buf);
+			ioctl, MDP_Q_BUFFER, buf);
 	if (rc)
 		WFD_MSG_ERR("Failed to Q buffer to mdp\n");
 
+	return rc;
 }
+
+static int vsg_encode_frame(void *cookie, struct vsg_buf_info *buf)
+{
+	struct file *filp = cookie;
+	struct wfd_device *wfd_dev =
+		(struct wfd_device *)video_drvdata(filp);
+	struct venc_buf_info venc_buf;
+
+	if (!buf)
+		return -EINVAL;
+
+	venc_buf = (struct venc_buf_info){
+		.timestamp = timespec_to_ns(&buf->time),
+		.mregion = buf->mdp_buf_info.cookie
+	};
+
+	return v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
+			ENCODE_FRAME, &venc_buf);
+}
+
 void *wfd_vb2_mem_ops_get_userptr(void *alloc_ctx, unsigned long vaddr,
 					unsigned long size, int write)
 {
@@ -776,14 +1020,17 @@
 	int rc = 0;
 	struct wfd_inst *inst;
 	struct wfd_device *wfd_dev;
-	struct venc_msg_ops vmops;
+	struct venc_msg_ops enc_mops;
+	struct vsg_msg_ops vsg_mops;
+
 	WFD_MSG_DBG("wfd_open: E\n");
 	wfd_dev = video_drvdata(filp);
 	inst = kzalloc(sizeof(struct wfd_inst), GFP_KERNEL);
 	if (!inst || !wfd_dev) {
 		WFD_MSG_ERR("Could not allocate memory for "
 			"wfd instance\n");
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto err_mdp_open;
 	}
 	filp->private_data = inst;
 	spin_lock_init(&inst->inst_lock);
@@ -801,21 +1048,34 @@
 		WFD_MSG_ERR("Failed to load video encoder firmware: %d\n", rc);
 		goto err_venc;
 	}
-	vmops.op_buffer_done = venc_op_buffer_done;
-	vmops.ip_buffer_done = venc_ip_buffer_done;
-	vmops.cbdata = filp;
+	enc_mops.op_buffer_done = venc_op_buffer_done;
+	enc_mops.ip_buffer_done = venc_ip_buffer_done;
+	enc_mops.cbdata = filp;
 	rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl, OPEN,
-				(void *)&vmops);
-	if (rc || !vmops.cookie) {
+				(void *)&enc_mops);
+	if (rc || !enc_mops.cookie) {
 		WFD_MSG_ERR("Failed to open encoder subdevice: %d\n", rc);
 		goto err_venc;
 	}
-	inst->venc_inst = vmops.cookie;
+	inst->venc_inst = enc_mops.cookie;
+
+	vsg_mops.encode_frame = vsg_encode_frame;
+	vsg_mops.release_input_frame = vsg_release_input_frame;
+	vsg_mops.cbdata = filp;
+	rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core, ioctl, VSG_OPEN,
+				&vsg_mops);
+	if (rc) {
+		WFD_MSG_ERR("Failed to open vsg subdevice: %d\n", rc);
+		goto err_vsg_open;
+	}
 
 	wfd_initialize_vb2_queue(&inst->vid_bufq, filp);
 	wfd_set_default_properties(filp);
 	WFD_MSG_DBG("wfd_open: X\n");
 	return rc;
+
+err_vsg_open:
+	v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl, CLOSE, NULL);
 err_venc:
 	v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
 				MDP_CLOSE, (void *)inst->mdp_inst);
@@ -842,9 +1102,16 @@
 
 		rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
 				CLOSE, (void *)inst->venc_inst);
+
 		if (rc)
 			WFD_MSG_ERR("Failed to CLOSE enc subdev: %d\n", rc);
 
+		rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core, ioctl,
+				VSG_CLOSE, NULL);
+
+		if (rc)
+			WFD_MSG_ERR("Failed to CLOSE vsg subdev: %d\n", rc);
+
 		kfree(inst);
 	}
 	WFD_MSG_DBG("wfd_close: X\n");
@@ -869,7 +1136,8 @@
 	if (!wfd_dev) {
 		WFD_MSG_ERR("Could not allocate memory for "
 				"wfd device\n");
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto err_v4l2_registration;
 	}
 	pdev->dev.platform_data = (void *) wfd_dev;
 	rc = v4l2_device_register(&pdev->dev, &wfd_dev->v4l2_dev);
@@ -917,6 +1185,15 @@
 		goto err_venc_init;
 	}
 
+	v4l2_subdev_init(&wfd_dev->vsg_sdev, &vsg_subdev_ops);
+	strncpy(wfd_dev->vsg_sdev.name, "wfd-vsg", V4L2_SUBDEV_NAME_SIZE);
+	rc = v4l2_device_register_subdev(&wfd_dev->v4l2_dev,
+						&wfd_dev->vsg_sdev);
+	if (rc) {
+		WFD_MSG_ERR("Failed to register vsg subdevice: %d\n", rc);
+		goto err_venc_init;
+	}
+
 	WFD_MSG_DBG("__wfd_probe: X\n");
 	return rc;
 
diff --git a/drivers/media/video/msm/wfd/wfd-util.h b/drivers/media/video/msm/wfd/wfd-util.h
index 038a2cb..3fe03e6 100644
--- a/drivers/media/video/msm/wfd/wfd-util.h
+++ b/drivers/media/video/msm/wfd/wfd-util.h
@@ -16,15 +16,16 @@
 
 /*#define DEBUG_WFD*/
 
+#define WFD_TAG "wfd: "
 #ifdef DEBUG_WFD
-	#define WFD_MSG_INFO(fmt...) pr_info(fmt)
-	#define WFD_MSG_WARN(fmt...) pr_warning(fmt)
-	#define WFD_MSG_DBG(fmt...) pr_debug(fmt)
+	#define WFD_MSG_INFO(fmt...) pr_info(WFD_TAG fmt)
+	#define WFD_MSG_WARN(fmt...) pr_warning(WFD_TAG fmt)
+	#define WFD_MSG_DBG(fmt...) pr_debug(WFD_TAG fmt)
 #else
 	#define WFD_MSG_INFO(fmt...)
 	#define WFD_MSG_WARN(fmt...)
 	#define WFD_MSG_DBG(fmt...)
 #endif
-	#define WFD_MSG_ERR(fmt...) pr_err(KERN_ERR fmt)
-	#define WFD_MSG_CRIT(fmt...) pr_crit(KERN_CRIT fmt)
+	#define WFD_MSG_ERR(fmt...) pr_err(KERN_ERR WFD_TAG fmt)
+	#define WFD_MSG_CRIT(fmt...) pr_crit(KERN_CRIT WFD_TAG fmt)
 #endif
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..ac57418 100644
--- a/drivers/mfd/pm8038-core.c
+++ b/drivers/mfd/pm8038-core.c
@@ -268,6 +268,11 @@
 	.id             = -1,
 };
 
+static struct mfd_cell leds_cell __devinitdata = {
+	.name		= PM8XXX_LEDS_DEV_NAME,
+	.id		= -1,
+};
+
 static struct mfd_cell debugfs_cell __devinitdata = {
 	.name		= "pm8xxx-debug",
 	.id		= 0,
@@ -313,9 +318,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
@@ -501,6 +506,16 @@
 		}
 	}
 
+	if (pdata->leds_pdata) {
+		leds_cell.platform_data = pdata->leds_pdata;
+		leds_cell.pdata_size = sizeof(struct pm8xxx_led_platform_data);
+		ret = mfd_add_devices(pmic->dev, 0, &leds_cell, 1, NULL, 0);
+		if (ret) {
+			pr_err("Failed to add leds subdevice ret=%d\n", ret);
+			goto bail;
+		}
+	}
+
 	if (pdata->num_regulators > 0 && pdata->regulator_pdatas) {
 		ret = pm8038_add_regulators(pdata, pmic, irq_base);
 		if (ret) {
diff --git a/drivers/mfd/pm8821-core.c b/drivers/mfd/pm8821-core.c
index 8a556bd..ffcef99 100644
--- a/drivers/mfd/pm8821-core.c
+++ b/drivers/mfd/pm8821-core.c
@@ -29,7 +29,7 @@
 #define REG_IRQ_BASE		0x1BB
 
 #define PM8821_VERSION_MASK	0xFFF0
-#define PM8821_VERSION_VALUE	0x07F0
+#define PM8821_VERSION_VALUE	0x0BF0
 #define PM8821_REVISION_MASK	0x000F
 
 #define SINGLE_IRQ_RESOURCE(_name, _irq) \
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index fa30ef2..e4d8bd5 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-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
@@ -42,6 +42,7 @@
 #define PM8921_VERSION_MASK	0xFFF0
 #define PM8921_VERSION_VALUE	0x06F0
 #define PM8922_VERSION_VALUE	0x0AF0
+#define PM8917_VERSION_VALUE	0x12F0
 #define PM8921_REVISION_MASK	0x000F
 
 #define REG_PM8921_PON_CNTRL_3	0x01D
@@ -116,6 +117,9 @@
 	else if ((pmic->rev_registers & PM8921_VERSION_MASK)
 			== PM8922_VERSION_VALUE)
 		version = PM8XXX_VERSION_8922;
+	else if ((pmic->rev_registers & PM8921_VERSION_MASK)
+			== PM8917_VERSION_VALUE)
+		version = PM8XXX_VERSION_8917;
 
 	return version;
 }
@@ -138,7 +142,7 @@
 	.pmic_get_revision	= pm8921_get_revision,
 };
 
-static const struct resource gpio_cell_resources[] __devinitconst = {
+static struct resource gpio_cell_resources[] = {
 	[0] = {
 		.start = PM8921_IRQ_BLOCK_BIT(PM8921_GPIO_BLOCK_START, 0),
 		.end   = PM8921_IRQ_BLOCK_BIT(PM8921_GPIO_BLOCK_START, 0)
@@ -167,7 +171,7 @@
 	.num_resources	= ARRAY_SIZE(adc_cell_resources),
 };
 
-static const struct resource mpp_cell_resources[] __devinitconst = {
+static struct resource mpp_cell_resources[] = {
 	{
 		.start	= PM8921_IRQ_BLOCK_BIT(PM8921_MPP_BLOCK_START, 0),
 		.end	= PM8921_IRQ_BLOCK_BIT(PM8921_MPP_BLOCK_START, 0)
@@ -408,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),
@@ -545,7 +549,14 @@
 	}
 
 	if (pdata->gpio_pdata) {
-		pdata->gpio_pdata->gpio_cdata.ngpios = PM8921_NR_GPIOS;
+		if (version == PM8XXX_VERSION_8917) {
+			gpio_cell_resources[0].end = gpio_cell_resources[0].end
+							+ PM8917_NR_GPIOS
+							- PM8921_NR_GPIOS;
+			pdata->gpio_pdata->gpio_cdata.ngpios = PM8917_NR_GPIOS;
+		} else {
+			pdata->gpio_pdata->gpio_cdata.ngpios = PM8921_NR_GPIOS;
+		}
 		gpio_cell.platform_data = pdata->gpio_pdata;
 		gpio_cell.pdata_size = sizeof(struct pm8xxx_gpio_platform_data);
 		ret = mfd_add_devices(pmic->dev, 0, &gpio_cell, 1,
@@ -557,7 +568,14 @@
 	}
 
 	if (pdata->mpp_pdata) {
-		pdata->mpp_pdata->core_data.nmpps = PM8921_NR_MPPS;
+		if (version == PM8XXX_VERSION_8917) {
+			mpp_cell_resources[0].end = mpp_cell_resources[0].end
+							+ PM8917_NR_MPPS
+							- PM8921_NR_MPPS;
+			pdata->mpp_pdata->core_data.nmpps = PM8917_NR_MPPS;
+		} else {
+			pdata->mpp_pdata->core_data.nmpps = PM8921_NR_MPPS;
+		}
 		pdata->mpp_pdata->core_data.base_addr = REG_MPP_BASE;
 		mpp_cell.platform_data = pdata->mpp_pdata;
 		mpp_cell.pdata_size = sizeof(struct pm8xxx_mpp_platform_data);
@@ -665,12 +683,6 @@
 		goto bail;
 	}
 
-	ret = mfd_add_devices(pmic->dev, 0, &pwm_cell, 1, NULL, 0);
-	if (ret) {
-		pr_err("Failed to add pwm subdevice ret=%d\n", ret);
-		goto bail;
-	}
-
 	if (pdata->misc_pdata) {
 		misc_cell.platform_data = pdata->misc_pdata;
 		misc_cell.pdata_size = sizeof(struct pm8xxx_misc_platform_data);
@@ -682,16 +694,6 @@
 		}
 	}
 
-	if (pdata->leds_pdata) {
-		leds_cell.platform_data = pdata->leds_pdata;
-		leds_cell.pdata_size = sizeof(struct pm8xxx_led_platform_data);
-		ret = mfd_add_devices(pmic->dev, 0, &leds_cell, 1, NULL, 0);
-		if (ret) {
-			pr_err("Failed to add leds subdevice ret=%d\n", ret);
-			goto bail;
-		}
-	}
-
 	ret = mfd_add_devices(pmic->dev, 0, &thermal_alarm_cell, 1, NULL,
 				irq_base);
 	if (ret) {
@@ -708,16 +710,37 @@
 		goto bail;
 	}
 
-	if (pdata->vibrator_pdata) {
-		vibrator_cell.platform_data = pdata->vibrator_pdata;
-		vibrator_cell.pdata_size =
-				sizeof(struct pm8xxx_vibrator_platform_data);
-		ret = mfd_add_devices(pmic->dev, 0, &vibrator_cell, 1, NULL, 0);
+	if (version != PM8XXX_VERSION_8917) {
+		ret = mfd_add_devices(pmic->dev, 0, &pwm_cell, 1, NULL, 0);
 		if (ret) {
-			pr_err("Failed to add vibrator subdevice ret=%d\n",
-									ret);
+			pr_err("Failed to add pwm subdevice ret=%d\n", ret);
 			goto bail;
 		}
+
+		if (pdata->leds_pdata) {
+			leds_cell.platform_data = pdata->leds_pdata;
+			leds_cell.pdata_size =
+				sizeof(struct pm8xxx_led_platform_data);
+			ret = mfd_add_devices(pmic->dev, 0, &leds_cell,
+					      1, NULL, 0);
+			if (ret) {
+				pr_err("Failed to add leds subdevice ret=%d\n",
+						ret);
+				goto bail;
+			}
+		}
+
+		if (pdata->vibrator_pdata) {
+			vibrator_cell.platform_data = pdata->vibrator_pdata;
+			vibrator_cell.pdata_size =
+				sizeof(struct pm8xxx_vibrator_platform_data);
+			ret = mfd_add_devices(pmic->dev, 0, &vibrator_cell,
+					      1, NULL, 0);
+			if (ret) {
+				pr_err("Failed to add vibrator ret=%d\n", ret);
+				goto bail;
+			}
+		}
 	}
 
 	if (pdata->ccadc_pdata) {
@@ -768,6 +791,11 @@
 	[PM8XXX_REVISION_8922_2p0]	= "2.0",
 };
 
+static const char * const pm8917_rev_names[] = {
+	[PM8XXX_REVISION_8917_TEST]	= "test",
+	[PM8XXX_REVISION_8917_1p0]	= "1.0",
+};
+
 static int __devinit pm8921_probe(struct platform_device *pdev)
 {
 	const struct pm8921_platform_data *pdata = pdev->dev.platform_data;
@@ -823,9 +851,14 @@
 		if (revision >= 0 && revision < ARRAY_SIZE(pm8922_rev_names))
 			revision_name = pm8922_rev_names[revision];
 		pr_info("PMIC version: PM8922 rev %s\n", revision_name);
+	} else if (version == PM8XXX_VERSION_8917) {
+		if (revision >= 0 && revision < ARRAY_SIZE(pm8917_rev_names))
+			revision_name = pm8917_rev_names[revision];
+		pr_info("PMIC version: PM8917 rev %s\n", revision_name);
 	} else {
 		WARN_ON(version != PM8XXX_VERSION_8921
-			&& version != PM8XXX_VERSION_8922);
+			&& version != PM8XXX_VERSION_8922
+			&& version != PM8XXX_VERSION_8917);
 	}
 
 	/* Log human readable restart reason */
diff --git a/drivers/mfd/pm8xxx-irq.c b/drivers/mfd/pm8xxx-irq.c
index 5864b85..14c9ec4 100644
--- a/drivers/mfd/pm8xxx-irq.c
+++ b/drivers/mfd/pm8xxx-irq.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
@@ -221,6 +221,11 @@
 	master = block / 8;
 	irq_bit = pmirq % 8;
 
+	if (chip->config[pmirq] == 0) {
+		pr_warn("masking rouge irq=%d pmirq=%d\n", d->irq, pmirq);
+		chip->config[pmirq] = irq_bit << PM_IRQF_BITS_SHIFT;
+	}
+
 	config = chip->config[pmirq] | PM_IRQF_MASK_ALL;
 	pm8xxx_write_config_irq(chip, block, config);
 }
@@ -236,6 +241,11 @@
 	master = block / 8;
 	irq_bit = pmirq % 8;
 
+	if (chip->config[pmirq] == 0) {
+		pr_warn("mask acking rouge irq=%d pmirq=%d\n", d->irq, pmirq);
+		chip->config[pmirq] = irq_bit << PM_IRQF_BITS_SHIFT;
+	}
+
 	config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
 	pm8xxx_write_config_irq(chip, block, config);
 }
diff --git a/drivers/mfd/pm8xxx-misc.c b/drivers/mfd/pm8xxx-misc.c
index 7314c7e..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,105 @@
 }
 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;
+
+	rc = pm8xxx_writeb(chip->dev->parent, 0x0BD, 0x0F);
+	if (rc)
+		pr_err("pm8xxx_writeb failed for 0x0BD, rc=%d\n", rc);
+
+	rc = pm8xxx_writeb(chip->dev->parent, 0x001, 0xB4);
+	if (rc)
+		pr_err("pm8xxx_writeb failed for 0x001, rc=%d\n", rc);
+
+	pr_info("dVdd preloaded\n");
+
+	return rc;
+}
+
+/**
+ * pm8xxx_preload_dVdd - preload the dVdd regulator during off state.
+ *
+ * This can help to reduce fluctuations in the dVdd voltage during startup
+ * at the cost of additional off state current draw.
+ *
+ * This API should only be called if dVdd startup issues are suspected.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_preload_dVdd(void)
+{
+	struct pm8xxx_misc_chip *chip;
+	unsigned long flags;
+	int rc = 0;
+
+	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_8901:
+			rc = __pm8901_preload_dVdd(chip);
+			break;
+		default:
+			/* PMIC doesn't have preload_dVdd; do nothing. */
+			break;
+		}
+		if (rc) {
+			pr_err("preload_dVdd failed, rc=%d\n", rc);
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(pm8xxx_preload_dVdd);
+
 static int __devinit pm8xxx_misc_probe(struct platform_device *pdev)
 {
 	const struct pm8xxx_misc_platform_data *pdata = pdev->dev.platform_data;
diff --git a/drivers/mfd/pm8xxx-pwm.c b/drivers/mfd/pm8xxx-pwm.c
index 523d3b6..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,32 +155,32 @@
 #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	3  /* No default support for pre-divide = 6 */
+#define NUM_LPG_PRE_DIVIDE	4
 #define NUM_PWM_PRE_DIVIDE	2
 
-#define PRE_DIVIDE_0		2
-#define PRE_DIVIDE_1		3
-#define PRE_DIVIDE_2		5
-
-#define PRE_DIVIDE_MIN		PRE_DIVIDE_0
-#define PRE_DIVIDE_MAX		PRE_DIVIDE_2
+#define PRE_DIVIDE_1		1	/* v1 */
+#define PRE_DIVIDE_2		2
+#define PRE_DIVIDE_3		3
+#define PRE_DIVIDE_5		5
+#define PRE_DIVIDE_6		6
 
 static unsigned int pt_t[NUM_LPG_PRE_DIVIDE][NUM_CLOCKS] = {
-	{	PRE_DIVIDE_0 * NSEC_1024HZ,
-		PRE_DIVIDE_0 * NSEC_32768HZ,
-		PRE_DIVIDE_0 * NSEC_19P2MHZ,
-	},
-	{	PRE_DIVIDE_1 * NSEC_1024HZ,
-		PRE_DIVIDE_1 * NSEC_32768HZ,
-		PRE_DIVIDE_1 * NSEC_19P2MHZ,
-	},
 	{	PRE_DIVIDE_2 * NSEC_1024HZ,
 		PRE_DIVIDE_2 * NSEC_32768HZ,
 		PRE_DIVIDE_2 * NSEC_19P2MHZ,
 	},
+	{	PRE_DIVIDE_3 * NSEC_1024HZ,
+		PRE_DIVIDE_3 * NSEC_32768HZ,
+		PRE_DIVIDE_3 * NSEC_19P2MHZ,
+	},
+	{	PRE_DIVIDE_5 * NSEC_1024HZ,
+		PRE_DIVIDE_5 * NSEC_32768HZ,
+		PRE_DIVIDE_5 * NSEC_19P2MHZ,
+	},
+	{	PRE_DIVIDE_6 * NSEC_1024HZ,
+		PRE_DIVIDE_6 * NSEC_32768HZ,
+		PRE_DIVIDE_6 * NSEC_19P2MHZ,
+	},
 };
 
 /* Private data */
@@ -1337,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/misc/pmem.c b/drivers/misc/pmem.c
index 7ee7c11..f0d523e 100644
--- a/drivers/misc/pmem.c
+++ b/drivers/misc/pmem.c
@@ -1,7 +1,7 @@
 /* drivers/android/pmem.c
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -2594,6 +2594,7 @@
 {
 	int i, index = 0, id;
 	struct vm_struct *pmem_vma = NULL;
+	struct page *page;
 
 	if (id_count >= PMEM_MAX_DEVICES) {
 		pr_alert("pmem: %s: unable to register driver(%s) - no more "
@@ -2794,6 +2795,11 @@
 
 	pmem[id].base = allocate_contiguous_memory_nomap(pmem[id].size,
 		pmem[id].memory_type, PAGE_SIZE);
+	if (!pmem[id].base) {
+		pr_err("pmem: Cannot allocate from reserved memory for %s\n",
+		 pdata->name);
+		goto err_misc_deregister;
+	}
 
 	pr_info("allocating %lu bytes at %p (%lx physical) for %s\n",
 		pmem[id].size, pmem[id].vbase, pmem[id].base, pmem[id].name);
@@ -2810,7 +2816,7 @@
 			if (!pmem_vma) {
 				pr_err("pmem: Failed to allocate virtual space for "
 					"%s\n", pdata->name);
-				goto out_put_kobj;
+				goto err_free;
 			}
 			pr_err("pmem: Reserving virtual address range %lx - %lx for"
 				" %s\n", (unsigned long) pmem_vma->addr,
@@ -2821,7 +2827,12 @@
 	} else
 		pmem[id].area = NULL;
 
-	pmem[id].garbage_pfn = page_to_pfn(alloc_page(GFP_KERNEL));
+	page = alloc_page(GFP_KERNEL);
+	if (!page) {
+		pr_err("pmem: Failed to allocate page for %s\n", pdata->name);
+		goto cleanup_vm;
+	}
+	pmem[id].garbage_pfn = page_to_pfn(page);
 	atomic_set(&pmem[id].allocation_cnt, 0);
 
 	if (pdata->setup_region)
@@ -2835,6 +2846,12 @@
 
 	return 0;
 
+cleanup_vm:
+	remove_vm_area(pmem_vma);
+err_free:
+	free_contiguous_memory_by_paddr(pmem[id].base);
+err_misc_deregister:
+	misc_deregister(&pmem[id].dev);
 err_cant_register_device:
 out_put_kobj:
 	kobject_put(&pmem[id].kobj);
@@ -2872,6 +2889,19 @@
 	int id = pdev->id;
 	__free_page(pfn_to_page(pmem[id].garbage_pfn));
 	pm_runtime_disable(&pdev->dev);
+	if (pmem[id].vbase)
+		iounmap(pmem[id].vbase);
+	if (pmem[id].map_on_demand && !pmem[id].reusable && pmem[id].area)
+		free_vm_area(pmem[id].area);
+	if (pmem[id].base)
+		free_contiguous_memory_by_paddr(pmem[id].base);
+	kobject_put(&pmem[id].kobj);
+	if (pmem[id].allocator_type == PMEM_ALLOCATORTYPE_BUDDYBESTFIT)
+		kfree(pmem[id].allocator.buddy_bestfit.buddy_bitmap);
+	else if (pmem[id].allocator_type == PMEM_ALLOCATORTYPE_BITMAP) {
+		kfree(pmem[id].allocator.bitmap.bitmap);
+		kfree(pmem[id].allocator.bitmap.bitm_alloc);
+	}
 	misc_deregister(&pmem[id].dev);
 	return 0;
 }
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 57e5696..8f42e5b 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -43,6 +43,7 @@
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+#include <linux/pm_qos_params.h>
 
 #include <asm/cacheflush.h>
 #include <asm/div64.h>
@@ -148,6 +149,24 @@
 	return ret;
 }
 
+/* Prevent idle power collapse(pc) while operating in peripheral mode */
+static void msmsdcc_pm_qos_update_latency(struct msmsdcc_host *host, int vote)
+{
+	u32 swfi_latency = 0;
+
+	if (!host->plat->swfi_latency)
+		return;
+
+	swfi_latency = host->plat->swfi_latency + 1;
+
+	if (vote)
+		pm_qos_update_request(&host->pm_qos_req_dma,
+					swfi_latency);
+	else
+		pm_qos_update_request(&host->pm_qos_req_dma,
+					PM_QOS_DEFAULT_VALUE);
+}
+
 #ifdef CONFIG_MMC_MSM_SPS_SUPPORT
 static int msmsdcc_sps_reset_ep(struct msmsdcc_host *host,
 				struct msmsdcc_sps_ep_conn_data *ep);
@@ -2454,6 +2473,12 @@
 {
 	int rc;
 	struct device *dev = mmc->parent;
+	struct msmsdcc_host *host = mmc_priv(mmc);
+
+	msmsdcc_pm_qos_update_latency(host, 1);
+
+	if (mmc->card && mmc_card_sdio(mmc->card) && host->is_resumed)
+		return 0;
 
 	if (dev->power.runtime_status == RPM_SUSPENDING) {
 		if (mmc->suspend_task == current) {
@@ -2469,6 +2494,8 @@
 				__func__, rc);
 		return rc;
 	}
+
+	host->is_resumed = true;
 out:
 	return 0;
 }
@@ -2478,16 +2505,22 @@
 	int rc;
 	struct msmsdcc_host *host = mmc_priv(mmc);
 
+	msmsdcc_pm_qos_update_latency(host, 0);
+
+	if (mmc->card && mmc_card_sdio(mmc->card))
+		return 0;
+
 	if (host->plat->disable_runtime_pm)
 		return -ENOTSUPP;
-	if (mmc->card && mmc->card->type == MMC_TYPE_SDIO)
-		return -ENOTSUPP;
 
 	rc = pm_runtime_put_sync(mmc->parent);
 
 	if (rc < 0)
 		pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
 				__func__, rc);
+	else
+		host->is_resumed = false;
+
 	return rc;
 }
 #else
@@ -2496,6 +2529,8 @@
 	struct msmsdcc_host *host = mmc_priv(mmc);
 	unsigned long flags;
 
+	msmsdcc_pm_qos_update_latency(host, 1);
+
 	spin_lock_irqsave(&host->lock, flags);
 	if (!host->clks_on) {
 		msmsdcc_setup_clocks(host, true);
@@ -2511,8 +2546,10 @@
 	struct msmsdcc_host *host = mmc_priv(mmc);
 	unsigned long flags;
 
+	msmsdcc_pm_qos_update_latency(host, 0);
+
 	if (mmc->card && mmc_card_sdio(mmc->card))
-		return -ENOTSUPP;
+		return 0;
 
 	spin_lock_irqsave(&host->lock, flags);
 	if (host->clks_on) {
@@ -2780,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;
 
@@ -4048,6 +4084,11 @@
 	/* Apply Hard reset to SDCC to put it in power on default state */
 	msmsdcc_hard_reset(host);
 
+	/* pm qos request to prevent apps idle power collapse */
+	if (host->plat->swfi_latency)
+		pm_qos_add_request(&host->pm_qos_req_dma,
+			PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
+
 	ret = msmsdcc_vreg_init(host, true);
 	if (ret) {
 		pr_err("%s: msmsdcc_vreg_init() failed (%d)\n", __func__, ret);
@@ -4325,6 +4366,8 @@
 	msmsdcc_vreg_init(host, false);
  clk_disable:
 	clk_disable(host->clk);
+	if (host->plat->swfi_latency)
+		pm_qos_remove_request(&host->pm_qos_req_dma);
  clk_put:
 	clk_put(host->clk);
  pclk_disable:
@@ -4397,6 +4440,9 @@
 	if (!IS_ERR_OR_NULL(host->dfab_pclk))
 		clk_put(host->dfab_pclk);
 
+	if (host->plat->swfi_latency)
+		pm_qos_remove_request(&host->pm_qos_req_dma);
+
 	msmsdcc_vreg_init(host, false);
 
 	if (host->is_dma_mode) {
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index d128984..ee7a3e5 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -26,6 +26,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/wakelock.h>
 #include <linux/earlysuspend.h>
+#include <linux/pm_qos_params.h>
 #include <mach/sps.h>
 
 #include <asm/sizes.h>
@@ -383,6 +384,7 @@
 	unsigned int	dummy_52_sent;
 
 	unsigned int	sdio_irq_disabled;
+	bool		is_resumed;
 	struct wake_lock	sdio_wlock;
 	struct wake_lock	sdio_suspend_wlock;
 	unsigned int    sdcc_suspending;
@@ -395,6 +397,7 @@
 	bool tuning_needed;
 	bool sdio_gpio_lpm;
 	bool irq_wake_enabled;
+	struct pm_qos_request_list pm_qos_req_dma;
 };
 
 int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave);
diff --git a/drivers/net/msm_rmnet_bam.c b/drivers/net/msm_rmnet_bam.c
index a0924ed..401b63c 100644
--- a/drivers/net/msm_rmnet_bam.c
+++ b/drivers/net/msm_rmnet_bam.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
@@ -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;
 
@@ -311,7 +308,7 @@
 	/* if write() succeeds, skb access is unsafe in this process */
 	bam_ret = msm_bam_dmux_write(p->ch_id, skb);
 
-	if (bam_ret != 0 && bam_ret != -EAGAIN) {
+	if (bam_ret != 0 && bam_ret != -EAGAIN && bam_ret != -EFAULT) {
 		pr_err("[%s] %s: write returned error %d",
 			dev->name, __func__, bam_ret);
 		return -EPERM;
@@ -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,34 @@
 		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
+	 * the rest to the main ssr handling code when that happens later
+	 */
+	if (ret == -EFAULT) {
+		netif_carrier_off(dev);
+		dev_kfree_skb_any(skb);
+		ret = 0;
+		goto exit;
+	}
 
 	if (ret == -EAGAIN) {
 		/*
@@ -474,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)) {
@@ -482,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)
@@ -690,6 +724,10 @@
 
 	p = netdev_priv(netdevs[i]);
 	p->in_reset = 1;
+	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]);
@@ -729,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/net/wireless/libra/qcomwlan_pwrif.c b/drivers/net/wireless/libra/qcomwlan_pwrif.c
index 6dd603c..8268f24 100644
--- a/drivers/net/wireless/libra/qcomwlan_pwrif.c
+++ b/drivers/net/wireless/libra/qcomwlan_pwrif.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
@@ -69,6 +69,15 @@
 		1300000,
 		1250000,
 	};
+	static const int vregs_qwlan_peek_current[] = {
+		4000,
+		150000,
+		200000,
+		0,
+		32000,
+		130000,
+		0,
+	};
 	static const bool vregs_is_pin_controlled_default[] = {
 		1,
 		1,
@@ -180,6 +189,15 @@
 			}
 		}
 		if (on && !wlan_on) {
+			if (vregs_qwlan_peek_current[i]) {
+				rc = regulator_set_optimum_mode(vregs_qwlan[i],
+						vregs_qwlan_peek_current[i]);
+				if (rc < 0)
+					pr_err("vreg %s set optimum mode"
+						" failed to %d (%d)\n",
+						vregs_qwlan_name[i], rc,
+						 vregs_qwlan_peek_current[i]);
+			}
 			rc = regulator_enable(vregs_qwlan[i]);
 			if (rc < 0) {
 				pr_err("vreg %s enable failed (%d)\n",
@@ -195,6 +213,26 @@
 				}
 			}
 		} else if (!on && wlan_on) {
+
+			if (vregs_qwlan_peek_current[i]) {
+				/* For legacy reasons we pass 1mA current to
+				 * put regulator in LPM mode.
+				 */
+				rc = regulator_set_optimum_mode(vregs_qwlan[i],
+									 1000);
+				if (rc < 0)
+					pr_info("vreg %s set optimum mode"
+								"failed (%d)\n",
+						vregs_qwlan_name[i], rc);
+				rc = regulator_set_voltage(vregs_qwlan[i], 0 ,
+							vregs_qwlan_val_max[i]);
+				if (rc)
+					pr_err("regulator_set_voltage(%s)"
+								"failed (%d)\n",
+						vregs_qwlan_name[i], rc);
+
+			}
+
 			if (vregs_is_pin_controlled[i]) {
 				rc = regulator_disable(vregs_pc_qwlan[i]);
 				if (rc < 0) {
@@ -202,13 +240,16 @@
 						vregs_qwlan_pc_name[i], rc);
 					goto vreg_fail;
 				}
+				regulator_put(vregs_pc_qwlan[i]);
 			}
+
 			rc = regulator_disable(vregs_qwlan[i]);
 			if (rc < 0) {
 				pr_err("vreg %s disable failed (%d)\n",
 						vregs_qwlan_name[i], rc);
 				goto vreg_fail;
 			}
+			regulator_put(vregs_qwlan[i]);
 		}
 	}
 	if (on) {
diff --git a/drivers/net/wireless/wcnss/wcnss_riva.c b/drivers/net/wireless/wcnss/wcnss_riva.c
index fe6abf2..0939dd8 100644
--- a/drivers/net/wireless/wcnss/wcnss_riva.c
+++ b/drivers/net/wireless/wcnss/wcnss_riva.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
@@ -22,6 +22,7 @@
 #include <linux/semaphore.h>
 #include <linux/list.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
 #include <mach/msm_xo.h>
 #include <mach/msm_iomap.h>
 
@@ -60,11 +61,11 @@
 };
 
 static struct vregs_info iris_vregs[] = {
-	{"iris_vddio",  VREG_NULL_CONFIG, 0000000, 0, 0000000, 0,      NULL},
+	{"iris_vddio",  VREG_NULL_CONFIG, 1800000, 0, 1800000, 4000,   NULL},
 	{"iris_vddxo",  VREG_NULL_CONFIG, 1800000, 0, 1800000, 10000,  NULL},
 	{"iris_vddrfa", VREG_NULL_CONFIG, 1300000, 0, 1300000, 100000, NULL},
-	{"iris_vddpa",  VREG_NULL_CONFIG, 3000000, 0, 3000000, 515000, NULL},
-	{"iris_vdddig", VREG_NULL_CONFIG, 0000000, 0, 0000000, 0,      NULL},
+	{"iris_vddpa",  VREG_NULL_CONFIG, 2900000, 0, 3000000, 515000, NULL},
+	{"iris_vdddig", VREG_NULL_CONFIG, 1200000, 0, 1200000, 10000,  NULL},
 };
 
 static struct vregs_info riva_vregs[] = {
@@ -79,10 +80,15 @@
 };
 
 
-static int configure_iris_xo(bool use_48mhz_xo, int on)
+static int configure_iris_xo(struct device *dev, bool use_48mhz_xo, int on)
 {
 	u32 reg = 0;
 	int rc = 0;
+	struct clk *cxo = clk_get(dev, "cxo");
+	if (IS_ERR(cxo)) {
+		pr_err("Couldn't get cxo clock\n");
+		return PTR_ERR(cxo);
+	}
 
 	if (on) {
 		msm_riva_base = ioremap(MSM_RIVA_PHYS, SZ_256);
@@ -92,6 +98,11 @@
 		}
 
 		/* Enable IRIS XO */
+		rc = clk_prepare_enable(cxo);
+		if (rc) {
+			pr_err("cxo enable failed\n");
+			goto fail;
+		}
 		writel_relaxed(0, RIVA_PMU_CFG);
 		reg = readl_relaxed(RIVA_PMU_CFG);
 		reg |= RIVA_PMU_CFG_GC_BUS_MUX_SEL_TOP |
@@ -119,6 +130,7 @@
 		reg &= ~(RIVA_PMU_CFG_GC_BUS_MUX_SEL_TOP |
 				RIVA_PMU_CFG_IRIS_XO_CFG);
 		writel_relaxed(reg, RIVA_PMU_CFG);
+		clk_disable_unprepare(cxo);
 
 		if (!use_48mhz_xo) {
 			wlan_clock = msm_xo_get(MSM_XO_TCXO_A2, id);
@@ -148,12 +160,14 @@
 	/* Add some delay for XO to settle */
 	msleep(20);
 
+	clk_put(cxo);
 	return rc;
 
 msm_xo_vote_fail:
 	msm_xo_put(wlan_clock);
 
 fail:
+	clk_put(cxo);
 	return rc;
 }
 
@@ -206,7 +220,7 @@
 static int wcnss_vregs_on(struct device *dev,
 		struct vregs_info regulators[], uint size)
 {
-	int i, rc = 0;
+	int i, rc = 0, reg_cnt;
 
 	for (i = 0; i < size; i++) {
 			/* Get regulator source */
@@ -219,9 +233,10 @@
 				goto fail;
 		}
 		regulators[i].state |= VREG_GET_REGULATOR_MASK;
-
+		reg_cnt = regulator_count_voltages(regulators[i].regulator);
 		/* Set voltage to nominal. Exclude swtiches e.g. LVS */
-		if (regulators[i].nominal_min || regulators[i].max_voltage) {
+		if ((regulators[i].nominal_min || regulators[i].max_voltage)
+				&& (reg_cnt > 0)) {
 			rc = regulator_set_voltage(regulators[i].regulator,
 					regulators[i].nominal_min,
 					regulators[i].max_voltage);
@@ -234,7 +249,7 @@
 		}
 
 		/* Vote for PWM/PFM mode if needed */
-		if (regulators[i].uA_load) {
+		if (regulators[i].uA_load && (reg_cnt > 0)) {
 			rc = regulator_set_optimum_mode(regulators[i].regulator,
 					regulators[i].uA_load);
 			if (rc < 0) {
@@ -302,13 +317,15 @@
 			goto fail_iris_on;
 
 		/* Configure IRIS XO */
-		rc = configure_iris_xo(cfg->use_48mhz_xo, WCNSS_WLAN_SWITCH_ON);
+		rc = configure_iris_xo(dev, cfg->use_48mhz_xo,
+				WCNSS_WLAN_SWITCH_ON);
 		if (rc)
 			goto fail_iris_xo;
 		up(&riva_power_on_lock);
 
 	} else {
-		configure_iris_xo(cfg->use_48mhz_xo, WCNSS_WLAN_SWITCH_OFF);
+		configure_iris_xo(dev, cfg->use_48mhz_xo,
+				WCNSS_WLAN_SWITCH_OFF);
 		wcnss_iris_vregs_off();
 		wcnss_riva_vregs_off();
 	}
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 7217434..d99f13a 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -41,12 +41,53 @@
 	struct resource	*rx_irq_res;
 	struct resource	*gpios_5wire;
 	const struct dev_pm_ops *pm_ops;
-	int             triggered;
-	int             smd_channel_ready;
+	int		triggered;
+	int		smd_channel_ready;
+	unsigned int	serial_number;
 	struct wcnss_wlan_config wlan_config;
 	struct delayed_work wcnss_work;
 } *penv = NULL;
 
+static ssize_t wcnss_serial_number_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	if (!penv)
+		return -ENODEV;
+
+	return scnprintf(buf, PAGE_SIZE, "%08X\n", penv->serial_number);
+}
+
+static ssize_t wcnss_serial_number_store(struct device *dev,
+		struct device_attribute *attr, const char * buf, size_t count)
+{
+	unsigned int value;
+
+	if (!penv)
+		return -ENODEV;
+
+	if (sscanf(buf, "%08X", &value) != 1)
+		return -EINVAL;
+
+	penv->serial_number = value;
+	return count;
+}
+
+static DEVICE_ATTR(serial_number, S_IRUSR | S_IWUSR,
+	wcnss_serial_number_show, wcnss_serial_number_store);
+
+static int wcnss_create_sysfs(struct device *dev)
+{
+	if (!dev)
+		return -ENODEV;
+	return device_create_file(dev, &dev_attr_serial_number);
+}
+
+static void wcnss_remove_sysfs(struct device *dev)
+{
+	if (dev)
+		device_remove_file(dev, &dev_attr_serial_number);
+}
+
 static void wcnss_post_bootup(struct work_struct *work)
 {
 	pr_info("%s: Cancel APPS vote for Iris & Riva\n", __func__);
@@ -189,6 +230,14 @@
 }
 EXPORT_SYMBOL(wcnss_wlan_unregister_pm_ops);
 
+unsigned int wcnss_get_serial_number(void)
+{
+	if (penv)
+		return penv->serial_number;
+	return 0;
+}
+EXPORT_SYMBOL(wcnss_get_serial_number);
+
 static int wcnss_wlan_suspend(struct device *dev)
 {
 	if (penv && dev && (dev == &penv->pdev->dev) &&
@@ -272,8 +321,14 @@
 		goto fail_res;
 	}
 
+	/* register sysfs entries */
+	ret = wcnss_create_sysfs(&pdev->dev);
+	if (ret)
+		goto fail_sysfs;
+
 	return 0;
 
+fail_sysfs:
 fail_res:
 	if (penv->pil)
 		pil_put(penv->pil);
@@ -360,6 +415,7 @@
 static int __devexit
 wcnss_wlan_remove(struct platform_device *pdev)
 {
+	wcnss_remove_sysfs(&pdev->dev);
 	return 0;
 }
 
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index d06a637..a306357 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -75,4 +75,10 @@
 	help
 	  OpenFirmware PCI bus accessors
 
+config OF_SPMI
+	def_tristate SPMI
+	depends on SPMI
+	help
+	  OpenFirmware SPMI bus accessors
+
 endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index f7861ed..2087c5e 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -10,3 +10,4 @@
 obj-$(CONFIG_OF_SPI)	+= of_spi.o
 obj-$(CONFIG_OF_MDIO)	+= of_mdio.o
 obj-$(CONFIG_OF_PCI)	+= of_pci.o
+obj-$(CONFIG_OF_SPMI)	+= of_spmi.o
diff --git a/drivers/of/of_spmi.c b/drivers/of/of_spmi.c
new file mode 100644
index 0000000..9f2a396
--- /dev/null
+++ b/drivers/of/of_spmi.c
@@ -0,0 +1,160 @@
+/* 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/spmi.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_spmi.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+/**
+ * Allocate resources for a child of a spmi-container node.
+ */
+static int of_spmi_allocate_resources(struct spmi_controller *ctrl,
+				      struct spmi_boardinfo *info,
+				      struct device_node *node,
+				      uint32_t num_reg)
+{
+	int i, num_irq = 0;
+	uint64_t size;
+	uint32_t flags;
+	struct resource *res;
+	const  __be32 *addrp;
+	struct of_irq oirq;
+
+	while (of_irq_map_one(node, num_irq, &oirq) == 0)
+		num_irq++;
+
+	if (num_irq || num_reg) {
+		res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
+		if (!res)
+			return -ENOMEM;
+
+		info->num_resources = num_reg + num_irq;
+		info->resource = res;
+		for (i = 0; i < num_reg; i++, res++) {
+			/* Addresses are always 16 bits */
+			addrp = of_get_address(node, i, &size, &flags);
+			BUG_ON(!addrp);
+			res->start = be32_to_cpup(addrp);
+			res->end = res->start + size - 1;
+			res->flags = flags;
+		}
+		WARN_ON(of_irq_to_resource_table(node, res, num_irq) !=
+								num_irq);
+	}
+
+	return 0;
+}
+
+static int of_spmi_create_device(struct spmi_controller *ctrl,
+				 struct spmi_boardinfo *info,
+			  struct device_node *node)
+{
+	void *result;
+	int rc;
+
+	rc = of_modalias_node(node, info->name, sizeof(info->name));
+	if (rc < 0) {
+		dev_err(&ctrl->dev, "of_spmi modalias failure on %s\n",
+				node->full_name);
+		return rc;
+	}
+
+	info->of_node = of_node_get(node);
+	result = spmi_new_device(ctrl, info);
+
+	if (result == NULL) {
+		dev_err(&ctrl->dev, "of_spmi: Failure registering %s\n",
+				node->full_name);
+		of_node_put(node);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void of_spmi_walk_container_children(struct spmi_controller *ctrl,
+				     struct spmi_boardinfo *info,
+				     struct device_node *container)
+{
+	struct device_node *node;
+	uint64_t size;
+	uint32_t flags, num_reg = 0;
+	int rc;
+
+	for_each_child_of_node(container, node) {
+		/*
+		 * We can't use of_address_to_resource here since it includes
+		 * address translation; and address translation assumes that no
+		 * parent buses have a size-cell of 0. But SPMI does have a
+		 * size-cell of 0.
+		 */
+		while (of_get_address(node, num_reg, &size, &flags) != NULL)
+			num_reg++;
+
+		rc = of_spmi_allocate_resources(ctrl, info, node, num_reg);
+		if (rc) {
+			dev_err(&ctrl->dev, "%s: unable to allocate"
+						" resources\n", __func__);
+			return;
+		}
+		rc = of_spmi_create_device(ctrl, info, node);
+		if (rc) {
+			dev_err(&ctrl->dev, "%s: unable to create device for"
+				     " node %s\n", __func__, node->full_name);
+			return;
+		}
+	}
+}
+
+int of_spmi_register_devices(struct spmi_controller *ctrl)
+{
+	struct device_node *node;
+
+	/* Only register child devices if the ctrl has a node pointer set */
+	if (!ctrl->dev.of_node)
+		return -ENODEV;
+
+	for_each_child_of_node(ctrl->dev.of_node, node) {
+		struct spmi_boardinfo info = {};
+		const __be32 *slave_id;
+		int len, rc;
+
+		slave_id = of_get_property(node, "reg", &len);
+		if (!slave_id) {
+			dev_err(&ctrl->dev, "of_spmi: invalid sid "
+					"on %s\n", node->full_name);
+			continue;
+		}
+
+		info.slave_id = be32_to_cpup(slave_id);
+
+		if (of_get_property(node, "spmi-dev-container", NULL)) {
+			of_spmi_walk_container_children(ctrl, &info, node);
+			continue;
+		} else {
+			rc = of_spmi_allocate_resources(ctrl, &info, node, 0);
+			if (rc)
+				continue;
+			of_spmi_create_device(ctrl, &info, node);
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(of_spmi_register_devices);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index c2a4b6a..c17da9b 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -1535,7 +1535,7 @@
 		SPS_ERR("sps:fail to get pmem_clk.");
 		goto clk_err;
 	} else {
-		ret = clk_enable(sps->pmem_clk);
+		ret = clk_prepare_enable(sps->pmem_clk);
 		if (ret) {
 			SPS_ERR("sps:failed to enable pmem_clk. ret=%d", ret);
 			goto clk_err;
@@ -1548,14 +1548,14 @@
 		SPS_ERR("sps:fail to get bamdma_clk.");
 		goto clk_err;
 	} else {
-		ret = clk_enable(sps->bamdma_clk);
+		ret = clk_prepare_enable(sps->bamdma_clk);
 		if (ret) {
 			SPS_ERR("sps:failed to enable bamdma_clk. ret=%d", ret);
 			goto clk_err;
 		}
 	}
 
-	ret = clk_enable(sps->dfab_clk);
+	ret = clk_prepare_enable(sps->dfab_clk);
 	if (ret) {
 		SPS_ERR("sps:failed to enable dfab_clk. ret=%d", ret);
 		goto clk_err;
@@ -1565,12 +1565,12 @@
 	if (ret) {
 		SPS_ERR("sps:sps_device_init err.");
 #ifdef CONFIG_SPS_SUPPORT_BAMDMA
-		clk_disable(sps->dfab_clk);
+		clk_disable_unprepare(sps->dfab_clk);
 #endif
 		goto sps_device_init_err;
 	}
 #ifdef CONFIG_SPS_SUPPORT_BAMDMA
-	clk_disable(sps->dfab_clk);
+	clk_disable_unprepare(sps->dfab_clk);
 #endif
 	sps->is_ready = true;
 
diff --git a/drivers/platform/msm/ssbi.c b/drivers/platform/msm/ssbi.c
index 8a6dbf7..e2554f5 100644
--- a/drivers/platform/msm/ssbi.c
+++ b/drivers/platform/msm/ssbi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  * Copyright (c) 2010, Google Inc.
  *
  * Original authors: Code Aurora Forum
@@ -25,6 +25,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/msm_ssbi.h>
+#include <linux/remote_spinlock.h>
 
 /* SSBI 2.0 controller registers */
 #define SSBI2_CMD			0x0008
@@ -75,7 +76,9 @@
 	struct device		*dev;
 	struct device		*slave;
 	void __iomem		*base;
+	bool			 use_rlock;
 	spinlock_t		lock;
+	remote_spinlock_t	 rspin_lock;
 	enum msm_ssbi_controller_type controller_type;
 	int (*read)(struct msm_ssbi *, u16 addr, u8 *buf, int len);
 	int (*write)(struct msm_ssbi *, u16 addr, u8 *buf, int len);
@@ -255,9 +258,15 @@
 	if (ssbi->dev != dev)
 		return -ENXIO;
 
-	spin_lock_irqsave(&ssbi->lock, flags);
-	ret = ssbi->read(ssbi, addr, buf, len);
-	spin_unlock_irqrestore(&ssbi->lock, flags);
+	if (ssbi->use_rlock) {
+		remote_spin_lock_irqsave(&ssbi->rspin_lock, flags);
+		ret = ssbi->read(ssbi, addr, buf, len);
+		remote_spin_unlock_irqrestore(&ssbi->rspin_lock, flags);
+	} else {
+		spin_lock_irqsave(&ssbi->lock, flags);
+		ret = ssbi->read(ssbi, addr, buf, len);
+		spin_unlock_irqrestore(&ssbi->lock, flags);
+	}
 
 	return ret;
 }
@@ -272,9 +281,15 @@
 	if (ssbi->dev != dev)
 		return -ENXIO;
 
-	spin_lock_irqsave(&ssbi->lock, flags);
-	ret = ssbi->write(ssbi, addr, buf, len);
-	spin_unlock_irqrestore(&ssbi->lock, flags);
+	if (ssbi->use_rlock) {
+		remote_spin_lock_irqsave(&ssbi->rspin_lock, flags);
+		ret = ssbi->write(ssbi, addr, buf, len);
+		remote_spin_unlock_irqrestore(&ssbi->rspin_lock, flags);
+	} else {
+		spin_lock_irqsave(&ssbi->lock, flags);
+		ret = ssbi->write(ssbi, addr, buf, len);
+		spin_unlock_irqrestore(&ssbi->lock, flags);
+	}
 
 	return ret;
 }
@@ -362,6 +377,15 @@
 		ssbi->write = msm_ssbi_write_bytes;
 	}
 
+	if (pdata->rsl_id) {
+		ret = remote_spin_lock_init(&ssbi->rspin_lock, pdata->rsl_id);
+		if (ret) {
+			dev_err(&pdev->dev, "remote spinlock init failed\n");
+			goto err_ssbi_add_slave;
+		}
+		ssbi->use_rlock = 1;
+	}
+
 	spin_lock_init(&ssbi->lock);
 
 	ret = msm_ssbi_add_slave(ssbi, &pdata->slave);
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index b34c35e..6caa48f 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -170,20 +170,34 @@
 	struct msm_usb_bam_platform_data *pdata =
 		(struct msm_usb_bam_platform_data *)
 			(usb_bam_pdev->dev.platform_data);
+	struct resource *res;
+	int irq;
 
-	usb_virt_addr = ioremap_nocache(
-						pdata->usb_bam_phy_base,
-						pdata->usb_bam_phy_size);
+	res = platform_get_resource(usb_bam_pdev, IORESOURCE_MEM,
+						pdata->usb_active_bam);
+	if (!res) {
+		dev_err(&usb_bam_pdev->dev, "Unable to get memory resource\n");
+		return -ENODEV;
+	}
+
+	irq = platform_get_irq(usb_bam_pdev, pdata->usb_active_bam);
+	if (irq < 0) {
+		dev_err(&usb_bam_pdev->dev, "Unable to get IRQ resource\n");
+		return irq;
+	}
+
+	usb_virt_addr = ioremap(res->start, resource_size(res));
 	if (!usb_virt_addr) {
 		pr_err("%s: ioremap failed\n", __func__);
 		return -ENOMEM;
 	}
-	usb_props.phys_addr = pdata->usb_bam_phy_base;
+	usb_props.phys_addr = res->start;
 	usb_props.virt_addr = usb_virt_addr;
-	usb_props.virt_size = pdata->usb_bam_phy_size;
-	usb_props.irq = USB1_HS_BAM_IRQ;
-	usb_props.num_pipes = pdata->usb_bam_num_pipes;
+	usb_props.virt_size = resource_size(res);
+	usb_props.irq = irq;
 	usb_props.summing_threshold = USB_SUMMING_THRESHOLD;
+	usb_props.num_pipes = pdata->usb_bam_num_pipes;
+
 	ret = sps_register_bam_device(&usb_props, &h_usb);
 	if (ret < 0) {
 		pr_err("%s: register bam error %d\n", __func__, ret);
@@ -210,7 +224,7 @@
 
 	ret = usb_bam_init();
 	if (ret) {
-		dev_err(&pdev->dev, "failed to get platform resource mem\n");
+		dev_err(&pdev->dev, "failed to initialize usb bam\n");
 		return ret;
 	}
 
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 22d53e9..fa8f866 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -220,8 +220,8 @@
 	unsigned int			update_time;
 	unsigned int			max_voltage_mv;
 	unsigned int			min_voltage_mv;
-	unsigned int			cool_temp_dc;
-	unsigned int			warm_temp_dc;
+	int				cool_temp_dc;
+	int				warm_temp_dc;
 	unsigned int			temp_check_period;
 	unsigned int			cool_bat_chg_current;
 	unsigned int			warm_bat_chg_current;
@@ -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;
@@ -263,6 +264,7 @@
 	enum pm8921_chg_hot_thr		hot_thr;
 };
 
+static int usb_max_current;
 static int charging_disabled;
 static int thermal_mitigation;
 
@@ -291,6 +293,24 @@
 	return 0;
 }
 
+static int pm_chg_get_rt_status(struct pm8921_chg_chip *chip, int irq_id)
+{
+	return pm8xxx_read_irq_stat(chip->dev->parent,
+					chip->pmic_chg_irq[irq_id]);
+}
+
+/* Treat OverVoltage/UnderVoltage as source missing */
+static int is_usb_chg_plugged_in(struct pm8921_chg_chip *chip)
+{
+	return pm_chg_get_rt_status(chip, USBIN_VALID_IRQ);
+}
+
+/* Treat OverVoltage/UnderVoltage as source missing */
+static int is_dc_chg_plugged_in(struct pm8921_chg_chip *chip)
+{
+	return pm_chg_get_rt_status(chip, DCIN_VALID_IRQ);
+}
+
 #define CAPTURE_FSM_STATE_CMD	0xC2
 #define READ_BANK_7		0x70
 #define READ_BANK_4		0x40
@@ -405,21 +425,25 @@
 
 #define PM8921_CHG_V_MIN_MV	3240
 #define PM8921_CHG_V_STEP_MV	20
+#define PM8921_CHG_V_STEP_10_MV_BIT	BIT(7)
 #define PM8921_CHG_VDDMAX_MAX	4500
 #define PM8921_CHG_VDDMAX_MIN	3400
 #define PM8921_CHG_V_MASK	0x7F
-static int pm_chg_vddmax_set(struct pm8921_chg_chip *chip, int voltage)
+static int __pm_chg_vddmax_set(struct pm8921_chg_chip *chip, int voltage)
 {
-	u8 temp;
+	int remainder, voltage_20_step;
+	u8 temp = 0;
 
-	if (voltage < PM8921_CHG_VDDMAX_MIN
-			|| voltage > PM8921_CHG_VDDMAX_MAX) {
-		pr_err("bad mV=%d asked to set\n", voltage);
-		return -EINVAL;
+	voltage_20_step = voltage;
+	remainder = voltage % 20;
+	if (remainder >= 10) {
+		voltage_20_step += 10;
+		temp = PM8921_CHG_V_STEP_10_MV_BIT;
 	}
-	temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
+
+	temp |= (voltage_20_step - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
 	pr_debug("voltage=%d setting %02x\n", voltage, temp);
-	return pm_chg_masked_write(chip, CHG_VDD_MAX, PM8921_CHG_V_MASK, temp);
+	return pm8xxx_writeb(chip->dev->parent, CHG_VDD_MAX, temp);
 }
 
 static int pm_chg_vddmax_get(struct pm8921_chg_chip *chip, int *voltage)
@@ -435,9 +459,53 @@
 	}
 	temp &= PM8921_CHG_V_MASK;
 	*voltage = (int)temp * PM8921_CHG_V_STEP_MV + PM8921_CHG_V_MIN_MV;
+	if (temp & PM8921_CHG_V_STEP_10_MV_BIT)
+		*voltage = *voltage - 10;
 	return 0;
 }
 
+static int pm_chg_vddmax_set(struct pm8921_chg_chip *chip, int voltage)
+{
+	int current_mv, ret, steps, i;
+	bool increase;
+
+	ret = 0;
+
+	if (voltage < PM8921_CHG_VDDMAX_MIN
+		|| voltage > PM8921_CHG_VDDMAX_MAX) {
+		pr_err("bad mV=%d asked to set\n", voltage);
+		return -EINVAL;
+	}
+
+	ret = pm_chg_vddmax_get(chip, &current_mv);
+	if (ret) {
+		pr_err("Failed to read vddmax rc=%d\n", ret);
+		return -EINVAL;
+	}
+	if (current_mv == voltage)
+		return 0;
+
+	/* Only change in increments when USB is present */
+	if (is_usb_chg_plugged_in(chip)) {
+		if (current_mv < voltage) {
+			steps = (voltage - current_mv) / PM8921_CHG_V_STEP_MV;
+			increase = true;
+		} else {
+			steps = (current_mv - voltage) / PM8921_CHG_V_STEP_MV;
+			increase = false;
+		}
+		for (i = 0; i < steps; i++) {
+			if (increase)
+				current_mv += PM8921_CHG_V_STEP_MV;
+			else
+				current_mv -= PM8921_CHG_V_STEP_MV;
+			ret |= __pm_chg_vddmax_set(chip, current_mv);
+		}
+	}
+	ret |= __pm_chg_vddmax_set(chip, voltage);
+	return ret;
+}
+
 #define PM8921_CHG_VDDSAFE_MIN	3400
 #define PM8921_CHG_VDDSAFE_MAX	4500
 static int pm_chg_vddsafe_set(struct pm8921_chg_chip *chip, int voltage)
@@ -575,6 +643,22 @@
 	return 0;
 }
 
+struct usb_ma_limit_entry {
+	int usb_ma;
+	u8  chg_iusb_value;
+};
+
+static struct usb_ma_limit_entry usb_ma_table[] = {
+	{100, 0},
+	{500, 1},
+	{700, 2},
+	{850, 3},
+	{900, 4},
+	{1100, 5},
+	{1300, 6},
+	{1500, 7},
+};
+
 #define PM8921_CHG_IUSB_MASK 0x1C
 #define PM8921_CHG_IUSB_MAX  7
 #define PM8921_CHG_IUSB_MIN  0
@@ -591,6 +675,26 @@
 					 temp);
 }
 
+static int pm_chg_iusbmax_get(struct pm8921_chg_chip *chip, int *mA)
+{
+	u8 temp;
+	int i, rc;
+
+	*mA = 0;
+	rc = pm8xxx_readb(chip->dev->parent, PBL_ACCESS2, &temp);
+	if (rc) {
+		pr_err("err=%d reading PBL_ACCESS2\n", rc);
+		return rc;
+	}
+	temp &= PM8921_CHG_IUSB_MASK;
+	temp = temp >> 2;
+	for (i = ARRAY_SIZE(usb_ma_table) - 1; i >= 0; i--) {
+		if (usb_ma_table[i].chg_iusb_value == temp)
+			*mA = usb_ma_table[i].usb_ma;
+	}
+	return rc;
+}
+
 #define PM8921_CHG_WD_MASK 0x1F
 static int pm_chg_disable_wd(struct pm8921_chg_chip *chip)
 {
@@ -822,24 +926,6 @@
 	return test_bit(interrupt, chip->enabled_irqs);
 }
 
-static int pm_chg_get_rt_status(struct pm8921_chg_chip *chip, int irq_id)
-{
-	return pm8xxx_read_irq_stat(chip->dev->parent,
-					chip->pmic_chg_irq[irq_id]);
-}
-
-/* Treat OverVoltage/UnderVoltage as source missing */
-static int is_usb_chg_plugged_in(struct pm8921_chg_chip *chip)
-{
-	return pm_chg_get_rt_status(chip, USBIN_VALID_IRQ);
-}
-
-/* Treat OverVoltage/UnderVoltage as source missing */
-static int is_dc_chg_plugged_in(struct pm8921_chg_chip *chip)
-{
-	return pm_chg_get_rt_status(chip, DCIN_VALID_IRQ);
-}
-
 static bool is_ext_charging(struct pm8921_chg_chip *chip)
 {
 	union power_supply_propval ret = {0,};
@@ -920,25 +1006,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:
@@ -1209,27 +1311,17 @@
 	}
 }
 
-struct usb_ma_limit_entry {
-	int usb_ma;
-	u8  chg_iusb_value;
-};
-
-static struct usb_ma_limit_entry usb_ma_table[] = {
-	{100, 0},
-	{500, 1},
-	{700, 2},
-	{850, 3},
-	{900, 4},
-	{1100, 5},
-	{1300, 6},
-	{1500, 7},
-};
-
 /* assumes vbus_lock is held */
 static void __pm8921_charger_vbus_draw(unsigned int mA)
 {
 	int i, rc;
 
+	if (usb_max_current && mA > usb_max_current) {
+		pr_warn("restricting usb current to %d instead of %d\n",
+					usb_max_current, mA);
+		mA = usb_max_current;
+	}
+
 	if (mA > 0 && mA <= 2) {
 		usb_chg_current = 0;
 		rc = pm_chg_iusbmax_set(the_chip,
@@ -2301,8 +2393,16 @@
 {
 	int rc;
 
-	btm_config.btm_warm_fn = battery_warm;
-	btm_config.btm_cool_fn = battery_cool;
+	if (chip->warm_temp_dc != INT_MIN)
+		btm_config.btm_warm_fn = battery_warm;
+	else
+		btm_config.btm_warm_fn = NULL;
+
+	if (chip->cool_temp_dc != INT_MIN)
+		btm_config.btm_cool_fn = battery_cool;
+	else
+		btm_config.btm_cool_fn = NULL;
+
 	btm_config.low_thr_temp = chip->cool_temp_dc;
 	btm_config.high_thr_temp = chip->warm_temp_dc;
 	btm_config.interval = chip->temp_check_period;
@@ -2383,6 +2483,28 @@
 					param_get_uint,
 					&thermal_mitigation, 0644);
 
+static int set_usb_max_current(const char *val, struct kernel_param *kp)
+{
+	int ret, mA;
+	struct pm8921_chg_chip *chip = the_chip;
+
+	ret = param_set_int(val, kp);
+	if (ret) {
+		pr_err("error setting value %d\n", ret);
+		return ret;
+	}
+	if (chip) {
+		pr_warn("setting current max to %d\n", usb_max_current);
+		pm_chg_iusbmax_get(chip, &mA);
+		if (mA > usb_max_current)
+			pm8921_charger_vbus_draw(usb_max_current);
+		return 0;
+	}
+	return -EINVAL;
+}
+module_param_call(usb_max_current, set_usb_max_current, param_get_uint,
+					&usb_max_current, 0644);
+
 static void free_irqs(struct pm8921_chg_chip *chip)
 {
 	int i;
@@ -2541,12 +2663,98 @@
 	return -EINVAL;
 }
 
+static void pm8921_chg_force_19p2mhz_clk(struct pm8921_chg_chip *chip)
+{
+	int err;
+	u8 temp;
+
+	temp  = 0xD1;
+	err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+	if (err) {
+		pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
+		return;
+	}
+
+	temp  = 0xD3;
+	err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+	if (err) {
+		pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
+		return;
+	}
+
+	temp  = 0xD1;
+	err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+	if (err) {
+		pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
+		return;
+	}
+
+	temp  = 0xD5;
+	err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+	if (err) {
+		pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
+		return;
+	}
+
+	udelay(183);
+
+	temp  = 0xD1;
+	err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+	if (err) {
+		pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
+		return;
+	}
+
+	temp  = 0xD0;
+	err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+	if (err) {
+		pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
+		return;
+	}
+	udelay(32);
+
+	temp  = 0xD1;
+	err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+	if (err) {
+		pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
+		return;
+	}
+
+	temp  = 0xD3;
+	err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+	if (err) {
+		pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
+		return;
+	}
+}
+
+static void pm8921_chg_set_hw_clk_switching(struct pm8921_chg_chip *chip)
+{
+	int err;
+	u8 temp;
+
+	temp  = 0xD1;
+	err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+	if (err) {
+		pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
+		return;
+	}
+
+	temp  = 0xD0;
+	err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+	if (err) {
+		pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
+		return;
+	}
+}
+
 #define ENUM_TIMER_STOP_BIT	BIT(1)
 #define BOOT_DONE_BIT		BIT(6)
 #define CHG_BATFET_ON_BIT	BIT(3)
 #define CHG_VCP_EN		BIT(0)
 #define CHG_BAT_TEMP_DIS_BIT	BIT(2)
 #define SAFE_CURRENT_MA		1500
+#define VREF_BATT_THERM_FORCE_ON	BIT(7)
 static int __devinit pm8921_chg_hw_init(struct pm8921_chg_chip *chip)
 {
 	int rc;
@@ -2736,6 +2944,13 @@
 	/* Disable EOC FSM processing */
 	pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0x91);
 
+	pm8921_chg_force_19p2mhz_clk(chip);
+
+	rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON,
+						VREF_BATT_THERM_FORCE_ON);
+	if (rc)
+		pr_err("Failed to Force Vref therm rc=%d\n", rc);
+
 	rc = pm_chg_charge_dis(chip, charging_disabled);
 	if (rc) {
 		pr_err("Failed to disable CHG_CHARGE_DIS bit rc=%d\n", rc);
@@ -2918,12 +3133,38 @@
 	}
 }
 
+static int pm8921_charger_suspend_noirq(struct device *dev)
+{
+	int rc;
+	struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
+
+	rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON, 0);
+	if (rc)
+		pr_err("Failed to Force Vref therm off rc=%d\n", rc);
+	pm8921_chg_set_hw_clk_switching(chip);
+	return 0;
+}
+
+static int pm8921_charger_resume_noirq(struct device *dev)
+{
+	int rc;
+	struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
+
+	pm8921_chg_force_19p2mhz_clk(chip);
+
+	rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON,
+						VREF_BATT_THERM_FORCE_ON);
+	if (rc)
+		pr_err("Failed to Force Vref therm on rc=%d\n", rc);
+	return 0;
+}
+
 static int pm8921_charger_resume(struct device *dev)
 {
 	int rc;
 	struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
 
-	if (!(chip->cool_temp_dc == 0 && chip->warm_temp_dc == 0)
+	if (!(chip->cool_temp_dc == INT_MIN && chip->warm_temp_dc == INT_MIN)
 		&& !(chip->keep_btm_on_suspend)) {
 		rc = pm8xxx_adc_btm_configure(&btm_config);
 		if (rc)
@@ -2945,7 +3186,7 @@
 	int rc;
 	struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
 
-	if (!(chip->cool_temp_dc == 0 && chip->warm_temp_dc == 0)
+	if (!(chip->cool_temp_dc == INT_MIN && chip->warm_temp_dc == INT_MIN)
 		&& !(chip->keep_btm_on_suspend)) {
 		rc = pm8xxx_adc_btm_end();
 		if (rc)
@@ -2956,6 +3197,7 @@
 		pm8921_chg_enable_irq(chip, LOOP_CHANGE_IRQ);
 		enable_irq_wake(chip->pmic_chg_irq[LOOP_CHANGE_IRQ]);
 	}
+
 	return 0;
 }
 static int __devinit pm8921_charger_probe(struct platform_device *pdev)
@@ -2990,8 +3232,16 @@
 	chip->batt_id_channel = pdata->charger_cdata.batt_id_channel;
 	chip->batt_id_min = pdata->batt_id_min;
 	chip->batt_id_max = pdata->batt_id_max;
-	chip->cool_temp_dc = pdata->cool_temp * 10;
-	chip->warm_temp_dc = pdata->warm_temp * 10;
+	if (pdata->cool_temp != INT_MIN)
+		chip->cool_temp_dc = pdata->cool_temp * 10;
+	else
+		chip->cool_temp_dc = INT_MIN;
+
+	if (pdata->warm_temp != INT_MIN)
+		chip->warm_temp_dc = pdata->warm_temp * 10;
+	else
+		chip->warm_temp_dc = INT_MIN;
+
 	chip->temp_check_period = pdata->temp_check_period;
 	chip->max_bat_chg_current = pdata->max_bat_chg_current;
 	chip->cool_bat_chg_current = pdata->cool_bat_chg_current;
@@ -3024,6 +3274,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,
@@ -3036,10 +3294,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);
@@ -3064,11 +3328,12 @@
 	enable_irq_wake(chip->pmic_chg_irq[USBIN_UV_IRQ]);
 	enable_irq_wake(chip->pmic_chg_irq[BAT_TEMP_OK_IRQ]);
 	enable_irq_wake(chip->pmic_chg_irq[VBATDET_LOW_IRQ]);
+	enable_irq_wake(chip->pmic_chg_irq[FASTCHG_IRQ]);
 	/*
-	 * if both the cool_temp_dc and warm_temp_dc are zero the device doesnt
+	 * if both the cool_temp_dc and warm_temp_dc are invalid device doesnt
 	 * care for jeita compliance
 	 */
-	if (!(chip->cool_temp_dc == 0 && chip->warm_temp_dc == 0)) {
+	if (!(chip->cool_temp_dc == INT_MIN && chip->warm_temp_dc == INT_MIN)) {
 		rc = configure_btm(chip);
 		if (rc) {
 			pr_err("couldn't register with btm rc=%d\n", rc);
@@ -3097,6 +3362,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:
@@ -3116,6 +3383,8 @@
 }
 static const struct dev_pm_ops pm8921_pm_ops = {
 	.suspend	= pm8921_charger_suspend,
+	.suspend_noirq  = pm8921_charger_suspend_noirq,
+	.resume_noirq   = pm8921_charger_resume_noirq,
 	.resume		= pm8921_charger_resume,
 };
 static struct platform_driver pm8921_charger_driver = {
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/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index aa67c8c..0fed092 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -75,6 +75,8 @@
 #define SAT_MSG_VER	0x1
 #define SAT_MSG_PROT	0x1
 #define MSM_SAT_SUCCSS	0x20
+#define MSM_MAX_NSATS	2
+#define MSM_MAX_SATCH	32
 
 #define QC_MFGID_LSB	0x2
 #define QC_MFGID_MSB	0x17
@@ -225,7 +227,7 @@
 	int			err;
 	int			ee;
 	struct completion	*wr_comp;
-	struct msm_slim_sat	*satd;
+	struct msm_slim_sat	*satd[MSM_MAX_NSATS];
 	struct msm_slim_endp	pipes[7];
 	struct msm_slim_sps_bam	bam;
 	struct msm_slim_endp	rx_msgq;
@@ -240,6 +242,14 @@
 	bool			reconf_busy;
 	bool			chan_active;
 	enum msm_ctrl_state	state;
+	int			nsats;
+};
+
+struct msm_sat_chan {
+	u8 chan;
+	u16 chanh;
+	int req_rem;
+	int req_def;
 };
 
 struct msm_slim_sat {
@@ -248,7 +258,7 @@
 	struct workqueue_struct *wq;
 	struct work_struct	wd;
 	u8			sat_msgs[SAT_CONCUR_MSG][40];
-	u16			*satch;
+	struct msm_sat_chan	*satch;
 	u8			nsatch;
 	bool			sent_capability;
 	bool			pending_reconf;
@@ -258,6 +268,8 @@
 	spinlock_t lock;
 };
 
+static struct msm_slim_sat *msm_slim_alloc_sat(struct msm_slim_ctrl *dev);
+
 static int msm_slim_rx_enqueue(struct msm_slim_ctrl *dev, u32 *buf, u8 len)
 {
 	spin_lock(&dev->rx_lock);
@@ -354,11 +366,28 @@
 static void msm_slim_put_ctrl(struct msm_slim_ctrl *dev)
 {
 #ifdef CONFIG_PM_RUNTIME
+	int ref;
 	pm_runtime_mark_last_busy(dev->dev);
-	pm_runtime_put(dev->dev);
+	ref = atomic_read(&dev->dev->power.usage_count);
+	if (ref <= 0)
+		dev_err(dev->dev, "reference count mismatch:%d", ref);
+	else
+		pm_runtime_put(dev->dev);
 #endif
 }
 
+static struct msm_slim_sat *addr_to_sat(struct msm_slim_ctrl *dev, u8 laddr)
+{
+	struct msm_slim_sat *sat = NULL;
+	int i = 0;
+	while (!sat && i < dev->nsats) {
+		if (laddr == dev->satd[i]->satcl.laddr)
+			sat = dev->satd[i];
+		i++;
+	}
+	return sat;
+}
+
 static irqreturn_t msm_slim_interrupt(int irq, void *d)
 {
 	struct msm_slim_ctrl *dev = d;
@@ -398,8 +427,13 @@
 		dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
 		if (mt == SLIM_MSG_MT_DEST_REFERRED_USER ||
 				mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
-			struct msm_slim_sat *sat = dev->satd;
-			msm_sat_enqueue(sat, rx_buf, len);
+			u8 laddr = (u8)((rx_buf[0] >> 16) & 0xFF);
+			struct msm_slim_sat *sat = addr_to_sat(dev, laddr);
+			if (sat)
+				msm_sat_enqueue(sat, rx_buf, len);
+			else
+				dev_err(dev->dev, "unknown sat:%d message",
+						laddr);
 			writel_relaxed(MGR_INT_RX_MSG_RCVD,
 					dev->base + MGR_INT_CLR);
 			/*
@@ -407,37 +441,21 @@
 			 * queuing work
 			 */
 			mb();
-			queue_work(sat->wq, &sat->wd);
+			if (sat)
+				queue_work(sat->wq, &sat->wd);
 		} else if (mt == SLIM_MSG_MT_CORE &&
 			mc == SLIM_MSG_MC_REPORT_PRESENT) {
 			u8 e_addr[6];
 			msm_get_eaddr(e_addr, rx_buf);
-			if (msm_is_sat_dev(e_addr)) {
-				/*
-				 * Consider possibility that this device may
-				 * be reporting more than once?
-				 */
-				struct msm_slim_sat *sat = dev->satd;
-				msm_sat_enqueue(sat, rx_buf, len);
-				writel_relaxed(MGR_INT_RX_MSG_RCVD, dev->base +
-							MGR_INT_CLR);
-				/*
-				 * Guarantee that CLR bit write goes through
-				 * before queuing work
-				 */
-				mb();
-				queue_work(sat->wq, &sat->wd);
-			} else {
-				msm_slim_rx_enqueue(dev, rx_buf, len);
-				writel_relaxed(MGR_INT_RX_MSG_RCVD, dev->base +
-							MGR_INT_CLR);
-				/*
-				 * Guarantee that CLR bit write goes through
-				 * before signalling completion
-				 */
-				mb();
-				complete(&dev->rx_msgq_notify);
-			}
+			msm_slim_rx_enqueue(dev, rx_buf, len);
+			writel_relaxed(MGR_INT_RX_MSG_RCVD, dev->base +
+						MGR_INT_CLR);
+			/*
+			 * Guarantee that CLR bit write goes through
+			 * before signalling completion
+			 */
+			mb();
+			complete(&dev->rx_msgq_notify);
 		} else if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
 				mc == SLIM_MSG_MC_REPLY_VALUE) {
 			msm_slim_rx_enqueue(dev, rx_buf, len);
@@ -954,18 +972,67 @@
 	int i;
 	int ret = 0;
 	if (mc == SLIM_USR_MC_CHAN_CTRL) {
-		u16 chanh = sat->satch[buf[5]];
+		for (i = 0; i < sat->nsatch; i++) {
+			if (buf[5] == sat->satch[i].chan)
+				break;
+		}
+		if (i >= sat->nsatch)
+			return -ENOTCONN;
 		oper = ((buf[3] & 0xC0) >> 6);
 		/* part of grp. activating/removing 1 will take care of rest */
-		ret = slim_control_ch(&sat->satcl, chanh, oper, false);
+		ret = slim_control_ch(&sat->satcl, sat->satch[i].chanh, oper,
+					false);
+		if (!ret) {
+			for (i = 5; i < len; i++) {
+				int j;
+				for (j = 0; j < sat->nsatch; j++) {
+					if (buf[i] == sat->satch[j].chan) {
+						if (oper == SLIM_CH_REMOVE)
+							sat->satch[j].req_rem++;
+						else
+							sat->satch[j].req_def++;
+						break;
+					}
+				}
+			}
+		}
 	} else {
 		u16 chh[40];
 		struct slim_ch prop;
 		u32 exp;
 		u8 coeff, cc;
 		u8 prrate = buf[6];
-		for (i = 8; i < len; i++)
-			chh[i-8] = sat->satch[buf[i]];
+		if (len <= 8)
+			return -EINVAL;
+		for (i = 8; i < len; i++) {
+			int j = 0;
+			for (j = 0; j < sat->nsatch; j++) {
+				if (sat->satch[j].chan == buf[i]) {
+					chh[i - 8] = sat->satch[j].chanh;
+					break;
+				}
+			}
+			if (j < sat->nsatch) {
+				u16 dummy;
+				ret = slim_query_ch(&sat->satcl, buf[i],
+							&dummy);
+				if (ret)
+					return ret;
+				if (mc == SLIM_USR_MC_DEF_ACT_CHAN)
+					sat->satch[j].req_def++;
+				continue;
+			}
+			if (sat->nsatch >= MSM_MAX_SATCH)
+				return -EXFULL;
+			ret = slim_query_ch(&sat->satcl, buf[i], &chh[i - 8]);
+			if (ret)
+				return ret;
+			sat->satch[j].chan = buf[i];
+			sat->satch[j].chanh = chh[i - 8];
+			if (mc == SLIM_USR_MC_DEF_ACT_CHAN)
+				sat->satch[j].req_def++;
+			sat->nsatch++;
+		}
 		prop.dataf = (enum slim_ch_dataf)((buf[3] & 0xE0) >> 5);
 		prop.auxf = (enum slim_ch_auxf)((buf[4] & 0xC0) >> 5);
 		prop.baser = SLIM_RATE_4000HZ;
@@ -981,17 +1048,18 @@
 		prop.ratem = cc * (1 << exp);
 		if (i > 9)
 			ret = slim_define_ch(&sat->satcl, &prop, chh, len - 8,
-						true, &sat->satch[buf[8]]);
+					true, &chh[0]);
 		else
 			ret = slim_define_ch(&sat->satcl, &prop,
-						&sat->satch[buf[8]], 1, false,
-						NULL);
+					&chh[0], 1, false, NULL);
 		dev_dbg(dev->dev, "define sat grp returned:%d", ret);
+		if (ret)
+			return ret;
 
 		/* part of group so activating 1 will take care of rest */
 		if (mc == SLIM_USR_MC_DEF_ACT_CHAN)
 			ret = slim_control_ch(&sat->satcl,
-					sat->satch[buf[8]],
+					chh[0],
 					SLIM_CH_ACTIVATE, false);
 	}
 	return ret;
@@ -1024,6 +1092,18 @@
 				laddr == (QC_MSM_DEVS - 1))
 				pm_runtime_enable(dev->dev);
 
+			if (!ret && msm_is_sat_dev(e_addr)) {
+				struct msm_slim_sat *sat = addr_to_sat(dev,
+								laddr);
+				if (!sat)
+					sat = msm_slim_alloc_sat(dev);
+				if (!sat)
+					return;
+
+				sat->satcl.laddr = laddr;
+				msm_sat_enqueue(sat, (u32 *)buf, len);
+				queue_work(sat->wq, &sat->wd);
+			}
 		} else if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
 				mc == SLIM_MSG_MC_REPLY_VALUE) {
 			u8 tid = buf[3];
@@ -1059,7 +1139,6 @@
 
 	while ((msm_sat_dequeue(sat, buf)) != -ENODATA) {
 		struct slim_msg_txn txn;
-		int i;
 		u8 len, mc, mt;
 		u32 bw_sl;
 		int ret = 0;
@@ -1067,6 +1146,7 @@
 		bool gen_ack = false;
 		u8 tid;
 		u8 wbuf[8];
+		int i;
 		txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
 		txn.dt = SLIM_MSG_DEST_LOGICALADDR;
 		txn.ec = 0;
@@ -1107,20 +1187,23 @@
 				continue;
 			}
 			/* send a Manager capability msg */
-			if (sat->sent_capability)
-				continue;
+			if (sat->sent_capability) {
+				if (mt == SLIM_MSG_MT_CORE)
+					goto send_capability;
+				else
+					continue;
+			}
 			ret = slim_add_device(&dev->ctrl, &sat->satcl);
 			if (ret) {
 				dev_err(dev->dev,
 					"Satellite-init failed");
 				continue;
 			}
-			/* Satellite owns first 21 channels */
-			sat->satch = kzalloc(21 * sizeof(u16), GFP_KERNEL);
-			sat->nsatch = 20;
-			/* alloc all sat chans */
-			for (i = 0; i < 21; i++)
-				slim_alloc_ch(&sat->satcl, &sat->satch[i]);
+			/* Satellite-channels */
+			sat->satch = kzalloc(MSM_MAX_SATCH *
+					sizeof(struct msm_sat_chan),
+					GFP_KERNEL);
+send_capability:
 			txn.mc = SLIM_USR_MC_MASTER_CAPABILITY;
 			txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
 			txn.la = sat->satcl.laddr;
@@ -1171,6 +1254,20 @@
 			tid = buf[3];
 			gen_ack = true;
 			ret = slim_reconfigure_now(&sat->satcl);
+			for (i = 0; i < sat->nsatch; i++) {
+				struct msm_sat_chan *sch = &sat->satch[i];
+				if (sch->req_rem) {
+					if (!ret)
+						slim_dealloc_ch(&sat->satcl,
+								sch->chanh);
+					sch->req_rem--;
+				} else if (sch->req_def) {
+					if (ret)
+						slim_dealloc_ch(&sat->satcl,
+								sch->chanh);
+					sch->req_def--;
+				}
+			}
 			if (sat->pending_reconf) {
 				msm_slim_put_ctrl(dev);
 				sat->pending_reconf = false;
@@ -1238,6 +1335,44 @@
 	}
 }
 
+static struct msm_slim_sat *msm_slim_alloc_sat(struct msm_slim_ctrl *dev)
+{
+	struct msm_slim_sat *sat;
+	char *name;
+	if (dev->nsats >= MSM_MAX_NSATS)
+		return NULL;
+
+	sat = kzalloc(sizeof(struct msm_slim_sat), GFP_KERNEL);
+	if (!sat) {
+		dev_err(dev->dev, "no memory for satellite");
+		return NULL;
+	}
+	name = kzalloc(SLIMBUS_NAME_SIZE, GFP_KERNEL);
+	if (!name) {
+		dev_err(dev->dev, "no memory for satellite name");
+		kfree(sat);
+		return NULL;
+	}
+	dev->satd[dev->nsats] = sat;
+	sat->dev = dev;
+	snprintf(name, SLIMBUS_NAME_SIZE, "msm_sat%d", dev->nsats);
+	sat->satcl.name = name;
+	spin_lock_init(&sat->lock);
+	INIT_WORK(&sat->wd, slim_sat_rxprocess);
+	sat->wq = create_singlethread_workqueue(sat->satcl.name);
+	if (!sat->wq) {
+		kfree(name);
+		kfree(sat);
+		return NULL;
+	}
+	/*
+	 * Both sats will be allocated from RX thread and RX thread will
+	 * process messages sequentially. No synchronization necessary
+	 */
+	dev->nsats++;
+	return sat;
+}
+
 static void
 msm_slim_rx_msgq_event(struct msm_slim_ctrl *dev, struct sps_event_notify *ev)
 {
@@ -1370,18 +1505,13 @@
 			mc = (buffer[0] >> 8) & 0xff;
 			dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
 			if (mt == SLIM_MSG_MT_DEST_REFERRED_USER ||
-				mt == SLIM_MSG_MT_SRC_REFERRED_USER)
-				sat = dev->satd;
-
+				mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
+				u8 laddr;
+				laddr = (u8)((buffer[0] >> 16) & 0xff);
+				sat = addr_to_sat(dev, laddr);
+			}
 		} else if ((index * 4) >= msg_len) {
 			index = 0;
-			if (mt == SLIM_MSG_MT_CORE &&
-				mc == SLIM_MSG_MC_REPORT_PRESENT) {
-				u8 e_addr[6];
-				msm_get_eaddr(e_addr, buffer);
-				if (msm_is_sat_dev(e_addr))
-					sat = dev->satd;
-			}
 			if (sat) {
 				msm_sat_enqueue(sat, buffer, msg_len);
 				queue_work(sat->wq, &sat->wd);
@@ -1751,21 +1881,10 @@
 		goto err_request_irq_failed;
 	}
 
-	dev->satd = kzalloc(sizeof(struct msm_slim_sat), GFP_KERNEL);
-	if (!dev->satd) {
-		ret = -ENOMEM;
-		goto err_sat_failed;
-	}
-
 	msm_slim_prg_slew(pdev, dev);
 	clk_set_rate(dev->rclk, SLIM_ROOT_FREQ);
 	clk_enable(dev->rclk);
 
-	dev->satd->dev = dev;
-	dev->satd->satcl.name  = "msm_sat_dev";
-	spin_lock_init(&dev->satd->lock);
-	INIT_WORK(&dev->satd->wd, slim_sat_rxprocess);
-	dev->satd->wq = create_singlethread_workqueue("msm_slim_sat");
 	/* Component register initialization */
 	writel_relaxed(1, dev->base + COMP_CFG);
 	writel_relaxed((EE_MGR_RSC_GRP | EE_NGD_2 | EE_NGD_1),
@@ -1851,8 +1970,6 @@
 err_ctrl_failed:
 	writel_relaxed(0, dev->base + COMP_CFG);
 	kfree(dev->satd);
-err_sat_failed:
-	free_irq(dev->irq, dev);
 err_request_irq_failed:
 	clk_disable(dev->rclk);
 	clk_put(dev->rclk);
@@ -1877,13 +1994,20 @@
 	struct resource *bam_mem;
 	struct resource *slim_mem;
 	struct resource *slew_mem = dev->slew_mem;
-	struct msm_slim_sat *sat = dev->satd;
-	slim_remove_device(&sat->satcl);
+	int i;
+	for (i = 0; i < dev->nsats; i++) {
+		struct msm_slim_sat *sat = dev->satd[i];
+		int j;
+		for (j = 0; j < sat->nsatch; j++)
+			slim_dealloc_ch(&sat->satcl, sat->satch[j].chanh);
+		slim_remove_device(&sat->satcl);
+		kfree(sat->satch);
+		destroy_workqueue(sat->wq);
+		kfree(sat->satcl.name);
+		kfree(sat);
+	}
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
-	kfree(sat->satch);
-	destroy_workqueue(sat->wq);
-	kfree(sat);
 	free_irq(dev->irq, dev);
 	slim_del_controller(&dev->ctrl);
 	clk_put(dev->rclk);
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index a541d8b..6733396 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.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
@@ -25,6 +25,8 @@
 #define SLIM_HDL_TO_FLOW(hdl)	(((u32)(hdl) & 0xFF0000) >> 16)
 #define SLIM_HDL_TO_PORT(hdl)	((u32)(hdl) & 0xFF)
 
+#define SLIM_HDL_TO_CHIDX(hdl)	((u16)(hdl) & 0xFF)
+
 #define SLIM_SLAVE_PORT(p, la)	(((la)<<16) | (p))
 #define SLIM_MGR_PORT(p)	((0xFF << 16) | (p))
 #define SLIM_LA_MANAGER		0xFF
@@ -1074,7 +1076,7 @@
 	else
 		mc = SLIM_MSG_MC_CONNECT_SINK;
 	buf[0] = pn;
-	buf[1] = ch;
+	buf[1] = ctrl->chans[ch].chan;
 	if (la == SLIM_LA_MANAGER)
 		ctrl->ports[pn].flow = flow;
 	ret = slim_processtxn(ctrl, SLIM_MSG_DEST_LOGICALADDR, mc, 0,
@@ -1104,75 +1106,117 @@
 }
 
 /*
- * slim_connect_ports: Connect port(s) to channel.
+ * slim_connect_src: Connect source port to channel.
  * @sb: client handle
- * @srch: source handles to be connected to this channel
- * @nrsc: number of source ports
- * @sinkh: sink handle to be connected to this channel
+ * @srch: source handle to be connected to this channel
  * @chanh: Channel with which the ports need to be associated with.
- * Per slimbus specification, a channel may have multiple source-ports and 1
- * sink port.Channel specified in chanh needs to be allocated first.
+ * Per slimbus specification, a channel may have 1 source port.
+ * Channel specified in chanh needs to be allocated first.
+ * Returns -EALREADY if source is already configured for this channel.
+ * Returns -ENOTCONN if channel is not allocated
  */
-int slim_connect_ports(struct slim_device *sb, u32 *srch, int nsrc, u32 sinkh,
-			u16 chanh)
+int slim_connect_src(struct slim_device *sb, u32 srch, u16 chanh)
+{
+	struct slim_controller *ctrl = sb->ctrl;
+	int ret;
+	u8 chan = SLIM_HDL_TO_CHIDX(chanh);
+	struct slim_ich *slc = &ctrl->chans[chan];
+	enum slim_port_flow flow = SLIM_HDL_TO_FLOW(srch);
+
+	if (flow != SLIM_SRC)
+		return -EINVAL;
+
+	mutex_lock(&ctrl->m_ctrl);
+
+	if (slc->state == SLIM_CH_FREE) {
+		ret = -ENOTCONN;
+		goto connect_src_err;
+	}
+	/*
+	 * Once channel is removed, its ports can be considered disconnected
+	 * So its ports can be reassigned. Source port is zeroed
+	 * when channel is deallocated.
+	 */
+	if (slc->srch) {
+		ret = -EALREADY;
+		goto connect_src_err;
+	}
+
+	ret = connect_port_ch(ctrl, chan, srch, SLIM_SRC);
+
+	if (!ret)
+		slc->srch = srch;
+
+connect_src_err:
+	mutex_unlock(&ctrl->m_ctrl);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(slim_connect_src);
+
+/*
+ * slim_connect_sink: Connect sink port(s) to channel.
+ * @sb: client handle
+ * @sinkh: sink handle(s) to be connected to this channel
+ * @nsink: number of sinks
+ * @chanh: Channel with which the ports need to be associated with.
+ * Per slimbus specification, a channel may have multiple sink-ports.
+ * Channel specified in chanh needs to be allocated first.
+ * Returns -EALREADY if sink is already configured for this channel.
+ * Returns -ENOTCONN if channel is not allocated
+ */
+int slim_connect_sink(struct slim_device *sb, u32 *sinkh, int nsink, u16 chanh)
 {
 	struct slim_controller *ctrl = sb->ctrl;
 	int j;
 	int ret = 0;
-	u8 chan = (u8)(chanh & 0xFF);
+	u8 chan = SLIM_HDL_TO_CHIDX(chanh);
 	struct slim_ich *slc = &ctrl->chans[chan];
 
+	if (!sinkh || !nsink)
+		return -EINVAL;
+
 	mutex_lock(&ctrl->m_ctrl);
-	/* Make sure the channel is not already pending reconf. or active */
-	if (slc->state >= SLIM_CH_PENDING_ACTIVE) {
-		dev_err(&ctrl->dev, "Channel %d  already active", chan);
-		ret = -EISCONN;
-		goto connect_port_err;
-	}
 
 	/*
 	 * Once channel is removed, its ports can be considered disconnected
-	 * So its ports can be reassigned. Source port array is freed
-	 * when channel is deallocated.
+	 * So its ports can be reassigned. Sink ports are freed when channel
+	 * is deallocated.
 	 */
-	slc->srch = krealloc(slc->srch, (sizeof(u32) * nsrc), GFP_KERNEL);
-	if (!slc->srch) {
-		ret = -ENOMEM;
-		goto connect_port_err;
+	if (slc->state == SLIM_CH_FREE) {
+		ret = -ENOTCONN;
+		goto connect_sink_err;
 	}
 
-	/* connect source */
-	for (j = 0; j < nsrc; j++) {
-		ret = connect_port_ch(ctrl, chan, srch[j], SLIM_SRC);
+	for (j = 0; j < nsink; j++) {
+		enum slim_port_flow flow = SLIM_HDL_TO_FLOW(sinkh[j]);
+		if (flow != SLIM_SINK)
+			ret = -EINVAL;
+		else
+			ret = connect_port_ch(ctrl, chan, sinkh[j], SLIM_SINK);
 		if (ret) {
-			for ( ; j >= 0 ; j--)
-				disconnect_port_ch(ctrl,
-						srch[j]);
-			kfree(slc->srch);
-			slc->srch = NULL;
-			goto connect_port_err;
+			for (j = j - 1; j >= 0; j--)
+				disconnect_port_ch(ctrl, sinkh[j]);
+			goto connect_sink_err;
 		}
 	}
-	/* connect sink */
-	ret = connect_port_ch(ctrl, chan, sinkh, SLIM_SINK);
-	if (ret) {
-		for (j = 0; j < nsrc; j++)
-			disconnect_port_ch(ctrl, srch[j]);
-		kfree(slc->srch);
-		slc->srch = NULL;
-		goto connect_port_err;
+
+	slc->sinkh = krealloc(slc->sinkh, (sizeof(u32) * (slc->nsink + nsink)),
+				GFP_KERNEL);
+	if (!slc->sinkh) {
+		ret = -ENOMEM;
+		for (j = 0; j < nsink; j++)
+			disconnect_port_ch(ctrl, sinkh[j]);
+		goto connect_sink_err;
 	}
 
-	memcpy(slc->srch, srch, (sizeof(u32) * nsrc));
-	slc->nsrc = nsrc;
-	if (sinkh)
-		slc->sinkh = sinkh;
+	memcpy(slc->sinkh + slc->nsink, sinkh, (sizeof(u32) * nsink));
+	slc->nsink += nsink;
 
-connect_port_err:
+connect_sink_err:
 	mutex_unlock(&ctrl->m_ctrl);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(slim_connect_ports);
+EXPORT_SYMBOL_GPL(slim_connect_sink);
 
 /*
  * slim_disconnect_ports: Disconnect port(s) from channel
@@ -1269,6 +1313,9 @@
 	int i, j;
 	int *len;
 	int sl = slc->seglen << slc->rootexp;
+	/* Channel is already active and other end is transmitting data */
+	if (slc->state >= SLIM_CH_ACTIVE)
+		return;
 	if (slc->coeff == SLIM_COEFF_1) {
 		arr = ctrl->sched.chc1;
 		len = &ctrl->sched.num_cc1;
@@ -1329,8 +1376,8 @@
 	slc->state = SLIM_CH_ALLOCATED;
 	slc->newintr = 0;
 	slc->newoff = 0;
-	for (i = 0; i < slc->nsrc; i++) {
-		ph = slc->srch[i];
+	for (i = 0; i < slc->nsink; i++) {
+		ph = slc->sinkh[i];
 		la = SLIM_HDL_TO_LA(ph);
 		/*
 		 * For ports managed by manager's ported device, no need to send
@@ -1341,11 +1388,15 @@
 			ctrl->ports[SLIM_HDL_TO_PORT(ph)].state = SLIM_P_UNCFG;
 	}
 
-	ph = slc->sinkh;
+	ph = slc->srch;
 	la = SLIM_HDL_TO_LA(ph);
 	if (la == SLIM_LA_MANAGER)
 		ctrl->ports[SLIM_HDL_TO_PORT(ph)].state = SLIM_P_UNCFG;
 
+	kfree(slc->sinkh);
+	slc->sinkh = NULL;
+	slc->srch = 0;
+	slc->nsink = 0;
 	return 0;
 }
 
@@ -1507,9 +1558,8 @@
  * slim_alloc_ch: Allocate a slimbus channel and return its handle.
  * @sb: client handle.
  * @chanh: return channel handle
- * Slimbus channels are limited to 256 per specification. LSB of the handle
- * indicates channel number and MSB of the handle is used by the slimbus
- * framework. -EXFULL is returned if all channels are in use.
+ * Slimbus channels are limited to 256 per specification.
+ * -EXFULL is returned if all channels are in use.
  * Although slimbus specification supports 256 channels, a controller may not
  * support that many channels.
  */
@@ -1532,6 +1582,7 @@
 	*chanh = i;
 	ctrl->chans[i].nextgrp = 0;
 	ctrl->chans[i].state = SLIM_CH_ALLOCATED;
+	ctrl->chans[i].chan = (u8)(ctrl->reserved + i);
 
 	mutex_unlock(&ctrl->m_ctrl);
 	return 0;
@@ -1539,28 +1590,99 @@
 EXPORT_SYMBOL_GPL(slim_alloc_ch);
 
 /*
+ * slim_query_ch: Get reference-counted handle for a channel number. Every
+ * channel is reference counted by upto one as producer and the others as
+ * consumer)
+ * @sb: client handle
+ * @chan: slimbus channel number
+ * @chanh: return channel handle
+ * If request channel number is not in use, it is allocated, and reference
+ * count is set to one. If the channel was was already allocated, this API
+ * will return handle to that channel and reference count is incremented.
+ * -EXFULL is returned if all channels are in use
+ */
+int slim_query_ch(struct slim_device *sb, u8 ch, u16 *chanh)
+{
+	struct slim_controller *ctrl = sb->ctrl;
+	u16 i, j;
+	int ret = 0;
+	if (!ctrl || !chanh)
+		return -EINVAL;
+	mutex_lock(&ctrl->m_ctrl);
+	/* start with modulo number */
+	i = ch % ctrl->nchans;
+
+	for (j = 0; j < ctrl->nchans; j++) {
+		if (ctrl->chans[i].chan == ch) {
+			*chanh = i;
+			ctrl->chans[i].ref++;
+			if (ctrl->chans[i].state == SLIM_CH_FREE)
+				ctrl->chans[i].state = SLIM_CH_ALLOCATED;
+			goto query_out;
+		}
+		i = (i + 1) % ctrl->nchans;
+	}
+
+	/* Channel not in table yet */
+	ret = -EXFULL;
+	for (j = 0; j < ctrl->nchans; j++) {
+		if (ctrl->chans[i].state == SLIM_CH_FREE) {
+			ctrl->chans[i].state =
+				SLIM_CH_ALLOCATED;
+			*chanh = i;
+			ctrl->chans[i].ref++;
+			ctrl->chans[i].chan = ch;
+			ctrl->chans[i].nextgrp = 0;
+			ret = 0;
+			break;
+		}
+		i = (i + 1) % ctrl->nchans;
+	}
+query_out:
+	mutex_unlock(&ctrl->m_ctrl);
+	dev_dbg(&ctrl->dev, "query ch:%d,hdl:%d,ref:%d,ret:%d",
+				ch, i, ctrl->chans[i].ref, ret);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(slim_query_ch);
+
+/*
  * slim_dealloc_ch: Deallocate channel allocated using the API above
  * -EISCONN is returned if the channel is tried to be deallocated without
  *  being removed first.
+ *  -ENOTCONN is returned if deallocation is tried on a channel that's not
+ *  allocated.
  */
 int slim_dealloc_ch(struct slim_device *sb, u16 chanh)
 {
 	struct slim_controller *ctrl = sb->ctrl;
-	u8 chan = (u8)(chanh & 0xFF);
+	u8 chan = SLIM_HDL_TO_CHIDX(chanh);
 	struct slim_ich *slc = &ctrl->chans[chan];
 	if (!ctrl)
 		return -EINVAL;
 
 	mutex_lock(&ctrl->m_ctrl);
+	if (slc->state == SLIM_CH_FREE) {
+		mutex_unlock(&ctrl->m_ctrl);
+		return -ENOTCONN;
+	}
+	if (slc->ref > 1) {
+		slc->ref--;
+		mutex_unlock(&ctrl->m_ctrl);
+		dev_dbg(&ctrl->dev, "remove chan:%d,hdl:%d,ref:%d",
+					slc->chan, chanh, slc->ref);
+		return 0;
+	}
 	if (slc->state >= SLIM_CH_PENDING_ACTIVE) {
 		dev_err(&ctrl->dev, "Channel:%d should be removed first", chan);
 		mutex_unlock(&ctrl->m_ctrl);
 		return -EISCONN;
 	}
-	kfree(slc->srch);
-	slc->srch = NULL;
+	slc->ref--;
 	slc->state = SLIM_CH_FREE;
 	mutex_unlock(&ctrl->m_ctrl);
+	dev_dbg(&ctrl->dev, "remove chan:%d,hdl:%d,ref:%d",
+				slc->chan, chanh, slc->ref);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(slim_dealloc_ch);
@@ -1571,7 +1693,7 @@
  */
 enum slim_ch_state slim_get_ch_state(struct slim_device *sb, u16 chanh)
 {
-	u8 chan = (u8)(chanh & 0xFF);
+	u8 chan = SLIM_HDL_TO_CHIDX(chanh);
 	struct slim_ich *slc = &sb->ctrl->chans[chan];
 	return slc->state;
 }
@@ -1589,8 +1711,8 @@
  * Channels can be grouped if multiple channels use same parameters
  * (e.g. 5.1 audio has 6 channels with same parameters. They will all be grouped
  * and given 1 handle for simplicity and avoid repeatedly calling the API)
- * -EISCONN is returned if the channel is already connected. -EBUSY is
- * returned if the channel is already allocated to some other client.
+ * -EISCONN is returned if channel is already used with different parameters.
+ * -ENXIO is returned if the channel is not yet allocated.
  */
 int slim_define_ch(struct slim_device *sb, struct slim_ch *prop, u16 *chanh,
 			u8 nchan, bool grp, u16 *grph)
@@ -1602,27 +1724,29 @@
 		return -EINVAL;
 	mutex_lock(&ctrl->m_ctrl);
 	for (i = 0; i < nchan; i++) {
-		u8 chan = (u8)(chanh[i] & 0xFF);
-		dev_dbg(&ctrl->dev, "define_ch: port:%d, state:%d", chanh[i],
+		u8 chan = SLIM_HDL_TO_CHIDX(chanh[i]);
+		struct slim_ich *slc = &ctrl->chans[chan];
+		dev_dbg(&ctrl->dev, "define_ch: ch:%d, state:%d", chan,
 				(int)ctrl->chans[chan].state);
-		if (ctrl->chans[chan].state < SLIM_CH_ALLOCATED ||
-			ctrl->chans[chan].state > SLIM_CH_DEFINED) {
-			int j;
-			for (j = i - 1; j >= 0; j--)
-				ctrl->chans[chan].state = SLIM_CH_ALLOCATED;
-			ret = -EBUSY;
+		if (slc->state < SLIM_CH_ALLOCATED) {
+			ret = -ENXIO;
 			goto err_define_ch;
 		}
-		ctrl->chans[chan].prop = *prop;
-		ret = slim_nextdefine_ch(sb, chan);
-		if (ret) {
-			int j;
-			for (j = i - 1; j >= 0; j--) {
-				chan = chanh[j] & 0xFF;
-				ctrl->chans[chan].nextgrp = 0;
-				ctrl->chans[chan].state = SLIM_CH_ALLOCATED;
+		if (slc->state >= SLIM_CH_DEFINED && slc->ref >= 2) {
+			if (prop->ratem != slc->prop.ratem ||
+			prop->sampleszbits != slc->prop.sampleszbits ||
+			prop->baser != slc->prop.baser) {
+				ret = -EISCONN;
+				goto err_define_ch;
 			}
+		} else if (slc->state > SLIM_CH_DEFINED) {
+			ret = -EISCONN;
 			goto err_define_ch;
+		} else {
+			ctrl->chans[chan].prop = *prop;
+			ret = slim_nextdefine_ch(sb, chan);
+			if (ret)
+				goto err_define_ch;
 		}
 		if (i < (nchan - 1))
 			ctrl->chans[chan].nextgrp = chanh[i + 1];
@@ -1630,13 +1754,18 @@
 			ctrl->chans[chan].nextgrp |= SLIM_START_GRP;
 		if (i == (nchan - 1))
 			ctrl->chans[chan].nextgrp |= SLIM_END_GRP;
-
-		ctrl->chans[chan].state = SLIM_CH_DEFINED;
 	}
 
 	if (grp)
 		*grph = chanh[0];
+	for (i = 0; i < nchan; i++) {
+		u8 chan = SLIM_HDL_TO_CHIDX(chanh[i]);
+		struct slim_ich *slc = &ctrl->chans[chan];
+		if (slc->state == SLIM_CH_ALLOCATED)
+			slc->state = SLIM_CH_DEFINED;
+	}
 err_define_ch:
+	dev_dbg(&ctrl->dev, "define_ch: ch:%d, ret:%d", *chanh, ret);
 	mutex_unlock(&ctrl->m_ctrl);
 	return ret;
 }
@@ -2182,7 +2311,7 @@
 	for (; last > 0; last--) {
 		struct slim_ich *slc1 = slc;
 		struct slim_ich *slc2;
-		u8 next = (u8)(slc1->nextgrp & 0xFF);
+		u8 next = SLIM_HDL_TO_CHIDX(slc1->nextgrp);
 		slc2 = &ctrl->chans[next];
 		for (second = 1; second <= last && slc2 &&
 			(slc2->state == SLIM_CH_ACTIVE ||
@@ -2197,7 +2326,7 @@
 				break;
 			}
 			slc1 = slc2;
-			next = (u8)(slc1->nextgrp & 0xFF);
+			next = SLIM_HDL_TO_CHIDX(slc1->nextgrp);
 			slc2 = &ctrl->chans[next];
 		}
 		if (slc2 == NULL)
@@ -2310,14 +2439,17 @@
 					struct slim_pending_ch, pending);
 		slc = &ctrl->chans[pch->chan];
 		if (revert) {
-			u32 sl = slc->seglen << slc->rootexp;
-			if (slc->coeff == SLIM_COEFF_3)
-				sl *= 3;
-			ctrl->sched.usedslots -= sl;
-			slim_remove_ch(ctrl, slc);
-			slc->state = SLIM_CH_DEFINED;
+			if (slc->state == SLIM_CH_PENDING_ACTIVE) {
+				u32 sl = slc->seglen << slc->rootexp;
+				if (slc->coeff == SLIM_COEFF_3)
+					sl *= 3;
+				ctrl->sched.usedslots -= sl;
+				slim_remove_ch(ctrl, slc);
+				slc->state = SLIM_CH_DEFINED;
+			}
 		} else {
 			slc->state = SLIM_CH_ACTIVE;
+			slc->def++;
 		}
 		list_del_init(&pch->pending);
 		kfree(pch);
@@ -2333,6 +2465,7 @@
 			if (slc->coeff == SLIM_COEFF_3)
 				sl *= 3;
 			ctrl->sched.usedslots += sl;
+			slc->def = 1;
 			slc->state = SLIM_CH_ACTIVE;
 		} else
 			slim_remove_ch(ctrl, slc);
@@ -2383,7 +2516,8 @@
 	list_for_each_entry(pch, &sb->mark_define, pending) {
 		struct slim_ich *slc = &ctrl->chans[pch->chan];
 		slim_add_ch(ctrl, slc);
-		slc->state = SLIM_CH_PENDING_ACTIVE;
+		if (slc->state < SLIM_CH_ACTIVE)
+			slc->state = SLIM_CH_PENDING_ACTIVE;
 	}
 
 	list_for_each_entry(pch, &sb->mark_removal, pending) {
@@ -2433,7 +2567,7 @@
 	list_for_each_entry(pch, &sb->mark_define, pending) {
 		struct slim_ich *slc = &ctrl->chans[pch->chan];
 		/* Define content */
-		wbuf[0] = pch->chan;
+		wbuf[0] = slc->chan;
 		wbuf[1] = slc->prrate;
 		wbuf[2] = slc->prop.dataf | (slc->prop.auxf << 4);
 		wbuf[3] = slc->prop.sampleszbits / SLIM_CL_PER_SL;
@@ -2456,8 +2590,9 @@
 	}
 
 	list_for_each_entry(pch, &sb->mark_removal, pending) {
+		struct slim_ich *slc = &ctrl->chans[pch->chan];
 		dev_dbg(&ctrl->dev, "remove chan:%x\n", pch->chan);
-		wbuf[0] = pch->chan;
+		wbuf[0] = slc->chan;
 		ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST,
 				SLIM_MSG_MC_NEXT_REMOVE_CHANNEL, 0,
 				SLIM_MSG_MT_CORE, NULL, wbuf, 1, 4,
@@ -2466,8 +2601,9 @@
 			goto revert_reconfig;
 	}
 	list_for_each_entry(pch, &sb->mark_suspend, pending) {
+		struct slim_ich *slc = &ctrl->chans[pch->chan];
 		dev_dbg(&ctrl->dev, "suspend chan:%x\n", pch->chan);
-		wbuf[0] = pch->chan;
+		wbuf[0] = slc->chan;
 		ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST,
 				SLIM_MSG_MC_NEXT_DEACTIVATE_CHANNEL, 0,
 				SLIM_MSG_MT_CORE, NULL, wbuf, 1, 4,
@@ -2489,13 +2625,13 @@
 		dev_dbg(&ctrl->dev, "new-off:%d, old-off:%d\n",
 				slc->newoff, slc->offset);
 
-		if (slc->state < SLIM_CH_ACTIVE ||
+		if (slc->state < SLIM_CH_ACTIVE || slc->def < slc->ref ||
 			slc->newintr != slc->interval ||
 			slc->newoff != slc->offset) {
 			segdist |= 0x200;
 			segdist >>= curexp;
 			segdist |= (slc->newoff << (curexp + 1)) & 0xC00;
-			wbuf[0] = (u8)(slc - ctrl->chans);
+			wbuf[0] = slc->chan;
 			wbuf[1] = (u8)(segdist & 0xFF);
 			wbuf[2] = (u8)((segdist & 0xF00) >> 8) |
 					(slc->prop.prot << 4);
@@ -2522,13 +2658,13 @@
 		dev_dbg(&ctrl->dev, "new-off:%d, old-off:%d\n",
 				slc->newoff, slc->offset);
 
-		if (slc->state < SLIM_CH_ACTIVE ||
+		if (slc->state < SLIM_CH_ACTIVE || slc->def < slc->ref ||
 			slc->newintr != slc->interval ||
 			slc->newoff != slc->offset) {
 			segdist |= 0x200;
 			segdist >>= curexp;
 			segdist |= 0xC00;
-			wbuf[0] = (u8)(slc - ctrl->chans);
+			wbuf[0] = slc->chan;
 			wbuf[1] = (u8)(segdist & 0xFF);
 			wbuf[2] = (u8)((segdist & 0xF00) >> 8) |
 					(slc->prop.prot << 4);
@@ -2602,11 +2738,13 @@
 	struct slim_ich *slc;
 	int ret = 0;
 	/* Get rid of the group flag in MSB if any */
-	u8 chan = (u8)(chanh & 0xFF);
+	u8 chan = SLIM_HDL_TO_CHIDX(chanh);
 	mutex_lock(&sb->sldev_reconf);
 	mutex_lock(&ctrl->m_ctrl);
 	do {
 		slc = &ctrl->chans[chan];
+		dev_dbg(&ctrl->dev, "chan:%d,ctrl:%d,def:%d", chan, chctrl,
+					slc->def);
 		if (slc->state < SLIM_CH_DEFINED) {
 			ret = -ENOTCONN;
 			break;
@@ -2616,7 +2754,7 @@
 			if (ret)
 				break;
 		} else if (chctrl == SLIM_CH_ACTIVATE) {
-			if (slc->state >= SLIM_CH_ACTIVE) {
+			if (slc->state > SLIM_CH_ACTIVE) {
 				ret = -EISCONN;
 				break;
 			}
@@ -2628,13 +2766,16 @@
 				ret = -ENOTCONN;
 				break;
 			}
-			ret = add_pending_ch(&sb->mark_removal, chan);
+			if (slc->def > 0)
+				slc->def--;
+			if (slc->def == 0)
+				ret = add_pending_ch(&sb->mark_removal, chan);
 			if (ret)
 				break;
 		}
 
 		if (!(slc->nextgrp & SLIM_END_GRP))
-			chan = (u8)(slc->nextgrp & 0xFF);
+			chan = SLIM_HDL_TO_CHIDX(slc->nextgrp);
 	} while (!(slc->nextgrp & SLIM_END_GRP));
 	mutex_unlock(&ctrl->m_ctrl);
 	if (!ret && commit == true)
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index 17b9f0d..e2d77e9 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -1283,8 +1283,8 @@
 	if (dd->use_rlock)
 		remote_mutex_lock(&dd->r_lock);
 
-	clk_enable(dd->clk);
-	clk_enable(dd->pclk);
+	clk_prepare_enable(dd->clk);
+	clk_prepare_enable(dd->pclk);
 	msm_spi_enable_irqs(dd);
 
 	if (!msm_spi_is_valid_state(dd)) {
@@ -1311,8 +1311,8 @@
 	spin_unlock_irqrestore(&dd->queue_lock, flags);
 
 	msm_spi_disable_irqs(dd);
-	clk_disable(dd->clk);
-	clk_disable(dd->pclk);
+	clk_disable_unprepare(dd->clk);
+	clk_disable_unprepare(dd->pclk);
 
 	if (dd->use_rlock)
 		remote_mutex_unlock(&dd->r_lock);
@@ -1400,8 +1400,8 @@
 	if (dd->use_rlock)
 		remote_mutex_lock(&dd->r_lock);
 
-	clk_enable(dd->clk);
-	clk_enable(dd->pclk);
+	clk_prepare_enable(dd->clk);
+	clk_prepare_enable(dd->pclk);
 
 	spi_ioc = readl_relaxed(dd->base + SPI_IO_CONTROL);
 	mask = SPI_IO_C_CS_N_POLARITY_0 << spi->chip_select;
@@ -1429,8 +1429,8 @@
 
 	/* Ensure previous write completed before disabling the clocks */
 	mb();
-	clk_disable(dd->clk);
-	clk_disable(dd->pclk);
+	clk_disable_unprepare(dd->clk);
+	clk_disable_unprepare(dd->pclk);
 
 	if (dd->use_rlock)
 		remote_mutex_unlock(&dd->r_lock);
@@ -1925,7 +1925,7 @@
 	if (pdata && pdata->max_clock_speed)
 		msm_spi_clock_set(dd, dd->pdata->max_clock_speed);
 
-	rc = clk_enable(dd->clk);
+	rc = clk_prepare_enable(dd->clk);
 	if (rc) {
 		dev_err(&pdev->dev, "%s: unable to enable core_clk\n",
 			__func__);
@@ -1933,7 +1933,7 @@
 	}
 
 	clk_enabled = 1;
-	rc = clk_enable(dd->pclk);
+	rc = clk_prepare_enable(dd->pclk);
 	if (rc) {
 		dev_err(&pdev->dev, "%s: unable to enable iface_clk\n",
 		__func__);
@@ -1966,8 +1966,8 @@
 	if (rc)
 		goto err_probe_state;
 
-	clk_disable(dd->clk);
-	clk_disable(dd->pclk);
+	clk_disable_unprepare(dd->clk);
+	clk_disable_unprepare(dd->pclk);
 	clk_enabled = 0;
 	pclk_enabled = 0;
 
@@ -2009,10 +2009,10 @@
 err_probe_dma:
 err_probe_gsbi:
 	if (pclk_enabled)
-		clk_disable(dd->pclk);
+		clk_disable_unprepare(dd->pclk);
 err_probe_pclk_enable:
 	if (clk_enabled)
-		clk_disable(dd->clk);
+		clk_disable_unprepare(dd->clk);
 err_probe_clk_enable:
 	clk_put(dd->pclk);
 err_probe_pclk_get:
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/Kconfig b/drivers/thermal/Kconfig
index 794775a..5163886 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -66,3 +66,13 @@
 	  Enabling the thermal zone device via the mode file results in
 	  shifting over temperature shutdown control of the PMIC from hardware
 	  to software.
+
+config THERMAL_MONITOR
+	bool "Monitor thermal state and limit CPU Frequency"
+	depends on THERMAL_TSENS8960
+	default n
+	help
+	  This enables thermal monitoring capability in the kernel in the
+	  absence of a system wide thermal monitoring entity or until such an
+	  entity starts running in the userspace. Monitors TSENS temperature
+	  and limits the max frequency of the cores.
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 31b5c3f..63b7056 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -7,3 +7,4 @@
 obj-$(CONFIG_THERMAL_TSENS)	+= msm_tsens.o
 obj-$(CONFIG_THERMAL_TSENS8960) += msm8960_tsens.o
 obj-$(CONFIG_THERMAL_PM8XXX)	+= pm8xxx-tm.o
+obj-$(CONFIG_THERMAL_MONITOR)	+= msm_thermal.o
diff --git a/drivers/thermal/msm8960_tsens.c b/drivers/thermal/msm8960_tsens.c
index a616ffc..2a2166a 100644
--- a/drivers/thermal/msm8960_tsens.c
+++ b/drivers/thermal/msm8960_tsens.c
@@ -165,29 +165,46 @@
 	return code;
 }
 
-static int tsens_tz_get_temp(struct thermal_zone_device *thermal,
-			     unsigned long *temp)
+static void tsens8960_get_temp(int sensor_num, unsigned long *temp)
 {
-	struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
 	unsigned int code;
 
-	if (!tm_sensor || tm_sensor->mode != THERMAL_DEVICE_ENABLED || !temp)
-		return -EINVAL;
-
 	if (!tmdev->prev_reading_avail) {
-		while (!(readl_relaxed(TSENS_INT_STATUS_ADDR) &
-						TSENS_TRDY_MASK))
+		while (!(readl_relaxed(TSENS_INT_STATUS_ADDR)
+					& TSENS_TRDY_MASK))
 			usleep_range(TSENS_TRDY_RDY_MIN_TIME,
 				TSENS_TRDY_RDY_MAX_TIME);
 		tmdev->prev_reading_avail = true;
 	}
 	code = readl_relaxed(TSENS_S0_STATUS_ADDR +
-			(tm_sensor->sensor_num << TSENS_STATUS_ADDR_OFFSET));
-	*temp = tsens_tz_code_to_degC(code, tm_sensor->sensor_num);
+			(sensor_num << TSENS_STATUS_ADDR_OFFSET));
+	*temp = tsens_tz_code_to_degC(code, sensor_num);
+}
+
+static int tsens_tz_get_temp(struct thermal_zone_device *thermal,
+			     unsigned long *temp)
+{
+	struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
+
+	if (!tm_sensor || tm_sensor->mode != THERMAL_DEVICE_ENABLED || !temp)
+		return -EINVAL;
+
+	tsens8960_get_temp(tm_sensor->sensor_num, temp);
 
 	return 0;
 }
 
+int tsens_get_temp(struct tsens_device *device, unsigned long *temp)
+{
+	if (!tmdev)
+		return -ENODEV;
+
+	tsens8960_get_temp(device->sensor_num, temp);
+
+	return 0;
+}
+EXPORT_SYMBOL(tsens_get_temp);
+
 static int tsens_tz_get_mode(struct thermal_zone_device *thermal,
 			      enum thermal_device_mode *mode)
 {
@@ -708,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;
 		}
@@ -745,12 +762,10 @@
 	return rc;
 }
 
-static int __devinit tsens_tm_probe(struct platform_device *pdev)
+int msm_tsens_early_init(struct tsens_platform_data *pdata)
 {
-	int rc, i;
-	struct tsens_platform_data *pdata;
+	int rc = 0;
 
-	pdata = pdev->dev.platform_data;
 	if (!pdata) {
 		pr_err("No TSENS Platform data\n");
 		return -EINVAL;
@@ -759,7 +774,7 @@
 	tmdev = kzalloc(sizeof(struct tsens_tm_device) +
 			pdata->tsens_num_sensor *
 			sizeof(struct tsens_tm_device_sensor),
-			GFP_KERNEL);
+			GFP_ATOMIC);
 	if (tmdev == NULL) {
 		pr_err("%s: kzalloc() failed.\n", __func__);
 		return -ENOMEM;
@@ -773,20 +788,34 @@
 	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;
 	}
 
-	platform_set_drvdata(pdev, tmdev);
-
 	tsens_hw_init();
 
-	for (i = 0; i < pdata->tsens_num_sensor; i++) {
+	pr_info("msm_tsens_early_init: done\n");
+
+	return rc;
+}
+
+static int __init tsens_tm_init(void)
+{
+	int rc, i;
+
+	if (!tmdev) {
+		pr_info("%s : TSENS early init not done.\n", __func__);
+		return -EFAULT;
+	}
+
+	for (i = 0; i < tmdev->tsens_num_sensor; i++) {
 		char name[17];
 		snprintf(name, sizeof(name), "tsens_tz_sensor%d", i);
 		tmdev->sensor[i].mode = THERMAL_DEVICE_ENABLED;
@@ -812,22 +841,19 @@
 		goto fail;
 	}
 
-	tsens_disable_mode();
-
 	pr_notice("%s: OK\n", __func__);
 	mb();
 	return 0;
 fail:
 	tsens_disable_mode();
-	platform_set_drvdata(pdev, NULL);
 	kfree(tmdev);
+	tmdev = NULL;
 	mb();
 	return rc;
 }
 
-static int __devexit tsens_tm_remove(struct platform_device *pdev)
+static void __exit tsens_tm_remove(void)
 {
-	struct tsens_tm_device *tmdev = platform_get_drvdata(pdev);
 	int i;
 
 	tsens_disable_mode();
@@ -835,32 +861,12 @@
 	free_irq(TSENS_UPPER_LOWER_INT, tmdev);
 	for (i = 0; i < tmdev->tsens_num_sensor; i++)
 		thermal_zone_device_unregister(tmdev->sensor[i].tz_dev);
-	platform_set_drvdata(pdev, NULL);
 	kfree(tmdev);
-	return 0;
+	tmdev = NULL;
 }
 
-static struct platform_driver tsens_tm_driver = {
-	.probe	= tsens_tm_probe,
-	.remove	= __devexit_p(tsens_tm_remove),
-	.driver	= {
-		.name = "tsens8960-tm",
-		.owner = THIS_MODULE,
-	},
-};
-
-static int __init tsens_init(void)
-{
-	return platform_driver_register(&tsens_tm_driver);
-}
-
-static void __exit tsens_exit(void)
-{
-	platform_driver_unregister(&tsens_tm_driver);
-}
-
-module_init(tsens_init);
-module_exit(tsens_exit);
+module_init(tsens_tm_init);
+module_exit(tsens_tm_remove);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("MSM8960 Temperature Sensor driver");
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
new file mode 100644
index 0000000..ed80b1b
--- /dev/null
+++ b/drivers/thermal/msm_thermal.c
@@ -0,0 +1,189 @@
+/* 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/cpufreq.h>
+#include <linux/mutex.h>
+#include <linux/msm_tsens.h>
+#include <linux/workqueue.h>
+
+#define DEF_TEMP_SENSOR      0
+#define DEF_THERMAL_CHECK_MS 1000
+#define DEF_ALLOWED_MAX_HIGH 60
+#define DEF_ALLOWED_MAX_FREQ 918000
+
+static int enabled;
+static int allowed_max_high = DEF_ALLOWED_MAX_HIGH;
+static int allowed_max_low = (DEF_ALLOWED_MAX_HIGH - 10);
+static int allowed_max_freq = DEF_ALLOWED_MAX_FREQ;
+static int check_interval_ms = DEF_THERMAL_CHECK_MS;
+
+module_param(allowed_max_high, int, 0);
+module_param(allowed_max_freq, int, 0);
+module_param(check_interval_ms, int, 0);
+
+static DEFINE_PER_CPU(struct cpufreq_policy*, policy);
+static struct mutex policy_mutex;
+static struct delayed_work check_temp_work;
+
+static int update_cpu_max_freq(int cpu, int max_freq)
+{
+	struct cpufreq_policy *cpu_policy = per_cpu(policy, cpu);
+	int ret = 0;
+
+	if (!cpu_policy)
+		return -EINVAL;
+
+	cpufreq_verify_within_limits(cpu_policy,
+				cpu_policy->min, max_freq);
+	cpu_policy->user_policy.max = max_freq;
+
+	ret = cpufreq_update_policy(cpu);
+	if (ret)
+		pr_err("msm_thermal: cpufreq update to core%d %d err:%d\n",
+				cpu, max_freq, ret);
+	else
+		pr_info("msm_thermal: Limiting core%d max frequency to %d\n",
+			cpu, max_freq);
+
+	return ret;
+}
+
+static void check_temp(struct work_struct *work)
+{
+	struct cpufreq_policy *cpu_policy = NULL;
+	struct tsens_device tsens_dev;
+	unsigned long temp = 0;
+	unsigned int max_freq = 0;
+	int update_policy = 0;
+	int cpu = 0;
+	int ret = 0;
+
+	mutex_lock(&policy_mutex);
+	tsens_dev.sensor_num = DEF_TEMP_SENSOR;
+	ret = tsens_get_temp(&tsens_dev, &temp);
+	if (ret) {
+		pr_debug("msm_thermal: Unable to read TSENS sensor %d\n",
+				tsens_dev.sensor_num);
+		goto reschedule;
+	}
+
+	for_each_possible_cpu(cpu) {
+		cpu_policy = per_cpu(policy, cpu);
+		if (!cpu_policy) {
+			pr_debug("msm_thermal: No CPUFreq policy found for "
+				"cpu %d\n", cpu);
+			continue;
+		}
+		if (temp >= allowed_max_high) {
+			if (cpu_policy->max > allowed_max_freq) {
+				update_policy = 1;
+				max_freq = allowed_max_freq;
+			}
+		} else if (temp < allowed_max_low) {
+			if (cpu_policy->max < cpu_policy->cpuinfo.max_freq) {
+				max_freq = cpu_policy->cpuinfo.max_freq;
+				update_policy = 1;
+			}
+		}
+
+		if (update_policy)
+			update_cpu_max_freq(cpu, max_freq);
+	}
+
+reschedule:
+	if (enabled)
+		schedule_delayed_work(&check_temp_work,
+				msecs_to_jiffies(check_interval_ms));
+
+	mutex_unlock(&policy_mutex);
+}
+
+static int msm_thermal_notifier(struct notifier_block *nb,
+		unsigned long event, void *data)
+{
+	if (event == CPUFREQ_START) {
+		struct cpufreq_policy *cpu_policy = data;
+		mutex_lock(&policy_mutex);
+		per_cpu(policy, cpu_policy->cpu) = cpu_policy;
+		mutex_unlock(&policy_mutex);
+	}
+
+	return 0;
+}
+
+static struct notifier_block msm_thermal_notifier_block = {
+	.notifier_call = msm_thermal_notifier,
+};
+
+static void disable_msm_thermal(void)
+{
+	int cpu = 0;
+	struct cpufreq_policy *cpu_policy = NULL;
+
+	cpufreq_unregister_notifier(&msm_thermal_notifier_block,
+			CPUFREQ_POLICY_NOTIFIER);
+	cancel_delayed_work(&check_temp_work);
+
+	mutex_lock(&policy_mutex);
+	for_each_possible_cpu(cpu) {
+		cpu_policy = per_cpu(policy, cpu);
+		if (cpu_policy &&
+			cpu_policy->max < cpu_policy->cpuinfo.max_freq)
+			update_cpu_max_freq(cpu, cpu_policy->cpuinfo.max_freq);
+	}
+	mutex_unlock(&policy_mutex);
+}
+
+static int set_enabled(const char *val, const struct kernel_param *kp)
+{
+	int ret = 0;
+
+	ret = param_set_bool(val, kp);
+	if (!enabled)
+		disable_msm_thermal();
+	else
+		pr_info("msm_thermal: no action for enabled = %d\n", enabled);
+
+	pr_info("msm_thermal: enabled = %d\n", enabled);
+
+	return ret;
+}
+
+static struct kernel_param_ops module_ops = {
+	.set = set_enabled,
+	.get = param_get_bool,
+};
+
+module_param_cb(enabled, &module_ops, &enabled, 0644);
+MODULE_PARM_DESC(enabled, "enforce thermal limit on cpu");
+
+static int __init msm_thermal_init(void)
+{
+	int ret = 0;
+
+	enabled = 1;
+	mutex_init(&policy_mutex);
+	INIT_DELAYED_WORK(&check_temp_work, check_temp);
+
+	ret = cpufreq_register_notifier(&msm_thermal_notifier_block,
+			CPUFREQ_POLICY_NOTIFIER);
+
+	schedule_delayed_work(&check_temp_work, 0);
+
+	return ret;
+}
+fs_initcall(msm_thermal_init);
+
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 9dc4044..c0c6c1e 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -2,7 +2,7 @@
  * Gadget Driver for Android
  *
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  * Author: Mike Lockwood <lockwood@android.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -1472,53 +1472,83 @@
 	return 0;
 }
 
+static void android_destroy_device(struct android_dev *dev)
+{
+	struct device_attribute **attrs = android_usb_attributes;
+	struct device_attribute *attr;
+
+	while ((attr = *attrs++))
+		device_remove_file(dev->dev, attr);
+	device_destroy(android_class, dev->dev->devt);
+}
+
 static int __devinit android_probe(struct platform_device *pdev)
 {
 	struct android_usb_platform_data *pdata = pdev->dev.platform_data;
 	struct android_dev *dev = _android_dev;
 
 	dev->pdata = pdata;
-	
+
 	return 0;
 }
 
 static struct platform_driver android_platform_driver = {
+	.probe = android_probe,
 	.driver = { .name = "android_usb"},
 };
 
 static int __init init(void)
 {
 	struct android_dev *dev;
-	int err;
+	int ret;
 
 	android_class = class_create(THIS_MODULE, "android_usb");
 	if (IS_ERR(android_class))
 		return PTR_ERR(android_class);
 
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev)
+	if (!dev) {
+		pr_err("%s(): Failed to alloc memory for android_dev\n",
+				__func__);
+		class_destroy(android_class);
 		return -ENOMEM;
-
+	}
 	dev->functions = supported_functions;
 	INIT_LIST_HEAD(&dev->enabled_functions);
 	INIT_WORK(&dev->work, android_work);
 
-	err = android_create_device(dev);
-	if (err) {
-		class_destroy(android_class);
-		kfree(dev);
-		return err;
+	ret = android_create_device(dev);
+	if (ret) {
+		pr_err("%s(): android_create_device failed\n", __func__);
+		goto err_dev;
 	}
-
 	_android_dev = dev;
 
 	/* Override composite driver functions */
 	composite_driver.setup = android_setup;
 	composite_driver.disconnect = android_disconnect;
 
-	platform_driver_probe(&android_platform_driver, android_probe);
+	ret = platform_driver_register(&android_platform_driver);
+	if (ret) {
+		pr_err("%s(): Failed to register android"
+				 "platform driver\n", __func__);
+		goto err_probe;
+	}
+	ret = usb_composite_probe(&android_usb_driver, android_bind);
+	if (ret) {
+		pr_err("%s(): Failed to register android"
+				 "composite driver\n", __func__);
+		platform_driver_unregister(&android_platform_driver);
+		goto err_probe;
+	}
+	return ret;
 
-	return usb_composite_probe(&android_usb_driver, android_bind);
+err_probe:
+	android_destroy_device(dev);
+err_dev:
+	kfree(dev);
+	class_destroy(android_class);
+	return ret;
 }
 module_init(init);
 
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 69a36af..380ef87 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -755,6 +755,8 @@
 
 		/* copy descriptors, and track endpoint copies */
 		f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
+		if (!f->hs_descriptors)
+			goto fail;
 
 		acm->hs.in = usb_find_endpoint(acm_hs_function,
 				f->hs_descriptors, &acm_hs_in_desc);
@@ -772,6 +774,11 @@
 	return 0;
 
 fail:
+	if (f->hs_descriptors)
+		usb_free_descriptors(f->hs_descriptors);
+	if (f->descriptors)
+		usb_free_descriptors(f->descriptors);
+
 	if (acm->notify_req)
 		gs_free_req(acm->notify, acm->notify_req);
 
diff --git a/drivers/usb/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 177176e..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);
@@ -426,6 +424,23 @@
 	kfree(f->name);
 }
 
+static void frmnet_suspend(struct usb_function *f)
+{
+	struct f_rmnet *dev = func_to_rmnet(f);
+	unsigned port_num;
+
+	if (!atomic_read(&dev->online))
+		return;
+	/* This is a workaround for a bug in Windows 7/XP hosts in which
+	 * the DTR bit is not set low when going into suspend. Hence force it
+	 * low here when this function driver is suspended.
+	 */
+	if (dev->port.notify_modem) {
+		port_num = rmnet_ports[dev->port_num].ctrl_xport_num;
+		dev->port.notify_modem(&dev->port, port_num, ~ACM_CTRL_DTR);
+	}
+}
+
 static void frmnet_disable(struct usb_function *f)
 {
 	struct f_rmnet *dev = func_to_rmnet(f);
@@ -937,6 +952,7 @@
 	f->disable = frmnet_disable;
 	f->set_alt = frmnet_set_alt;
 	f->setup = frmnet_setup;
+	f->suspend = frmnet_suspend;
 	dev->port.send_cpkt_response = frmnet_send_cpkt_response;
 	dev->port.disconnect = frmnet_disconnect;
 	dev->port.connect = frmnet_connect;
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 23e0da8..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;
@@ -177,19 +177,15 @@
 /*--------------------------------------------- */
 
 /*------------data_path----------------------------*/
-static void gbam_write_data_tohost(struct work_struct *w)
+static void gbam_write_data_tohost(struct gbam_port *port)
 {
 	unsigned long			flags;
-	struct bam_ch_info	*d;
-	struct gbam_port	*port;
+	struct bam_ch_info		*d = &port->data_ch;
 	struct sk_buff			*skb;
 	int				ret;
 	struct usb_request		*req;
 	struct usb_ep			*ep;
 
-	d = container_of(w, struct bam_ch_info, write_tohost_w);
-	port = d->port;
-
 	spin_lock_irqsave(&port->port_lock_dl, flags);
 	if (!port->port_usb) {
 		spin_unlock_irqrestore(&port->port_lock_dl, flags);
@@ -234,6 +230,17 @@
 	spin_unlock_irqrestore(&port->port_lock_dl, flags);
 }
 
+static void gbam_write_data_tohost_w(struct work_struct *w)
+{
+	struct bam_ch_info	*d;
+	struct gbam_port	*port;
+
+	d = container_of(w, struct bam_ch_info, write_tohost_w);
+	port = d->port;
+
+	gbam_write_data_tohost(port);
+}
+
 void gbam_data_recv_cb(void *p, struct sk_buff *skb)
 {
 	struct gbam_port	*port = p;
@@ -266,7 +273,7 @@
 	__skb_queue_tail(&d->tx_skb_q, skb);
 	spin_unlock_irqrestore(&port->port_lock_dl, flags);
 
-	queue_work(gbam_wq, &d->write_tohost_w);
+	gbam_write_data_tohost(port);
 }
 
 void gbam_data_write_done(void *p, struct sk_buff *skb)
@@ -877,7 +884,7 @@
 	INIT_LIST_HEAD(&d->tx_idle);
 	INIT_LIST_HEAD(&d->rx_idle);
 	INIT_WORK(&d->write_tobam_w, gbam_data_write_tobam);
-	INIT_WORK(&d->write_tohost_w, gbam_write_data_tohost);
+	INIT_WORK(&d->write_tohost_w, gbam_write_data_tohost_w);
 	skb_queue_head_init(&d->tx_skb_q);
 	skb_queue_head_init(&d->rx_skb_q);
 	d->id = bam_ch_ids[portno];
diff --git a/drivers/usb/gadget/u_data_hsic.c b/drivers/usb/gadget/u_data_hsic.c
index 61458ea..7b77a1d 100644
--- a/drivers/usb/gadget/u_data_hsic.c
+++ b/drivers/usb/gadget/u_data_hsic.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
@@ -37,6 +37,7 @@
 #define GHSIC_DATA_SERIAL_RX_Q_SIZE		2
 #define GHSIC_DATA_SERIAL_TX_Q_SIZE		2
 #define GHSIC_DATA_RX_REQ_SIZE			2048
+#define GHSIC_DATA_TX_INTR_THRESHOLD		20
 
 static unsigned int ghsic_data_rmnet_tx_q_size = GHSIC_DATA_RMNET_TX_Q_SIZE;
 module_param(ghsic_data_rmnet_tx_q_size, uint, S_IRUGO | S_IWUSR);
@@ -53,6 +54,9 @@
 static unsigned int ghsic_data_rx_req_size = GHSIC_DATA_RX_REQ_SIZE;
 module_param(ghsic_data_rx_req_size, uint, S_IRUGO | S_IWUSR);
 
+unsigned int ghsic_data_tx_intr_thld = GHSIC_DATA_TX_INTR_THRESHOLD;
+module_param(ghsic_data_tx_intr_thld, uint, S_IRUGO | S_IWUSR);
+
 /*flow ctrl*/
 #define GHSIC_DATA_FLOW_CTRL_EN_THRESHOLD	500
 #define GHSIC_DATA_FLOW_CTRL_DISABLE		300
@@ -109,6 +113,8 @@
 	/*bridge status*/
 	unsigned long		bridge_sts;
 
+	unsigned int		n_tx_req_queued;
+
 	/*counters*/
 	unsigned long		to_modem;
 	unsigned long		to_host;
@@ -125,6 +131,8 @@
 	struct platform_driver	pdrv;
 } gdata_ports[NUM_PORTS];
 
+static unsigned int get_timestamp(void);
+static void dbg_timestamp(char *, struct sk_buff *);
 static void ghsic_data_start_rx(struct gdata_port *port);
 
 static void ghsic_data_free_requests(struct usb_ep *ep, struct list_head *head)
@@ -188,6 +196,7 @@
 	struct usb_request	*req;
 	struct usb_ep		*ep;
 	struct gdata_port	*port;
+	struct timestamp_info	*info;
 
 	port = container_of(w, struct gdata_port, write_tohost_w);
 
@@ -210,8 +219,18 @@
 		req->buf = skb->data;
 		req->length = skb->len;
 
+		port->n_tx_req_queued++;
+		if (port->n_tx_req_queued == ghsic_data_tx_intr_thld) {
+			req->no_interrupt = 0;
+			port->n_tx_req_queued = 0;
+		} else {
+			req->no_interrupt = 1;
+		}
+
 		list_del(&req->list);
 
+		info = (struct timestamp_info *)skb->cb;
+		info->tx_queued = get_timestamp();
 		spin_unlock_irqrestore(&port->port_lock, flags);
 		ret = usb_ep_queue(ep, req, GFP_KERNEL);
 		spin_lock_irqsave(&port->port_lock, flags);
@@ -281,6 +300,7 @@
 {
 	struct gdata_port	*port;
 	struct sk_buff		*skb;
+	struct timestamp_info	*info;
 	unsigned long		flags;
 	int			ret;
 
@@ -301,6 +321,8 @@
 		pr_debug("%s: port:%p tom:%lu pno:%d\n", __func__,
 				port, port->to_modem, port->port_num);
 
+		info = (struct timestamp_info *)skb->cb;
+		info->rx_done_sent = get_timestamp();
 		spin_unlock_irqrestore(&port->port_lock, flags);
 		ret = data_bridge_write(port->brdg.ch_id, skb);
 		spin_lock_irqsave(&port->port_lock, flags);
@@ -332,6 +354,7 @@
 	switch (status) {
 	case 0:
 		/* successful completion */
+		dbg_timestamp("DL", skb);
 		break;
 	case -ECONNRESET:
 	case -ESHUTDOWN:
@@ -359,6 +382,7 @@
 {
 	struct gdata_port	*port = ep->driver_data;
 	struct sk_buff		*skb = req->context;
+	struct timestamp_info	*info = (struct timestamp_info *)skb->cb;
 	int			status = req->status;
 	int			queue = 0;
 
@@ -384,6 +408,7 @@
 
 	spin_lock(&port->port_lock);
 	if (queue) {
+		info->rx_done = get_timestamp();
 		__skb_queue_tail(&port->rx_skb_q, skb);
 		list_add_tail(&req->list, &port->rx_idle);
 		queue_work(port->wq, &port->write_tomdm_w);
@@ -398,6 +423,8 @@
 	unsigned long		flags;
 	int			ret;
 	struct sk_buff		*skb;
+	struct timestamp_info	*info;
+	unsigned int		created;
 
 	pr_debug("%s: port:%p\n", __func__, port);
 	spin_lock_irqsave(&port->port_lock, flags);
@@ -415,15 +442,18 @@
 		req = list_first_entry(&port->rx_idle,
 					struct usb_request, list);
 
+		created = get_timestamp();
 		skb = alloc_skb(ghsic_data_rx_req_size, GFP_ATOMIC);
 		if (!skb)
 			break;
-
+		info = (struct timestamp_info *)skb->cb;
+		info->created = created;
 		list_del(&req->list);
 		req->buf = skb->data;
 		req->length = ghsic_data_rx_req_size;
 		req->context = skb;
 
+		info->rx_queued = get_timestamp();
 		spin_unlock_irqrestore(&port->port_lock, flags);
 		ret = usb_ep_queue(ep, req, GFP_KERNEL);
 		spin_lock_irqsave(&port->port_lock, flags);
@@ -698,6 +728,7 @@
 	port->port_usb = 0;
 	port->in = NULL;
 	port->out = NULL;
+	port->n_tx_req_queued = 0;
 	clear_bit(TX_THROTTLED, &port->brdg.flags);
 	clear_bit(RX_THROTTLED, &port->brdg.flags);
 	spin_unlock_irqrestore(&port->port_lock, flags);
@@ -784,6 +815,103 @@
 
 #if defined(CONFIG_DEBUG_FS)
 #define DEBUG_BUF_SIZE 1024
+
+static unsigned int	record_timestamp;
+module_param(record_timestamp, uint, S_IRUGO | S_IWUSR);
+
+static struct timestamp_buf dbg_data = {
+	.idx = 0,
+	.lck = __RW_LOCK_UNLOCKED(lck)
+};
+
+/*get_timestamp - returns time of day in us */
+static unsigned int get_timestamp(void)
+{
+	struct timeval	tval;
+	unsigned int	stamp;
+
+	if (!record_timestamp)
+		return 0;
+
+	do_gettimeofday(&tval);
+	/* 2^32 = 4294967296. Limit to 4096s. */
+	stamp = tval.tv_sec & 0xFFF;
+	stamp = stamp * 1000000 + tval.tv_usec;
+	return stamp;
+}
+
+static void dbg_inc(unsigned *idx)
+{
+	*idx = (*idx + 1) & (DBG_DATA_MAX-1);
+}
+
+/**
+* dbg_timestamp - Stores timestamp values of a SKB life cycle
+*	to debug buffer
+* @event: "DL": Downlink Data
+* @skb: SKB used to store timestamp values to debug buffer
+*/
+static void dbg_timestamp(char *event, struct sk_buff * skb)
+{
+	unsigned long		flags;
+	struct timestamp_info	*info = (struct timestamp_info *)skb->cb;
+
+	if (!record_timestamp)
+		return;
+
+	write_lock_irqsave(&dbg_data.lck, flags);
+
+	scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
+		  "%p %u[%s] %u %u %u %u %u %u\n",
+		  skb, skb->len, event, info->created, info->rx_queued,
+		  info->rx_done, info->rx_done_sent, info->tx_queued,
+		  get_timestamp());
+
+	dbg_inc(&dbg_data.idx);
+
+	write_unlock_irqrestore(&dbg_data.lck, flags);
+}
+
+/* show_timestamp: displays the timestamp buffer */
+static ssize_t show_timestamp(struct file *file, char __user *ubuf,
+		size_t count, loff_t *ppos)
+{
+	unsigned long	flags;
+	unsigned	i;
+	unsigned	j = 0;
+	char		*buf;
+	int		ret = 0;
+
+	if (!record_timestamp)
+		return 0;
+
+	buf = kzalloc(sizeof(char) * 4 * DEBUG_BUF_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	read_lock_irqsave(&dbg_data.lck, flags);
+
+	i = dbg_data.idx;
+	for (dbg_inc(&i); i != dbg_data.idx; dbg_inc(&i)) {
+		if (!strnlen(dbg_data.buf[i], DBG_DATA_MSG))
+			continue;
+		j += scnprintf(buf + j, (4 * DEBUG_BUF_SIZE) - j,
+			       "%s\n", dbg_data.buf[i]);
+	}
+
+	read_unlock_irqrestore(&dbg_data.lck, flags);
+
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, j);
+
+	kfree(buf);
+
+	return ret;
+}
+
+const struct file_operations gdata_timestamp_ops = {
+	.read = show_timestamp,
+};
+
 static ssize_t ghsic_data_read_stats(struct file *file,
 	char __user *ubuf, size_t count, loff_t *ppos)
 {
@@ -881,7 +1009,8 @@
 };
 
 static struct dentry	*gdata_dent;
-static struct dentry	*gdata_dfile;
+static struct dentry	*gdata_dfile_stats;
+static struct dentry	*gdata_dfile_tstamp;
 
 static void ghsic_data_debugfs_init(void)
 {
@@ -889,21 +1018,37 @@
 	if (IS_ERR(gdata_dent))
 		return;
 
-	gdata_dfile = debugfs_create_file("status", 0444, gdata_dent, 0,
+	gdata_dfile_stats = debugfs_create_file("status", 0444, gdata_dent, 0,
 			&ghsic_stats_ops);
-	if (!gdata_dfile || IS_ERR(gdata_dfile))
+	if (!gdata_dfile_stats || IS_ERR(gdata_dfile_stats)) {
 		debugfs_remove(gdata_dent);
+		return;
+	}
+
+	gdata_dfile_tstamp = debugfs_create_file("timestamp", 0644, gdata_dent,
+				0, &gdata_timestamp_ops);
+		if (!gdata_dfile_tstamp || IS_ERR(gdata_dfile_tstamp))
+			debugfs_remove(gdata_dent);
 }
 
 static void ghsic_data_debugfs_exit(void)
 {
-	debugfs_remove(gdata_dfile);
+	debugfs_remove(gdata_dfile_stats);
+	debugfs_remove(gdata_dfile_tstamp);
 	debugfs_remove(gdata_dent);
 }
 
 #else
 static void ghsic_data_debugfs_init(void) { }
 static void ghsic_data_debugfs_exit(void) { }
+static void dbg_timestamp(char *event, struct sk_buff * skb)
+{
+	return;
+}
+static unsigned int get_timestamp(void)
+{
+	return 0;
+}
 
 #endif
 
diff --git a/drivers/usb/gadget/u_rmnet_ctrl_smd.c b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
index 90cbe54..8671669 100644
--- a/drivers/usb/gadget/u_rmnet_ctrl_smd.c
+++ b/drivers/usb/gadget/u_rmnet_ctrl_smd.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
@@ -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
@@ -59,7 +59,7 @@
 	struct grmnet		*port_usb;
 
 	spinlock_t		port_lock;
-	struct work_struct	connect_w;
+	struct delayed_work	connect_w;
 };
 
 static struct rmnet_ctrl_ports {
@@ -320,7 +320,7 @@
 static void grmnet_ctrl_smd_connect_w(struct work_struct *w)
 {
 	struct rmnet_ctrl_port *port =
-			container_of(w, struct rmnet_ctrl_port, connect_w);
+			container_of(w, struct rmnet_ctrl_port, connect_w.work);
 	struct smd_ch_info *c = &port->ctrl_ch;
 	unsigned long flags;
 	int ret;
@@ -332,8 +332,16 @@
 
 	ret = smd_open(c->name, &c->ch, port, grmnet_ctrl_smd_notify);
 	if (ret) {
-		pr_err("%s: Unable to open smd ch:%s err:%d\n",
-				__func__, c->name, ret);
+		if (ret == -EAGAIN) {
+			/* port not ready  - retry */
+			pr_debug("%s: SMD port not ready - rescheduling:%s err:%d\n",
+					__func__, c->name, ret);
+			queue_delayed_work(grmnet_ctrl_wq, &port->connect_w,
+				msecs_to_jiffies(250));
+		} else {
+			pr_err("%s: unable to open smd port:%s err:%d\n",
+					__func__, c->name, ret);
+		}
 		return;
 	}
 
@@ -370,7 +378,7 @@
 	gr->notify_modem = gsmd_ctrl_send_cbits_tomodem;
 	spin_unlock_irqrestore(&port->port_lock, flags);
 
-	queue_work(grmnet_ctrl_wq, &port->connect_w);
+	queue_delayed_work(grmnet_ctrl_wq, &port->connect_w, 0);
 
 	return 0;
 }
@@ -412,10 +420,13 @@
 
 	spin_unlock_irqrestore(&port->port_lock, flags);
 
-	if (test_bit(CH_OPENED, &c->flags)) {
-		/* this should send the dtr zero */
+	if (test_and_clear_bit(CH_OPENED, &c->flags))
+		/* send dtr zero */
+		smd_tiocmset(c->ch, c->cbits_tomodem, ~c->cbits_tomodem);
+
+	if (c->ch) {
 		smd_close(c->ch);
-		clear_bit(CH_OPENED, &c->flags);
+		c->ch = NULL;
 	}
 }
 
@@ -439,7 +450,8 @@
 			/* if usb is online, try opening smd_ch */
 			spin_lock_irqsave(&port->port_lock, flags);
 			if (port->port_usb)
-				queue_work(grmnet_ctrl_wq, &port->connect_w);
+				queue_delayed_work(grmnet_ctrl_wq,
+							&port->connect_w, 0);
 			spin_unlock_irqrestore(&port->port_lock, flags);
 
 			break;
@@ -464,7 +476,10 @@
 		if (!strncmp(c->name, pdev->name, SMD_CH_MAX_LEN)) {
 			clear_bit(CH_READY, &c->flags);
 			clear_bit(CH_OPENED, &c->flags);
-			smd_close(c->ch);
+			if (c->ch) {
+				smd_close(c->ch);
+				c->ch = NULL;
+			}
 			break;
 		}
 	}
@@ -497,7 +512,7 @@
 	port->port_num = portno;
 
 	spin_lock_init(&port->port_lock);
-	INIT_WORK(&port->connect_w, grmnet_ctrl_smd_connect_w);
+	INIT_DELAYED_WORK(&port->connect_w, grmnet_ctrl_smd_connect_w);
 
 	c = &port->ctrl_ch;
 	c->name = rmnet_ctrl_names[portno];
@@ -603,8 +618,8 @@
 				c->cbits_tomodem ? "HIGH" : "LOW",
 				test_bit(CH_OPENED, &c->flags),
 				test_bit(CH_READY, &c->flags),
-				smd_read_avail(c->ch),
-				smd_write_avail(c->ch));
+				c->ch ? smd_read_avail(c->ch) : 0,
+				c->ch ? smd_write_avail(c->ch) : 0);
 
 		spin_unlock_irqrestore(&port->port_lock, flags);
 	}
diff --git a/drivers/usb/gadget/u_smd.c b/drivers/usb/gadget/u_smd.c
index caccade..95adf5d 100644
--- a/drivers/usb/gadget/u_smd.c
+++ b/drivers/usb/gadget/u_smd.c
@@ -71,7 +71,7 @@
 	struct gserial		*port_usb;
 
 	struct smd_port_info	*pi;
-	struct work_struct	connect_work;
+	struct delayed_work	connect_work;
 
 	/* At present, smd does not notify
 	 * control bit change info from modem
@@ -562,7 +562,7 @@
 	struct smd_port_info *pi;
 	int ret;
 
-	port = container_of(w, struct gsmd_port, connect_work);
+	port = container_of(w, struct gsmd_port, connect_work.work);
 	pi = port->pi;
 
 	pr_debug("%s: port:%p port#%d\n", __func__, port, port->port_num);
@@ -573,9 +573,16 @@
 	ret = smd_named_open_on_edge(pi->name, SMD_APPS_MODEM,
 				&pi->ch, port, gsmd_notify);
 	if (ret) {
-		pr_err("%s: unable to open smd port:%s err:%d\n",
-				__func__, pi->name, ret);
-		return;
+		if (ret == -EAGAIN) {
+			/* port not ready  - retry */
+			pr_debug("%s: SMD port not ready - rescheduling:%s err:%d\n",
+					__func__, pi->name, ret);
+			queue_delayed_work(gsmd_wq, &port->connect_work,
+				msecs_to_jiffies(250));
+		} else {
+			pr_err("%s: unable to open smd port:%s err:%d\n",
+					__func__, pi->name, ret);
+		}
 	}
 }
 
@@ -672,7 +679,7 @@
 	}
 	gser->out->driver_data = port;
 
-	queue_work(gsmd_wq, &port->connect_work);
+	queue_delayed_work(gsmd_wq, &port->connect_work, msecs_to_jiffies(0));
 
 	return 0;
 }
@@ -711,17 +718,18 @@
 	port->n_read = 0;
 	spin_unlock_irqrestore(&port->port_lock, flags);
 
-	if (!test_bit(CH_OPENED, &port->pi->flags))
-		return;
+	if (test_and_clear_bit(CH_OPENED, &port->pi->flags)) {
+		/* lower the dtr */
+		port->cbits_to_modem = 0;
+		smd_tiocmset(port->pi->ch,
+				port->cbits_to_modem,
+				~port->cbits_to_modem);
+	}
 
-	/* lower the dtr */
-	port->cbits_to_modem = 0;
-	smd_tiocmset(port->pi->ch,
-			port->cbits_to_modem,
-			~port->cbits_to_modem);
-
-	smd_close(port->pi->ch);
-	clear_bit(CH_OPENED, &port->pi->flags);
+	if (port->pi->ch) {
+		smd_close(port->pi->ch);
+		port->pi->ch = NULL;
+	}
 }
 
 #define SMD_CH_MAX_LEN	20
@@ -742,7 +750,8 @@
 			set_bit(CH_READY, &pi->flags);
 			spin_lock_irqsave(&port->port_lock, flags);
 			if (port->port_usb)
-				queue_work(gsmd_wq, &port->connect_work);
+				queue_delayed_work(gsmd_wq, &port->connect_work,
+					msecs_to_jiffies(0));
 			spin_unlock_irqrestore(&port->port_lock, flags);
 			break;
 		}
@@ -765,7 +774,10 @@
 		if (!strncmp(pi->name, pdev->name, SMD_CH_MAX_LEN)) {
 			clear_bit(CH_READY, &pi->flags);
 			clear_bit(CH_OPENED, &pi->flags);
-			smd_close(pi->ch);
+			if (pi->ch) {
+				smd_close(pi->ch);
+				pi->ch = NULL;
+			}
 			break;
 		}
 	}
@@ -801,7 +813,7 @@
 	INIT_LIST_HEAD(&port->write_pool);
 	INIT_WORK(&port->pull, gsmd_tx_pull);
 
-	INIT_WORK(&port->connect_work, gsmd_connect_work);
+	INIT_DELAYED_WORK(&port->connect_work, gsmd_connect_work);
 
 	smd_ports[portno].port = port;
 	pdrv = &smd_ports[portno].pdrv;
@@ -821,6 +833,7 @@
 		size_t count, loff_t *ppos)
 {
 	struct gsmd_port *port;
+	struct smd_port_info *pi;
 	char *buf;
 	unsigned long flags;
 	int temp = 0;
@@ -833,6 +846,7 @@
 
 	for (i = 0; i < n_smd_ports; i++) {
 		port = smd_ports[i].port;
+		pi = port->pi;
 		spin_lock_irqsave(&port->port_lock, flags);
 		temp += scnprintf(buf + temp, 512 - temp,
 				"###PORT:%d###\n"
@@ -848,10 +862,10 @@
 				i, port->nbytes_tolaptop, port->nbytes_tomodem,
 				port->cbits_to_modem, port->cbits_to_laptop,
 				port->n_read,
-				smd_read_avail(port->pi->ch),
-				smd_write_avail(port->pi->ch),
-				test_bit(CH_OPENED, &port->pi->flags),
-				test_bit(CH_READY, &port->pi->flags));
+				pi->ch ? smd_read_avail(pi->ch) : 0,
+				pi->ch ? smd_write_avail(pi->ch) : 0,
+				test_bit(CH_OPENED, &pi->flags),
+				test_bit(CH_READY, &pi->flags));
 		spin_unlock_irqrestore(&port->port_lock, flags);
 	}
 
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index 66cdcb1..aab5b98 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/uaccess.h>
 #include <linux/usb.h>
+#include <linux/debugfs.h>
 #include <mach/diag_bridge.h>
 
 #define DRIVER_DESC	"USB host diag bridge driver"
@@ -35,6 +36,12 @@
 	struct kref		kref;
 	struct diag_bridge_ops	*ops;
 	struct platform_device	*pdev;
+
+	/* debugging counters */
+	unsigned long		bytes_to_host;
+	unsigned long		bytes_to_mdm;
+	unsigned		pending_reads;
+	unsigned		pending_writes;
 };
 struct diag_bridge *__dev;
 
@@ -84,6 +91,9 @@
 			urb->transfer_buffer,
 			urb->transfer_buffer_length,
 			urb->status < 0 ? urb->status : urb->actual_length);
+
+	dev->bytes_to_host += urb->actual_length;
+	dev->pending_reads--;
 }
 
 int diag_bridge_read(char *data, int size)
@@ -119,10 +129,12 @@
 	usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
 				diag_bridge_read_cb, dev);
 	usb_anchor_urb(urb, &dev->submitted);
+	dev->pending_reads++;
 
 	ret = usb_submit_urb(urb, GFP_ATOMIC);
 	if (ret) {
 		dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret);
+		dev->pending_reads--;
 		usb_unanchor_urb(urb);
 		usb_free_urb(urb);
 		return ret;
@@ -151,6 +163,9 @@
 			urb->transfer_buffer,
 			urb->transfer_buffer_length,
 			urb->status < 0 ? urb->status : urb->actual_length);
+
+	dev->bytes_to_mdm += urb->actual_length;
+	dev->pending_writes--;
 }
 
 int diag_bridge_write(char *data, int size)
@@ -186,10 +201,12 @@
 	usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
 				diag_bridge_write_cb, dev);
 	usb_anchor_urb(urb, &dev->submitted);
+	dev->pending_writes++;
 
 	ret = usb_submit_urb(urb, GFP_ATOMIC);
 	if (ret) {
-		err("submitting urb failed err:%d", ret);
+		dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret);
+		dev->pending_writes--;
 		usb_unanchor_urb(urb);
 		usb_free_urb(urb);
 		return ret;
@@ -211,6 +228,79 @@
 	kfree(dev);
 }
 
+#if defined(CONFIG_DEBUG_FS)
+#define DEBUG_BUF_SIZE	512
+static ssize_t diag_read_stats(struct file *file, char __user *ubuf,
+				size_t count, loff_t *ppos)
+{
+	struct diag_bridge	*dev = __dev;
+	char			*buf;
+	int			ret;
+
+	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = scnprintf(buf, DEBUG_BUF_SIZE,
+			"epin:%d, epout:%d\n"
+			"bytes to host: %lu\n"
+			"bytes to mdm: %lu\n"
+			"pending reads: %u\n"
+			"pending writes: %u\n"
+			"last error: %d\n",
+			dev->in_epAddr, dev->out_epAddr,
+			dev->bytes_to_host, dev->bytes_to_mdm,
+			dev->pending_reads, dev->pending_writes,
+			dev->err);
+
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t diag_reset_stats(struct file *file, const char __user *buf,
+				 size_t count, loff_t *ppos)
+{
+	struct diag_bridge	*dev = __dev;
+
+	dev->bytes_to_host = dev->bytes_to_mdm = 0;
+	dev->pending_reads = dev->pending_writes = 0;
+
+	return count;
+}
+
+const struct file_operations diag_stats_ops = {
+	.read = diag_read_stats,
+	.write = diag_reset_stats,
+};
+
+static struct dentry *dent;
+
+static void diag_bridge_debugfs_init(void)
+{
+	struct dentry *dfile;
+
+	dent = debugfs_create_dir("diag_bridge", 0);
+	if (IS_ERR(dent))
+		return;
+
+	dfile = debugfs_create_file("status", 0444, dent, 0, &diag_stats_ops);
+	if (!dfile || IS_ERR(dfile))
+		debugfs_remove(dent);
+}
+
+static void diag_bridge_debugfs_cleanup(void)
+{
+	if (dent) {
+		debugfs_remove_recursive(dent);
+		dent = NULL;
+	}
+}
+#else
+static inline void diag_bridge_debugfs_init(void) { }
+static inline void diag_bridge_debugfs_cleanup(void) { }
+#endif
+
 static int
 diag_bridge_probe(struct usb_interface *ifc, const struct usb_device_id *id)
 {
@@ -265,7 +355,7 @@
 	}
 
 	usb_set_intfdata(ifc, dev);
-
+	diag_bridge_debugfs_init();
 	platform_device_add(dev->pdev);
 
 	dev_dbg(&dev->udev->dev, "%s: complete\n", __func__);
@@ -286,6 +376,7 @@
 	dev_dbg(&dev->udev->dev, "%s:\n", __func__);
 
 	platform_device_del(dev->pdev);
+	diag_bridge_debugfs_cleanup();
 	kref_put(&dev->kref, diag_bridge_delete);
 	usb_set_intfdata(ifc, NULL);
 }
diff --git a/drivers/usb/misc/mdm_ctrl_bridge.c b/drivers/usb/misc/mdm_ctrl_bridge.c
index 11d388c..584503a 100644
--- a/drivers/usb/misc/mdm_ctrl_bridge.c
+++ b/drivers/usb/misc/mdm_ctrl_bridge.c
@@ -333,6 +333,7 @@
 
 static void ctrl_write_callback(struct urb *urb)
 {
+	struct ctrl_bridge	*dev = urb->context;
 
 	if (urb->status) {
 		pr_debug("Write status/size %d/%d\n",
@@ -342,6 +343,7 @@
 	kfree(urb->transfer_buffer);
 	kfree(urb->setup_packet);
 	usb_free_urb(urb);
+	usb_autopm_put_interface_async(dev->intf);
 }
 
 int ctrl_bridge_write(unsigned int id, char *data, size_t size)
@@ -406,7 +408,7 @@
 				 usb_sndctrlpipe(udev, 0),
 				 (unsigned char *)out_ctlreq,
 				 (void *)data, size,
-				 ctrl_write_callback, NULL);
+				 ctrl_write_callback, dev);
 
 	result = usb_autopm_get_interface_async(dev->intf);
 	if (result < 0) {
diff --git a/drivers/usb/misc/mdm_data_bridge.c b/drivers/usb/misc/mdm_data_bridge.c
index c3d5bb0..687c8c5 100644
--- a/drivers/usb/misc/mdm_data_bridge.c
+++ b/drivers/usb/misc/mdm_data_bridge.c
@@ -51,6 +51,9 @@
 unsigned int	stop_submit_urb_limit = STOP_SUBMIT_URB_LIMIT;
 module_param(stop_submit_urb_limit, uint, S_IRUGO | S_IWUSR);
 
+static unsigned tx_urb_mult = 20;
+module_param(tx_urb_mult, uint, S_IRUGO|S_IWUSR);
+
 #define TX_HALT   BIT(0)
 #define RX_HALT   BIT(1)
 #define SUSPENDED BIT(2)
@@ -60,6 +63,7 @@
 	struct usb_device		*udev;
 	unsigned int			bulk_in;
 	unsigned int			bulk_out;
+	int				err;
 
 	/* keep track of in-flight URBs */
 	struct usb_anchor		tx_active;
@@ -99,6 +103,8 @@
 /* counter used for indexing data bridge devices */
 static int	ch_id;
 
+static unsigned int get_timestamp(void);
+static void dbg_timestamp(char *, struct sk_buff *);
 static int submit_rx_urb(struct data_bridge *dev, struct urb *urb,
 		gfp_t flags);
 
@@ -136,6 +142,7 @@
 	unsigned long		flags;
 	struct urb		*rx_idle;
 	struct sk_buff		*skb;
+	struct timestamp_info	*info;
 	struct data_bridge	*dev =
 		container_of(work, struct data_bridge, process_rx_w);
 
@@ -146,6 +153,8 @@
 
 	while (!rx_throttled(brdg) && (skb = skb_dequeue(&dev->rx_done))) {
 		dev->to_host++;
+		info = (struct timestamp_info *)skb->cb;
+		info->rx_done_sent = get_timestamp();
 		/* hand off sk_buff to client,they'll need to free it */
 		retval = brdg->ops.send_pkt(brdg->ctx, skb, skb->len);
 		if (retval == -ENOTCONN || retval == -EINVAL) {
@@ -178,16 +187,17 @@
 {
 	struct bridge		*brdg;
 	struct sk_buff		*skb = urb->context;
-	struct data_bridge	*dev = *(struct data_bridge **)skb->cb;
+	struct timestamp_info	*info = (struct timestamp_info *)skb->cb;
+	struct data_bridge	*dev = info->dev;
 	bool			queue = 0;
 
 	brdg = dev->brdg;
-
 	skb_put(skb, urb->actual_length);
 
 	switch (urb->status) {
 	case 0: /* success */
 		queue = 1;
+		info->rx_done = get_timestamp();
 		spin_lock(&dev->rx_done.lock);
 		__skb_queue_tail(&dev->rx_done, skb);
 		spin_unlock(&dev->rx_done.lock);
@@ -227,14 +237,19 @@
 static int submit_rx_urb(struct data_bridge *dev, struct urb *rx_urb,
 	gfp_t flags)
 {
-	struct sk_buff	*skb;
-	int		retval = -EINVAL;
+	struct sk_buff		*skb;
+	struct timestamp_info	*info;
+	int			retval = -EINVAL;
+	unsigned int		created;
 
+	created = get_timestamp();
 	skb = alloc_skb(RMNET_RX_BUFSIZE, flags);
 	if (!skb)
 		return -ENOMEM;
 
-	*((struct data_bridge **)skb->cb) = dev;
+	info = (struct timestamp_info *)skb->cb;
+	info->dev = dev;
+	info->created = created;
 
 	usb_fill_bulk_urb(rx_urb, dev->udev, dev->bulk_in,
 			  skb->data, RMNET_RX_BUFSIZE,
@@ -244,6 +259,7 @@
 		goto suspended;
 
 	usb_anchor_urb(rx_urb, &dev->rx_active);
+	info->rx_queued = get_timestamp();
 	retval = usb_submit_urb(rx_urb, flags);
 	if (retval)
 		goto fail;
@@ -293,6 +309,7 @@
 	dev_dbg(&dev->udev->dev, "%s: dev:%p\n", __func__, dev);
 
 	dev->brdg = brdg;
+	dev->err = 0;
 	atomic_set(&dev->pending_txurbs, 0);
 	dev->to_host = 0;
 	dev->to_modem = 0;
@@ -390,7 +407,8 @@
 static void data_bridge_write_cb(struct urb *urb)
 {
 	struct sk_buff		*skb = urb->context;
-	struct data_bridge	*dev = *(struct data_bridge **)skb->cb;
+	struct timestamp_info	*info = (struct timestamp_info *)skb->cb;
+	struct data_bridge	*dev = info->dev;
 	struct bridge		*brdg = dev->brdg;
 	int			pending;
 
@@ -398,6 +416,10 @@
 
 	switch (urb->status) {
 	case 0: /*success*/
+		dbg_timestamp("UL", skb);
+		break;
+	case -EPROTO:
+		dev->err = -EPROTO;
 		break;
 	case -EPIPE:
 		set_bit(TX_HALT, &dev->flags);
@@ -438,10 +460,11 @@
 	int			size = skb->len;
 	int			pending;
 	struct urb		*txurb;
+	struct timestamp_info	*info = (struct timestamp_info *)skb->cb;
 	struct data_bridge	*dev = __dev[id];
 	struct bridge		*brdg;
 
-	if (!dev || !dev->brdg || !usb_get_intfdata(dev->intf))
+	if (!dev || !dev->brdg || dev->err || !usb_get_intfdata(dev->intf))
 		return -ENODEV;
 
 	brdg = dev->brdg;
@@ -465,7 +488,8 @@
 	}
 
 	/* store dev pointer in skb */
-	*((struct data_bridge **)skb->cb) = dev;
+	info->dev = dev;
+	info->tx_queued = get_timestamp();
 
 	usb_fill_bulk_urb(txurb, dev->udev, dev->bulk_out,
 			skb->data, skb->len, data_bridge_write_cb, skb);
@@ -478,6 +502,9 @@
 	pending = atomic_inc_return(&dev->pending_txurbs);
 	usb_anchor_urb(txurb, &dev->tx_active);
 
+	if (atomic_read(&dev->pending_txurbs) % tx_urb_mult)
+		txurb->transfer_flags |= URB_NO_INTERRUPT;
+
 	result = usb_submit_urb(txurb, GFP_KERNEL);
 	if (result < 0) {
 		usb_unanchor_urb(txurb);
@@ -646,6 +673,103 @@
 
 #if defined(CONFIG_DEBUG_FS)
 #define DEBUG_BUF_SIZE	1024
+
+static unsigned int	record_timestamp;
+module_param(record_timestamp, uint, S_IRUGO | S_IWUSR);
+
+static struct timestamp_buf dbg_data = {
+	.idx = 0,
+	.lck = __RW_LOCK_UNLOCKED(lck)
+};
+
+/*get_timestamp - returns time of day in us */
+static unsigned int get_timestamp(void)
+{
+	struct timeval	tval;
+	unsigned int	stamp;
+
+	if (!record_timestamp)
+		return 0;
+
+	do_gettimeofday(&tval);
+	/* 2^32 = 4294967296. Limit to 4096s. */
+	stamp = tval.tv_sec & 0xFFF;
+	stamp = stamp * 1000000 + tval.tv_usec;
+	return stamp;
+}
+
+static void dbg_inc(unsigned *idx)
+{
+	*idx = (*idx + 1) & (DBG_DATA_MAX-1);
+}
+
+/**
+* dbg_timestamp - Stores timestamp values of a SKB life cycle
+*	to debug buffer
+* @event: "UL": Uplink Data
+* @skb: SKB used to store timestamp values to debug buffer
+*/
+static void dbg_timestamp(char *event, struct sk_buff * skb)
+{
+	unsigned long		flags;
+	struct timestamp_info	*info = (struct timestamp_info *)skb->cb;
+
+	if (!record_timestamp)
+		return;
+
+	write_lock_irqsave(&dbg_data.lck, flags);
+
+	scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
+		  "%p %u[%s] %u %u %u %u %u %u\n",
+		  skb, skb->len, event, info->created, info->rx_queued,
+		  info->rx_done, info->rx_done_sent, info->tx_queued,
+		  get_timestamp());
+
+	dbg_inc(&dbg_data.idx);
+
+	write_unlock_irqrestore(&dbg_data.lck, flags);
+}
+
+/* show_timestamp: displays the timestamp buffer */
+static ssize_t show_timestamp(struct file *file, char __user *ubuf,
+		size_t count, loff_t *ppos)
+{
+	unsigned long	flags;
+	unsigned	i;
+	unsigned	j = 0;
+	char		*buf;
+	int		ret = 0;
+
+	if (!record_timestamp)
+		return 0;
+
+	buf = kzalloc(sizeof(char) * 4 * DEBUG_BUF_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	read_lock_irqsave(&dbg_data.lck, flags);
+
+	i = dbg_data.idx;
+	for (dbg_inc(&i); i != dbg_data.idx; dbg_inc(&i)) {
+		if (!strnlen(dbg_data.buf[i], DBG_DATA_MSG))
+			continue;
+		j += scnprintf(buf + j, (4 * DEBUG_BUF_SIZE) - j,
+			       "%s\n", dbg_data.buf[i]);
+	}
+
+	read_unlock_irqrestore(&dbg_data.lck, flags);
+
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, j);
+
+	kfree(buf);
+
+	return ret;
+}
+
+const struct file_operations data_timestamp_ops = {
+	.read = show_timestamp,
+};
+
 static ssize_t data_bridge_read_stats(struct file *file, char __user *ubuf,
 		size_t count, loff_t *ppos)
 {
@@ -675,6 +799,7 @@
 				"rx throttled cnt:   %u\n"
 				"rx unthrottled cnt: %u\n"
 				"rx done skb qlen:   %u\n"
+				"dev err:            %d\n"
 				"suspended:          %d\n"
 				"TX_HALT:            %d\n"
 				"RX_HALT:            %d\n",
@@ -688,6 +813,7 @@
 				dev->rx_throttled_cnt,
 				dev->rx_unthrottled_cnt,
 				dev->rx_done.qlen,
+				dev->err,
 				test_bit(SUSPENDED, &dev->flags),
 				test_bit(TX_HALT, &dev->flags),
 				test_bit(RX_HALT, &dev->flags));
@@ -728,29 +854,49 @@
 	.write = data_bridge_reset_stats,
 };
 
-struct dentry	*data_dent;
-struct dentry	*data_dfile;
+static struct dentry	*data_dent;
+static struct dentry	*data_dfile_stats;
+static struct dentry	*data_dfile_tstamp;
+
 static void data_bridge_debugfs_init(void)
 {
 	data_dent = debugfs_create_dir("data_hsic_bridge", 0);
 	if (IS_ERR(data_dent))
 		return;
 
-	data_dfile = debugfs_create_file("status", 0644, data_dent, 0,
-			&data_stats_ops);
-	if (!data_dfile || IS_ERR(data_dfile))
+	data_dfile_stats = debugfs_create_file("status", 0644, data_dent, 0,
+				&data_stats_ops);
+	if (!data_dfile_stats || IS_ERR(data_dfile_stats)) {
+		debugfs_remove(data_dent);
+		return;
+	}
+
+	data_dfile_tstamp = debugfs_create_file("timestamp", 0644, data_dent,
+				0, &data_timestamp_ops);
+	if (!data_dfile_tstamp || IS_ERR(data_dfile_tstamp))
 		debugfs_remove(data_dent);
 }
 
 static void data_bridge_debugfs_exit(void)
 {
-	debugfs_remove(data_dfile);
+	debugfs_remove(data_dfile_stats);
+	debugfs_remove(data_dfile_tstamp);
 	debugfs_remove(data_dent);
 }
 
 #else
 static void data_bridge_debugfs_init(void) { }
 static void data_bridge_debugfs_exit(void) { }
+static void dbg_timestamp(char *event, struct sk_buff * skb)
+{
+	return;
+}
+
+static unsigned int get_timestamp(void)
+{
+	return 0;
+}
+
 #endif
 
 static int __devinit
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index ec9ac24..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);
@@ -839,6 +835,33 @@
 }
 #endif
 
+static int msm_otg_notify_chg_type(struct msm_otg *motg)
+{
+	static int charger_type;
+	/*
+	 * TODO
+	 * Unify OTG driver charger types and power supply charger types
+	 */
+	if (charger_type == motg->chg_type)
+		return 0;
+
+	if (motg->chg_type == USB_SDP_CHARGER)
+		charger_type = POWER_SUPPLY_TYPE_USB;
+	else if (motg->chg_type == USB_CDP_CHARGER)
+		charger_type = POWER_SUPPLY_TYPE_USB_CDP;
+	else if (motg->chg_type == USB_DCP_CHARGER)
+		charger_type = POWER_SUPPLY_TYPE_USB_DCP;
+	else if ((motg->chg_type == USB_ACA_DOCK_CHARGER ||
+		motg->chg_type == USB_ACA_A_CHARGER ||
+		motg->chg_type == USB_ACA_B_CHARGER ||
+		motg->chg_type == USB_ACA_C_CHARGER))
+		charger_type = POWER_SUPPLY_TYPE_USB_ACA;
+	else
+		charger_type = POWER_SUPPLY_TYPE_BATTERY;
+
+	return pm8921_set_usb_power_supply_type(charger_type);
+}
+
 static int msm_otg_notify_power_supply(struct msm_otg *motg, unsigned mA)
 {
 	struct power_supply *psy;
@@ -877,6 +900,11 @@
 			mA > IDEV_ACA_CHG_LIMIT)
 		mA = IDEV_ACA_CHG_LIMIT;
 
+	if (msm_otg_notify_chg_type(motg))
+		dev_err(motg->otg.dev,
+			"Failed notifying %d charger type to PMIC\n",
+							motg->chg_type);
+
 	if (motg->cur_power == mA)
 		return;
 
@@ -998,7 +1026,9 @@
 		return;
 
 	if (motg->pdata->vbus_power) {
-		motg->pdata->vbus_power(on);
+		ret = motg->pdata->vbus_power(on);
+		if (!ret)
+			vbus_is_on = on;
 		return;
 	}
 
@@ -1592,14 +1622,15 @@
 {
 	struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
 	struct otg_transceiver *otg = &motg->otg;
-	bool is_dcd, tmout, vout, is_aca;
+	bool is_dcd = false, tmout, vout, is_aca;
 	unsigned long delay;
 
 	dev_dbg(otg->dev, "chg detection work\n");
 	switch (motg->chg_state) {
 	case USB_CHG_STATE_UNDEFINED:
 		msm_chg_block_on(motg);
-		msm_chg_enable_dcd(motg);
+		if (motg->pdata->enable_dcd)
+			msm_chg_enable_dcd(motg);
 		msm_chg_enable_aca_det(motg);
 		motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
 		motg->dcd_retries = 0;
@@ -1619,10 +1650,12 @@
 				break;
 			}
 		}
-		is_dcd = msm_chg_check_dcd(motg);
+		if (motg->pdata->enable_dcd)
+			is_dcd = msm_chg_check_dcd(motg);
 		tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
 		if (is_dcd || tmout) {
-			msm_chg_disable_dcd(motg);
+			if (motg->pdata->enable_dcd)
+				msm_chg_disable_dcd(motg);
 			msm_chg_enable_primary_det(motg);
 			delay = MSM_CHG_PRIMARY_DET_TIME;
 			motg->chg_state = USB_CHG_STATE_DCD_DONE;
@@ -1827,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;
@@ -2447,7 +2479,7 @@
 		goto free_regs;
 	}
 
-	motg->xo_handle = msm_xo_get(MSM_XO_TCXO_D0, "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__);
@@ -2455,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);
@@ -2585,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:
@@ -2653,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/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h
index c47b6ec..de8d490 100644
--- a/drivers/usb/serial/usb-wwan.h
+++ b/drivers/usb/serial/usb-wwan.h
@@ -31,10 +31,10 @@
 
 /* per port private data */
 
-#define N_IN_URB 4
-#define N_OUT_URB 4
-#define IN_BUFLEN 4096
-#define OUT_BUFLEN 4096
+#define N_IN_URB 5
+#define N_OUT_URB 5
+#define IN_BUFLEN 65536
+#define OUT_BUFLEN 65536
 
 struct usb_wwan_intf_private {
 	spinlock_t susp_lock;
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index fcf4b08..2a08101 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -410,6 +410,7 @@
 	tty->raw = 1;
 	tty->real_raw = 1;
 
+	set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);
 	dbg("%s", __func__);
 
 	/* Start reading from the IN endpoint */
@@ -552,7 +553,7 @@
 		init_usb_anchor(&portdata->delayed);
 
 		for (j = 0; j < N_IN_URB; j++) {
-			buffer = (u8 *) __get_free_page(GFP_KERNEL);
+			buffer = kmalloc(IN_BUFLEN, GFP_KERNEL);
 			if (!buffer)
 				goto bail_out_error;
 			portdata->in_buffer[j] = buffer;
@@ -581,8 +582,7 @@
 		kfree(portdata->out_buffer[j]);
 bail_out_error:
 	for (j = 0; j < N_IN_URB; j++)
-		if (portdata->in_buffer[j])
-			free_page((unsigned long)portdata->in_buffer[j]);
+		kfree(portdata->in_buffer[j]);
 	kfree(portdata);
 	return 1;
 }
@@ -628,8 +628,7 @@
 
 		for (j = 0; j < N_IN_URB; j++) {
 			usb_free_urb(portdata->in_urbs[j]);
-			free_page((unsigned long)
-				  portdata->in_buffer[j]);
+			kfree(portdata->in_buffer[j]);
 			portdata->in_urbs[j] = NULL;
 		}
 		for (j = 0; j < N_OUT_URB; j++) {
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index de6bf1a..c7759c4 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -93,6 +93,10 @@
 	bool
 	default n
 
+config FB_MSM_LVDS
+	bool
+	default n
+
 config FB_MSM_OVERLAY
 	depends on FB_MSM_MDP40 && ANDROID_PMEM
 	bool "MDP4 overlay support"
@@ -170,6 +174,10 @@
         select FB_MSM_MIPI_DSI
         default n
 
+config FB_MSM_MIPI_DSI_NT35510
+	bool
+	select FB_MSM_MIPI_DSI
+
 config FB_MSM_MIPI_DSI_TC358764_DSI2LVDS
 	bool
 	select FB_MSM_MIPI_DSI
@@ -247,6 +255,11 @@
 	select FB_MSM_LCDC_PANEL
 	default n
 
+config FB_MSM_LVDS_CHIMEI_WXGA
+	bool
+	select FB_MSM_LVDS
+	default n
+
 config FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT
 	bool
 	select FB_MSM_MIPI_DSI_TOSHIBA
@@ -277,6 +290,16 @@
 	select FB_MSM_MIPI_DSI_RENESAS
 	default n
 
+config FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT
+	bool
+	select FB_MSM_MIPI_DSI_NT35510
+	default n
+
+config FB_MSM_MIPI_NT35510_CMD_WVGA_PT
+	bool
+	select FB_MSM_MIPI_DSI_NT35510
+	default n
+
 config FB_MSM_MIPI_CHIMEI_WXGA
 	bool "LVDS Chimei WXGA Panel using Toshiba MIPI DSI-to-LVDS bridge."
 	select FB_MSM_MIPI_DSI_TC358764_DSI2LVDS
@@ -301,6 +324,13 @@
 	---help---
 	  Support for MDP4 OVERLAY0 write back mode
 
+
+config FB_MSM_OVERLAY1_WRITEBACK
+        depends on FB_MSM_OVERLAY
+        bool "MDP overlay1 write back mode enable"
+        ---help---
+          Support for MDP4 OVERLAY1 write back mode
+
 config FB_MSM_WRITEBACK_MSM_PANEL
 	depends on FB_MSM_OVERLAY
         bool "MDP overlay write back panel enable"
@@ -382,6 +412,12 @@
 	---help---
 	  Support for LCDC Samsung OLED PT (480x800) panel
 
+config FB_MSM_LVDS_CHIMEI_WXGA_PANEL
+        bool "LVDS Chimei WXGA Panel"
+        select FB_MSM_LVDS_CHIMEI_WXGA
+        ---help---
+          Support for LVDS Chimei WXGA(1366x768) panel
+
 config FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
 	depends on FB_MSM_LCDC_HW
 	bool "MDDI Panel Auto Detect + LCDC Prism WVGA"
@@ -406,6 +442,8 @@
 	select FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
 	select FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
 	select FB_MSM_MIPI_NOVATEK_CMD_QHD_PT
+	select FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT
+	select FB_MSM_MIPI_NT35510_CMD_WVGA_PT
 	select FB_MSM_MIPI_SIMULATOR_VIDEO
 	select FB_MSM_MIPI_CHIMEI_WXGA
 	---help---
@@ -441,6 +479,8 @@
 	select FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT
 	select FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
 	select FB_MSM_MIPI_NOVATEK_CMD_QHD_PT
+	select FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT
+	select FB_MSM_MIPI_NT35510_CMD_WVGA_PT
 	select FB_MSM_MIPI_SIMULATOR_VIDEO
 	---help---
 	  Support for LCDC + MIPI panel auto detect
@@ -507,6 +547,14 @@
 	bool "MIPI Truly Video WVGA PT Panel"
 	select FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
 
+config FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT_PANEL
+	bool "MIPI NT35510 Video WVGA PT Panel"
+	select FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT
+
+config FB_MSM_MIPI_NT35510_CMD_WVGA_PT_PANEL
+	bool "MIPI NT35510 Command WVGA PT Panel"
+	select FB_MSM_MIPI_NT35510_CMD_WVGA_PT
+
 config FB_MSM_MIPI_SIMULATOR_VIDEO_PANEL
 	bool "MIPI Simulator Video Panel"
 	select FB_MSM_MIPI_SIMULATOR_VIDEO
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index dc02da4..93205bc 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -56,6 +56,9 @@
 # LCDC
 obj-$(CONFIG_FB_MSM_LCDC) += lcdc.o
 
+# LVDS
+obj-$(CONFIG_FB_MSM_LVDS) += lvds.o
+
 # MDDI
 msm_mddi-objs := mddi.o mddihost.o mddihosti.o
 obj-$(CONFIG_FB_MSM_MDDI) += msm_mddi.o
@@ -73,6 +76,7 @@
 obj-$(CONFIG_FB_MSM_MIPI_DSI_NOVATEK) += mipi_novatek.o
 obj-$(CONFIG_FB_MSM_MIPI_DSI_RENESAS) += mipi_renesas.o
 obj-$(CONFIG_FB_MSM_MIPI_DSI_TRULY) += mipi_truly.o
+obj-$(CONFIG_FB_MSM_MIPI_DSI_NT35510) += mipi_NT35510.o
 obj-$(CONFIG_FB_MSM_MIPI_DSI_SIMULATOR) += mipi_simulator.o
 
 # MIPI Bridge
@@ -113,6 +117,7 @@
 obj-y += mipi_toshiba_video_wvga_pt.o mipi_toshiba_video_wsvga_pt.o
 obj-y += mipi_novatek_video_qhd_pt.o mipi_novatek_cmd_qhd_pt.o
 obj-y += mipi_renesas_video_fwvga_pt.o mipi_renesas_cmd_fwvga_pt.o
+obj-y += mipi_NT35510_video_wvga_pt.o mipi_NT35510_cmd_wvga_pt.o
 obj-y += mipi_chimei_wxga_pt.o
 obj-y += mipi_truly_video_wvga_pt.o
 else
@@ -122,7 +127,10 @@
 obj-$(CONFIG_FB_MSM_MIPI_NOVATEK_CMD_QHD_PT) += mipi_novatek_cmd_qhd_pt.o
 obj-$(CONFIG_FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT) += mipi_renesas_video_fwvga_pt.o
 obj-$(CONFIG_FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT) += mipi_renesas_cmd_fwvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT) += mipi_renesas_video_fwvga_pt.o
 obj-$(CONFIG_FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT) += mipi_truly_video_wvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_NT35510_CMD_WVGA_PT) += mipi_NT35510_cmd_wvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT) += mipi_NT35510_video_wvga_pt.o
 obj-$(CONFIG_FB_MSM_MIPI_SIMULATOR_VIDEO) += mipi_simulator_video.o
 obj-$(CONFIG_FB_MSM_MIPI_CHIMEI_WXGA) += mipi_chimei_wxga_pt.o
 endif
@@ -143,6 +151,7 @@
 obj-$(CONFIG_FB_MSM_LCDC_SAMSUNG_OLED_PT) += lcdc_samsung_oled_pt.o
 obj-$(CONFIG_FB_MSM_HDMI_ADV7520_PANEL) += adv7520.o
 obj-$(CONFIG_FB_MSM_LCDC_ST15_WXGA) += lcdc_st15.o
+obj-$(CONFIG_FB_MSM_LVDS_CHIMEI_WXGA) += lvds_chimei_wxga.o
 obj-$(CONFIG_FB_MSM_HDMI_MSM_PANEL) += hdmi_msm.o
 obj-$(CONFIG_FB_MSM_EXT_INTERFACE_COMMON) += external_common.o
 
diff --git a/drivers/video/msm/adv7520.c b/drivers/video/msm/adv7520.c
index 05de74e..b3b34bb 100644
--- a/drivers/video/msm/adv7520.c
+++ b/drivers/video/msm/adv7520.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010,2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -79,12 +79,15 @@
 	if (!external_common_state->uevent_kobj)
 		return;
 
-	if (online)
+	if (online) {
 		kobject_uevent(external_common_state->uevent_kobj,
 			KOBJ_ONLINE);
-	else
+		switch_set_state(&external_common_state->sdev, 1);
+	} else {
 		kobject_uevent(external_common_state->uevent_kobj,
 			KOBJ_OFFLINE);
+		switch_set_state(&external_common_state->sdev, 0);
+	}
 	DEV_INFO("adv7520_uevent: %d [suspend# %d]\n", online, suspend_count);
 }
 
@@ -871,6 +874,10 @@
 	} else
 		DEV_ERR("adv7520_probe: failed to add fb device\n");
 
+	external_common_state->sdev.name = "hdmi";
+	if (switch_dev_register(&external_common_state->sdev) < 0)
+		DEV_ERR("Hdmi switch registration failed\n");
+
 	return 0;
 
 probe_free:
@@ -887,6 +894,7 @@
 		DEV_ERR("%s: No HDMI Device\n", __func__);
 		return -ENODEV;
 	}
+	switch_dev_unregister(&external_common_state->sdev);
 	wake_lock_destroy(&wlock);
 	kfree(dd);
 	dd = NULL;
diff --git a/drivers/video/msm/external_common.h b/drivers/video/msm/external_common.h
index 2a243cd..c9ab88e 100644
--- a/drivers/video/msm/external_common.h
+++ b/drivers/video/msm/external_common.h
@@ -12,6 +12,7 @@
  */
 #ifndef __EXTERNAL_COMMON_H__
 #define __EXTERNAL_COMMON_H__
+#include <linux/switch.h>
 
 #ifdef DEBUG
 #ifndef DEV_DBG_PREFIX
@@ -202,6 +203,7 @@
 	struct kobject *uevent_kobj;
 	uint32 video_resolution;
 	struct device *dev;
+	struct switch_dev sdev;
 #ifdef CONFIG_FB_MSM_HDMI_3D
 	boolean format_3d;
 	void (*switch_3d)(boolean on);
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index fc6054f..56a6483 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -726,15 +726,6 @@
 		DEV_DBG("%s: ignored, probe failed\n", __func__);
 		return;
 	}
-#ifdef CONFIG_SUSPEND
-	mutex_lock(&hdmi_msm_state_mutex);
-	if (hdmi_msm_state->pm_suspended) {
-		mutex_unlock(&hdmi_msm_state_mutex);
-		DEV_WARN("%s: ignored, pm_suspended\n", __func__);
-		return;
-	}
-	mutex_unlock(&hdmi_msm_state_mutex);
-#endif
 
 	DEV_DBG("%s:Got interrupt\n", __func__);
 	/* HPD_INT_STATUS[0x0250] */
@@ -784,6 +775,9 @@
 		DEV_INFO("HDMI HPD: QDSP OFF\n");
 		kobject_uevent_env(external_common_state->uevent_kobj,
 				   KOBJ_CHANGE, envp);
+		switch_set_state(&external_common_state->sdev, 0);
+		DEV_INFO("Hdmi state switch to %d: %s\n",
+			external_common_state->sdev.state,  __func__);
 		if (hpd_state) {
 			hdmi_msm_read_edid();
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
@@ -802,12 +796,18 @@
 			DEV_INFO("HDMI HPD: sense : send HDCP_PASS\n");
 			kobject_uevent_env(external_common_state->uevent_kobj,
 				KOBJ_CHANGE, envp);
+			switch_set_state(&external_common_state->sdev, 1);
+			DEV_INFO("Hdmi state switch to %d: %s\n",
+				external_common_state->sdev.state, __func__);
 #endif
 		} else {
 			DEV_INFO("HDMI HPD: sense DISCONNECTED: send OFFLINE\n"
 				);
 			kobject_uevent(external_common_state->uevent_kobj,
 				KOBJ_OFFLINE);
+			switch_set_state(&external_common_state->sdev, 0);
+			DEV_INFO("Hdmi state switch to %d: %s\n",
+				external_common_state->sdev.state,  __func__);
 		}
 	}
 
@@ -839,15 +839,6 @@
 static void hdcp_deauthenticate(void);
 static void hdmi_msm_hdcp_reauth_work(struct work_struct *work)
 {
-#ifdef CONFIG_SUSPEND
-	mutex_lock(&hdmi_msm_state_mutex);
-	if (hdmi_msm_state->pm_suspended) {
-		mutex_unlock(&hdmi_msm_state_mutex);
-		DEV_WARN("HDCP: deauthenticating skipped, pm_suspended\n");
-		return;
-	}
-	mutex_unlock(&hdmi_msm_state_mutex);
-#endif
 
 	/* Don't process recursive actions */
 	mutex_lock(&hdmi_msm_state_mutex);
@@ -873,15 +864,6 @@
 
 static void hdmi_msm_hdcp_work(struct work_struct *work)
 {
-#ifdef CONFIG_SUSPEND
-	mutex_lock(&hdmi_msm_state_mutex);
-	if (hdmi_msm_state->pm_suspended) {
-		mutex_unlock(&hdmi_msm_state_mutex);
-		DEV_WARN("HDCP: Re-enable skipped, pm_suspended\n");
-		return;
-	}
-	mutex_unlock(&hdmi_msm_state_mutex);
-#endif
 
 	/* Only re-enable if cable still connected */
 	mutex_lock(&external_common_state_hpd_mutex);
@@ -917,15 +899,6 @@
 		DEV_DBG("ISR ignored, probe failed\n");
 		return IRQ_HANDLED;
 	}
-#ifdef CONFIG_SUSPEND
-	mutex_lock(&hdmi_msm_state_mutex);
-	if (hdmi_msm_state->pm_suspended) {
-		mutex_unlock(&hdmi_msm_state_mutex);
-		DEV_WARN("ISR ignored, pm_suspended\n");
-		return IRQ_HANDLED;
-	}
-	mutex_unlock(&hdmi_msm_state_mutex);
-#endif
 
 	/* Process HPD Interrupt */
 	/* HDMI_HPD_INT_STATUS[0x0250] */
@@ -1058,6 +1031,9 @@
 			DEV_INFO("HDMI HPD:QDSP OFF\n");
 			kobject_uevent_env(external_common_state->uevent_kobj,
 			KOBJ_CHANGE, envp);
+			switch_set_state(&external_common_state->sdev, 0);
+			DEV_INFO("Hdmi state switch to %d: %s\n",
+				external_common_state->sdev.state,  __func__);
 			mutex_lock(&hdcp_auth_state_mutex);
 			hdmi_msm_state->full_auth_done = FALSE;
 			mutex_unlock(&hdcp_auth_state_mutex);
@@ -2889,8 +2865,12 @@
 	uint32 found_repeater = 0x0;
 	char *envp[2];
 
-	if (!hdmi_msm_has_hdcp())
+	if (!hdmi_msm_has_hdcp()) {
+		switch_set_state(&external_common_state->sdev, 1);
+		DEV_INFO("Hdmi state switch to %d: %s\n",
+			external_common_state->sdev.state, __func__);
 		return;
+	}
 
 	mutex_lock(&hdmi_msm_state_mutex);
 	hdmi_msm_state->hdcp_activating = TRUE;
@@ -2961,6 +2941,9 @@
 		kobject_uevent_env(external_common_state->uevent_kobj,
 		    KOBJ_CHANGE, envp);
 	}
+	switch_set_state(&external_common_state->sdev, 1);
+	DEV_INFO("Hdmi state switch to %d: %s\n",
+		external_common_state->sdev.state, __func__);
 	return;
 
 error:
@@ -2980,6 +2963,9 @@
 			queue_work(hdmi_work_queue,
 			    &hdmi_msm_state->hdcp_reauth_work);
 	}
+	switch_set_state(&external_common_state->sdev, 0);
+	DEV_INFO("Hdmi state switch to %d: %s\n",
+		external_common_state->sdev.state, __func__);
 }
 #endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 
@@ -3956,7 +3942,6 @@
 	disable_irq(hdmi_msm_state->irq);
 
 	hdmi_msm_set_mode(FALSE);
-	HDMI_OUTP_ND(0x0308, 0x7F); /*0b01111111*/
 	hdmi_msm_state->hpd_initialized = FALSE;
 	hdmi_msm_state->pd->cec_power(0);
 	hdmi_msm_state->pd->enable_5v(0);
@@ -4035,15 +4020,6 @@
 
 	if (!hdmi_msm_state || !hdmi_msm_state->hdmi_app_clk || !MSM_HDMI_BASE)
 		return -ENODEV;
-#ifdef CONFIG_SUSPEND
-	mutex_lock(&hdmi_msm_state_mutex);
-	if (hdmi_msm_state->pm_suspended) {
-		mutex_unlock(&hdmi_msm_state_mutex);
-		DEV_WARN("%s: ignored, pm_suspended\n", __func__);
-		return -ENODEV;
-	}
-	mutex_unlock(&hdmi_msm_state_mutex);
-#endif
 
 	DEV_INFO("power: ON (%dx%d %d)\n", mfd->var_xres, mfd->var_yres,
 		mfd->var_pixclock);
@@ -4095,15 +4071,6 @@
 {
 	if (!hdmi_msm_state->hdmi_app_clk)
 		return -ENODEV;
-#ifdef CONFIG_SUSPEND
-	mutex_lock(&hdmi_msm_state_mutex);
-	if (hdmi_msm_state->pm_suspended) {
-		mutex_unlock(&hdmi_msm_state_mutex);
-		DEV_WARN("%s: ignored, pm_suspended\n", __func__);
-		return -ENODEV;
-	}
-	mutex_unlock(&hdmi_msm_state_mutex);
-#endif
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 	mutex_lock(&hdmi_msm_state_mutex);
@@ -4294,6 +4261,12 @@
 	}
 
 	queue_work(hdmi_work_queue, &hdmi_msm_state->hpd_read_work);
+
+	/* Initialize hdmi node and register with switch driver */
+	external_common_state->sdev.name = "hdmi";
+	if (switch_dev_register(&external_common_state->sdev) < 0)
+		DEV_ERR("Hdmi switch registration failed\n");
+
 	return 0;
 
 error:
@@ -4326,6 +4299,10 @@
 	DEV_INFO("HDMI device: remove\n");
 
 	DEV_INFO("HDMI HPD: OFF\n");
+
+	/* Unregister hdmi node from switch driver */
+	switch_dev_unregister(&external_common_state->sdev);
+
 	hdmi_msm_hpd_off();
 	free_irq(hdmi_msm_state->irq, NULL);
 
@@ -4361,79 +4338,21 @@
 	int rc = 0;
 
 	DEV_INFO("%s: %d\n", __func__, on);
-	if (on)
+	if (on) {
 		rc = hdmi_msm_hpd_on(true);
-	else
+	} else {
 		hdmi_msm_hpd_off();
+		/* Set HDMI switch node to 0 on HPD feature disable */
+		switch_set_state(&external_common_state->sdev, 0);
+	}
 
 	return rc;
 }
 
-
-#ifdef CONFIG_SUSPEND
-static int hdmi_msm_device_pm_suspend(struct device *dev)
-{
-	mutex_lock(&hdmi_msm_state_mutex);
-	if (hdmi_msm_state->pm_suspended) {
-		mutex_unlock(&hdmi_msm_state_mutex);
-		return 0;
-	}
-
-	DEV_DBG("pm_suspend\n");
-
-	del_timer(&hdmi_msm_state->hpd_state_timer);
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
-	del_timer(&hdmi_msm_state->hdcp_timer);
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
-
-	disable_irq(hdmi_msm_state->irq);
-	if (external_common_state->hpd_feature_on)
-		hdmi_msm_clk(0);
-
-	hdmi_msm_state->pm_suspended = TRUE;
-	mutex_unlock(&hdmi_msm_state_mutex);
-
-	hdmi_msm_powerdown_phy();
-	hdmi_msm_state->pd->enable_5v(0);
-	hdmi_msm_state->pd->core_power(0, 1);
-	return 0;
-}
-
-static int hdmi_msm_device_pm_resume(struct device *dev)
-{
-	mutex_lock(&hdmi_msm_state_mutex);
-	if (!hdmi_msm_state->pm_suspended) {
-		mutex_unlock(&hdmi_msm_state_mutex);
-		return 0;
-	}
-
-	DEV_DBG("pm_resume\n");
-
-	hdmi_msm_state->pd->core_power(1, 1);
-	hdmi_msm_state->pd->enable_5v(1);
-	if (external_common_state->hpd_feature_on)
-		hdmi_msm_clk(1);
-
-	hdmi_msm_state->pm_suspended = FALSE;
-	mutex_unlock(&hdmi_msm_state_mutex);
-	enable_irq(hdmi_msm_state->irq);
-	return 0;
-}
-#else
-#define hdmi_msm_device_pm_suspend	NULL
-#define hdmi_msm_device_pm_resume	NULL
-#endif
-
-static const struct dev_pm_ops hdmi_msm_device_pm_ops = {
-	.suspend = hdmi_msm_device_pm_suspend,
-	.resume = hdmi_msm_device_pm_resume,
-};
-
 static struct platform_driver this_driver = {
 	.probe = hdmi_msm_probe,
 	.remove = hdmi_msm_remove,
 	.driver.name = "hdmi_msm",
-	.driver.pm = &hdmi_msm_device_pm_ops,
 };
 
 static struct msm_fb_panel_data hdmi_msm_panel_data = {
diff --git a/drivers/video/msm/lvds.c b/drivers/video/msm/lvds.c
new file mode 100644
index 0000000..7ef437c
--- /dev/null
+++ b/drivers/video/msm/lvds.c
@@ -0,0 +1,235 @@
+/* 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/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <mach/clk.h>
+
+#include "msm_fb.h"
+
+static int lvds_probe(struct platform_device *pdev);
+static int lvds_remove(struct platform_device *pdev);
+
+static int lvds_off(struct platform_device *pdev);
+static int lvds_on(struct platform_device *pdev);
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static struct clk *lvds_clk;
+
+static struct platform_driver lvds_driver = {
+	.probe = lvds_probe,
+	.remove = lvds_remove,
+	.suspend = NULL,
+	.resume = NULL,
+	.shutdown = NULL,
+	.driver = {
+		   .name = "lvds",
+		   },
+};
+
+static struct lcdc_platform_data *lvds_pdata;
+
+static int lvds_off(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct msm_fb_data_type *mfd;
+
+	mfd = platform_get_drvdata(pdev);
+	ret = panel_next_off(pdev);
+
+	clk_disable(lvds_clk);
+
+	if (lvds_pdata && lvds_pdata->lcdc_power_save)
+		lvds_pdata->lcdc_power_save(0);
+
+	if (lvds_pdata && lvds_pdata->lcdc_gpio_config)
+		ret = lvds_pdata->lcdc_gpio_config(0);
+
+#ifdef CONFIG_MSM_BUS_SCALING
+	mdp_bus_scale_update_request(0);
+#endif
+
+	return ret;
+}
+
+static int lvds_on(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct msm_fb_data_type *mfd;
+	unsigned long panel_pixclock_freq = 0;
+	mfd = platform_get_drvdata(pdev);
+
+	if (lvds_pdata && lvds_pdata->lcdc_get_clk)
+		panel_pixclock_freq = lvds_pdata->lcdc_get_clk();
+
+	if (!panel_pixclock_freq)
+		panel_pixclock_freq = mfd->fbi->var.pixclock;
+#ifdef CONFIG_MSM_BUS_SCALING
+	mdp_bus_scale_update_request(2);
+#endif
+	mfd = platform_get_drvdata(pdev);
+
+	mfd->fbi->var.pixclock = clk_round_rate(lvds_clk,
+					mfd->fbi->var.pixclock);
+	ret = clk_set_rate(lvds_clk, mfd->fbi->var.pixclock);
+	if (ret) {
+		pr_err("%s: Can't set lvds clock to rate %u\n",
+			__func__, mfd->fbi->var.pixclock);
+		goto out;
+	}
+
+	clk_enable(lvds_clk);
+
+	if (lvds_pdata && lvds_pdata->lcdc_power_save)
+		lvds_pdata->lcdc_power_save(1);
+	if (lvds_pdata && lvds_pdata->lcdc_gpio_config)
+		ret = lvds_pdata->lcdc_gpio_config(1);
+
+	ret = panel_next_on(pdev);
+
+out:
+	return ret;
+}
+
+static int lvds_probe(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+	struct fb_info *fbi;
+	struct platform_device *mdp_dev = NULL;
+	struct msm_fb_panel_data *pdata = NULL;
+	int rc;
+
+	if (pdev->id == 0) {
+		lvds_pdata = pdev->dev.platform_data;
+		return 0;
+	}
+
+	mfd = platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+		return -ENOMEM;
+
+	mdp_dev = platform_device_alloc("mdp", pdev->id);
+	if (!mdp_dev)
+		return -ENOMEM;
+
+	/*
+	 * link to the latest pdev
+	 */
+	mfd->pdev = mdp_dev;
+	mfd->dest = DISPLAY_LCDC;
+
+	/*
+	 * alloc panel device data
+	 */
+	if (platform_device_add_data
+	    (mdp_dev, pdev->dev.platform_data,
+	     sizeof(struct msm_fb_panel_data))) {
+		pr_err("lvds_probe: platform_device_add_data failed!\n");
+		platform_device_put(mdp_dev);
+		return -ENOMEM;
+	}
+	/*
+	 * data chain
+	 */
+	pdata = (struct msm_fb_panel_data *)mdp_dev->dev.platform_data;
+	pdata->on = lvds_on;
+	pdata->off = lvds_off;
+	pdata->next = pdev;
+
+	/*
+	 * get/set panel specific fb info
+	 */
+	mfd->panel_info = pdata->panel_info;
+
+	if (mfd->index == 0)
+		mfd->fb_imgType = MSMFB_DEFAULT_TYPE;
+	else
+		mfd->fb_imgType = MDP_RGB_565;
+
+	fbi = mfd->fbi;
+	fbi->var.pixclock = clk_round_rate(lvds_clk,
+					mfd->panel_info.clk_rate);
+	fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch;
+	fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch;
+	fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch;
+	fbi->var.lower_margin = mfd->panel_info.lcdc.v_front_porch;
+	fbi->var.hsync_len = mfd->panel_info.lcdc.h_pulse_width;
+	fbi->var.vsync_len = mfd->panel_info.lcdc.v_pulse_width;
+
+	/*
+	 * set driver data
+	 */
+	platform_set_drvdata(mdp_dev, mfd);
+	/*
+	 * register in mdp driver
+	 */
+	rc = platform_device_add(mdp_dev);
+	if (rc)
+		goto lvds_probe_err;
+
+	pdev_list[pdev_list_cnt++] = pdev;
+
+	return 0;
+
+lvds_probe_err:
+	platform_device_put(mdp_dev);
+	return rc;
+}
+
+static int lvds_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int lvds_register_driver(void)
+{
+	return platform_driver_register(&lvds_driver);
+}
+
+static int __init lvds_driver_init(void)
+{
+	lvds_clk = clk_get(NULL, "lvds_clk");
+	if (IS_ERR(lvds_clk)) {
+		pr_err("Couldnt find lvds_clk\n");
+		return -EINVAL;
+	}
+
+	return lvds_register_driver();
+}
+
+module_init(lvds_driver_init);
diff --git a/drivers/video/msm/lvds_chimei_wxga.c b/drivers/video/msm/lvds_chimei_wxga.c
new file mode 100644
index 0000000..2c6b6d4
--- /dev/null
+++ b/drivers/video/msm/lvds_chimei_wxga.c
@@ -0,0 +1,124 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm_fb.h"
+
+static struct msm_panel_common_pdata *cm_pdata;
+static struct platform_device *cm_fbpdev;
+
+static int lvds_chimei_panel_on(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int lvds_chimei_panel_off(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static void lvds_chimei_set_backlight(struct msm_fb_data_type *mfd)
+{
+}
+
+static int __devinit lvds_chimei_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+
+	if (pdev->id == 0) {
+		cm_pdata = pdev->dev.platform_data;
+		if (cm_pdata == NULL)
+			pr_err("%s: no PWM gpio specified\n", __func__);
+		return 0;
+	}
+
+	cm_fbpdev = msm_fb_add_device(pdev);
+	if (!cm_fbpdev) {
+		dev_err(&pdev->dev, "failed to add msm_fb device\n");
+		rc = -ENODEV;
+		goto probe_exit;
+	}
+
+probe_exit:
+	return rc;
+}
+
+static struct platform_driver this_driver = {
+	.probe  = lvds_chimei_probe,
+	.driver = {
+		.name   = "lvds_chimei_wxga",
+	},
+};
+
+static struct msm_fb_panel_data lvds_chimei_panel_data = {
+	.on = lvds_chimei_panel_on,
+	.off = lvds_chimei_panel_off,
+	.set_backlight = lvds_chimei_set_backlight,
+};
+
+static struct platform_device this_device = {
+	.name   = "lvds_chimei_wxga",
+	.id	= 1,
+	.dev	= {
+		.platform_data = &lvds_chimei_panel_data,
+	}
+};
+
+static int __init lvds_chimei_wxga_init(void)
+{
+	int ret;
+	struct msm_panel_info *pinfo;
+
+	if (msm_fb_detect_client("lvds_chimei_wxga"))
+		return 0;
+
+	ret = platform_driver_register(&this_driver);
+	if (ret)
+		return ret;
+
+	pinfo = &lvds_chimei_panel_data.panel_info;
+	pinfo->xres = 320;
+	pinfo->yres = 240;
+	MSM_FB_SINGLE_MODE_PANEL(pinfo);
+	pinfo->type = LVDS_PANEL;
+	pinfo->pdest = DISPLAY_1;
+	pinfo->wait_cycle = 0;
+	pinfo->bpp = 24;
+	pinfo->fb_num = 2;
+	pinfo->clk_rate = 75000000;
+	pinfo->bl_max = 15;
+	pinfo->bl_min = 1;
+
+	/*
+	 * this panel is operated by de,
+	 * vsycn and hsync are ignored
+	 */
+	pinfo->lcdc.h_back_porch = 0;
+	pinfo->lcdc.h_front_porch = 194;
+	pinfo->lcdc.h_pulse_width = 40;
+	pinfo->lcdc.v_back_porch = 0;
+	pinfo->lcdc.v_front_porch = 38;
+	pinfo->lcdc.v_pulse_width = 20;
+	pinfo->lcdc.border_clr = 0xffff00;
+	pinfo->lcdc.underflow_clr = 0xff;
+	pinfo->lcdc.hsync_skew = 0;
+	pinfo->lvds.channel_mode = LVDS_SINGLE_CHANNEL_MODE;
+	pinfo->lcdc.xres_pad = 1046;
+	pinfo->lcdc.yres_pad = 528;
+
+	ret = platform_device_register(&this_device);
+	if (ret)
+		platform_driver_unregister(&this_driver);
+
+	return ret;
+}
+
+module_init(lvds_chimei_wxga_init);
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index db60546..5e46397 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -49,7 +49,7 @@
 static struct clk *mdp_pclk;
 static struct clk *mdp_lut_clk;
 int mdp_rev;
-static boolean mdp_hist_force_stop = FALSE;
+
 static struct regulator *footswitch;
 static unsigned int mdp_footswitch_on;
 
@@ -338,6 +338,8 @@
 {
 	unsigned long flag;
 	int ret = 0;
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
 	mutex_lock(&mdp_hist_mutex);
 	if (!mdp_is_hist_start) {
 		printk(KERN_ERR "%s histogram already stopped\n", __func__);
@@ -349,6 +351,14 @@
 	mdp_is_hist_start = FALSE;
 	spin_unlock_irqrestore(&mdp_spin_lock, flag);
 
+	if (!mfd->panel_power_on) {
+
+		mdp_is_hist_data = FALSE;
+		complete(&mdp_hist_comp);
+		ret = -EINVAL;
+		goto mdp_hist_stop_err;
+	}
+
 	ret = _mdp_histogram_ctrl(FALSE);
 
 mdp_hist_stop_err:
@@ -429,11 +439,6 @@
 		goto error;
 	}
 
-	if (mdp_hist_force_stop && (mdp_rev == MDP_REV_303)) {
-		ret = -EINVAL;
-		goto error;
-	}
-
 	if (!mdp_is_hist_start) {
 		printk(KERN_ERR "%s histogram not started\n", __func__);
 		ret = -EPERM;
@@ -444,17 +449,14 @@
 	mdp_hist_frame_cnt = hist->frame_cnt;
 	mutex_unlock(&mdp_hist_mutex);
 
-	wait_for_completion_killable(&mdp_hist_comp);
+	if (wait_for_completion_killable(&mdp_hist_comp)) {
+		pr_err("%s(): histogram bin collection killed", __func__);
+		return -EINVAL;
+	}
 
 	mutex_lock(&mdp_hist_mutex);
-	if (mdp_is_hist_data) {
-		if (mdp_hist_force_stop && (mdp_rev == MDP_REV_303)) {
-			pr_debug("%s histogram stopped\n", __func__);
-			ret = -EINVAL;
-			goto error;
-		}
+	if (mdp_is_hist_data)
 		ret =  _mdp_copy_hist_data(hist);
-	}
 error:
 	mutex_unlock(&mdp_hist_mutex);
 	return ret;
@@ -740,12 +742,6 @@
 		if ((mdp_all_blocks_off) && (mdp_current_clk_on)) {
 			mutex_lock(&mdp_suspend_mutex);
 			if (block == MDP_MASTER_BLOCK || mdp_suspended) {
-				if ((mdp_prim_panel_type == MIPI_CMD_PANEL) &&
-					(mdp_rev == MDP_REV_303)) {
-					mdp_hist_force_stop = TRUE;
-					complete(&mdp_hist_comp);
-				}
-
 				mdp_current_clk_on = FALSE;
 				mb();
 				/* turn off MDP clks */
@@ -920,7 +916,6 @@
 				dma->busy = FALSE;
 				mdp_pipe_ctrl(MDP_DMA2_BLOCK,
 					MDP_BLOCK_POWER_OFF, TRUE);
-				mdp_hist_force_stop = FALSE;
 				complete(&dma->comp);
 			}
 #endif
@@ -1088,12 +1083,12 @@
 static int mdp_off(struct platform_device *pdev)
 {
 	int ret = 0;
+
 	mdp_histogram_ctrl(FALSE);
 
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	ret = panel_next_off(pdev);
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
 	return ret;
 }
 
@@ -1103,9 +1098,12 @@
 
 #ifdef CONFIG_FB_MSM_MDP40
 	struct msm_fb_data_type *mfd;
+	mdp4_overlay_ctrl_db_reset();
+
+	mfd = platform_get_drvdata(pdev);
+
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	if (is_mdp4_hw_reset()) {
-		mfd = platform_get_drvdata(pdev);
 		mdp_vsync_cfg_regs(mfd, FALSE);
 		mdp4_hw_init();
 		outpdw(MDP_BASE + 0x0038, mdp4_display_intf);
@@ -1117,6 +1115,14 @@
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	ret = panel_next_on(pdev);
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+#ifdef CONFIG_FB_MSM_MDP40
+	if (mfd->panel.type == MIPI_CMD_PANEL)
+		mdp4_dsi_cmd_overlay_restore();
+	else if (mfd->panel.type == MDDI_PANEL)
+		mdp4_mddi_overlay_restore();
+#endif
+
 	return ret;
 }
 
@@ -1331,10 +1337,9 @@
 	struct msm_fb_panel_data *pdata = NULL;
 	int rc;
 	resource_size_t  size ;
+	unsigned long flag;
 #ifdef CONFIG_FB_MSM_MDP40
 	int intf, if_no;
-#else
-	unsigned long flag;
 #endif
 #if defined(CONFIG_FB_MSM_MIPI_DSI) && defined(CONFIG_FB_MSM_MDP40)
 	struct mipi_panel_info *mipi;
@@ -1479,6 +1484,17 @@
 			mfd->vsync_gpio = -1;
 
 #ifdef CONFIG_FB_MSM_MDP40
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+		spin_lock_irqsave(&mdp_spin_lock, flag);
+		mdp_intr_mask |= INTR_OVERLAY0_DONE;
+		if (mdp_hw_revision < MDP4_REVISION_V2_1) {
+			/* dmas dmap switch */
+			mdp_intr_mask |= INTR_DMA_S_DONE;
+		}
+		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+		spin_unlock_irqrestore(&mdp_spin_lock, flag);
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
 		if (mfd->panel.type == EBI2_PANEL)
 			intf = EBI2_INTF;
 		else
@@ -1535,10 +1551,8 @@
 	case MIPI_CMD_PANEL:
 #ifndef CONFIG_FB_MSM_MDP303
 		mfd->dma_fnc = mdp4_dsi_cmd_overlay;
-#ifdef CONFIG_FB_MSM_MDP40
 		mipi = &mfd->panel_info.mipi;
 		configure_mdp_core_clk_table((mipi->dsi_pclk_rate) * 3 / 2);
-#endif
 		if (mfd->panel_info.pdest == DISPLAY_1) {
 			if_no = PRIMARY_INTF_SEL;
 			mfd->dma = &dma2_data;
@@ -1549,6 +1563,13 @@
 		mfd->lut_update = mdp_lut_update_nonlcdc;
 		mfd->do_histogram = mdp_do_histogram;
 		mdp4_display_intf_sel(if_no, DSI_CMD_INTF);
+
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+		spin_lock_irqsave(&mdp_spin_lock, flag);
+		mdp_intr_mask |= INTR_OVERLAY0_DONE;
+		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+		spin_unlock_irqrestore(&mdp_spin_lock, flag);
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 #else
 		mfd->dma_fnc = mdp_dma2_update;
 		mfd->do_histogram = mdp_do_histogram;
@@ -1577,6 +1598,7 @@
 #endif
 	case HDMI_PANEL:
 	case LCDC_PANEL:
+	case LVDS_PANEL:
 		pdata->on = mdp_lcdc_on;
 		pdata->off = mdp_lcdc_off;
 		mfd->hw_refresh = TRUE;
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index 7b67905..35a1453 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -42,6 +42,7 @@
 extern ulong mdp4_display_intf;
 extern spinlock_t mdp_spin_lock;
 extern int mdp_rev;
+extern struct mdp_csc_cfg mdp_csc_convert[4];
 
 #define MDP4_REVISION_V1		0
 #define MDP4_REVISION_V2		1
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 1a4ce91..7b2b2c2 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -130,18 +130,17 @@
 #define INTR_OVERLAY2_DONE		BIT(30)
 
 #ifdef CONFIG_FB_MSM_OVERLAY
-#define MDP4_ANY_INTR_MASK	(INTR_OVERLAY0_DONE|INTR_DMA_S_DONE | \
-					INTR_DMA_P_HISTOGRAM)
+#define MDP4_ANY_INTR_MASK	(INTR_DMA_P_HISTOGRAM)
 #else
 #define MDP4_ANY_INTR_MASK	(INTR_DMA_P_DONE| \
 				INTR_DMA_P_HISTOGRAM)
 #endif
 
 enum {
-	OVERLAY_PIPE_RGB1,
-	OVERLAY_PIPE_RGB2,
 	OVERLAY_PIPE_VG1,	/* video/graphic */
 	OVERLAY_PIPE_VG2,
+	OVERLAY_PIPE_RGB1,
+	OVERLAY_PIPE_RGB2,
 	OVERLAY_PIPE_RGB3,
 	OVERLAY_PIPE_VG3,
 	OVERLAY_PIPE_VG4,
@@ -320,6 +319,7 @@
 	uint32 blt_cnt;
 	uint32 ov_cnt;
 	uint32 dmap_cnt;
+	uint32 dmae_cnt;
 	uint32 blt_end;
 	uint32 luma_align_size;
 	struct mdp4_hsic_regs hsic_regs;
@@ -409,8 +409,6 @@
 uint32 mdp4_overlay_op_mode(struct mdp4_overlay_pipe *pipe);
 void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd);
 #ifdef CONFIG_FB_MSM_DTV
-void mdp4_overlay_dtv_vsync_push(struct msm_fb_data_type *mfd,
-			struct mdp4_overlay_pipe *pipe);
 void mdp4_overlay_dtv_ov_done_push(struct msm_fb_data_type *mfd,
 			struct mdp4_overlay_pipe *pipe);
 void mdp4_overlay_dtv_wait_for_ov(struct msm_fb_data_type *mfd,
@@ -420,11 +418,6 @@
 int mdp4_overlay_dtv_unset(struct msm_fb_data_type *mfd,
 			struct mdp4_overlay_pipe *pipe);
 #else
-static inline void mdp4_overlay_dtv_vsync_push(struct msm_fb_data_type *mfd,
-	struct mdp4_overlay_pipe *pipe)
-{
-	/* empty */
-}
 static inline void  mdp4_overlay_dtv_ov_done_push(struct msm_fb_data_type *mfd,
 			struct mdp4_overlay_pipe *pipe)
 {
@@ -520,7 +513,6 @@
 void mdp4_overlay1_done_atv(void);
 void mdp4_primary_vsync_lcdc(void);
 void mdp4_external_vsync_dtv(void);
-void mdp4_mddi_overlay_restore(void);
 void mdp4_overlay_lcdc_wait4vsync(struct msm_fb_data_type *mfd);
 void mdp4_overlay_lcdc_vsync_push(struct msm_fb_data_type *mfd,
 				struct mdp4_overlay_pipe *pipe);
@@ -530,11 +522,16 @@
 
 #ifndef CONFIG_FB_MSM_MIPI_DSI
 void mdp4_mddi_dma_busy_wait(struct msm_fb_data_type *mfd);
+void mdp4_mddi_overlay_restore(void);
 #else
 static inline void mdp4_mddi_dma_busy_wait(struct msm_fb_data_type *mfd)
 {
 	/* empty */
 }
+static inline void mdp4_mddi_overlay_restore(void)
+{
+	/* empty */
+}
 #endif
 
 void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
@@ -612,6 +609,8 @@
 					struct msmfb_overlay_blt *req);
 void mdp4_lcdc_overlay_blt_start(struct msm_fb_data_type *mfd);
 void mdp4_lcdc_overlay_blt_stop(struct msm_fb_data_type *mfd);
+void mdp4_dtv_overlay_blt_start(struct msm_fb_data_type *mfd);
+void mdp4_dtv_overlay_blt_stop(struct msm_fb_data_type *mfd);
 
 int mdp4_mddi_overlay_blt_offset(int *off);
 void mdp4_mddi_overlay_blt(ulong addr);
@@ -634,6 +633,7 @@
 void mdp4_dsi_blt_dmap_busy_wait(struct msm_fb_data_type *mfd);
 void mdp4_overlay_dsi_video_vsync_push(struct msm_fb_data_type *mfd,
 				struct mdp4_overlay_pipe *pipe);
+void mdp4_dsi_cmd_overlay_restore(void);
 #else
 static inline void mdp4_dsi_cmd_dma_busy_wait(struct msm_fb_data_type *mfd)
 {
@@ -648,6 +648,10 @@
 {
 	/* empty */
 }
+static inline void mdp4_dsi_cmd_overlay_restore(void)
+{
+	/* empty */
+}
 #endif /* MIPI_DSI */
 
 void mdp4_dsi_cmd_kickoff_ui(struct msm_fb_data_type *mfd,
@@ -656,7 +660,6 @@
 				struct mdp4_overlay_pipe *pipe);
 void mdp4_dsi_cmd_overlay_kickoff(struct msm_fb_data_type *mfd,
 				struct mdp4_overlay_pipe *pipe);
-void mdp4_dsi_cmd_overlay_restore(void);
 
 void mdp4_overlay_panel_3d(int mixer_num, uint32 panel_3d);
 int mdp4_overlay_3d_sbys(struct fb_info *info, struct msmfb_overlay_3d *req);
@@ -679,6 +682,7 @@
 uint32_t mdp4_ss_table_value(int8_t param, int8_t index);
 void mdp4_overlay_status_write(enum mdp4_overlay_status type, bool val);
 bool mdp4_overlay_status_read(enum mdp4_overlay_status type);
+void mdp4_overlay_ctrl_db_reset(void);
 
 int mdp4_overlay_writeback_on(struct platform_device *pdev);
 int mdp4_overlay_writeback_off(struct platform_device *pdev);
@@ -687,6 +691,7 @@
 		struct mdp4_overlay_pipe *pipe);
 void mdp4_writeback_dma_busy_wait(struct msm_fb_data_type *mfd);
 void mdp4_overlay1_done_writeback(struct mdp_dma_data *dma);
+void mdp4_dma_e_done_dtv(void);
 
 int mdp4_writeback_start(struct fb_info *info);
 int mdp4_writeback_stop(struct fb_info *info);
@@ -701,6 +706,8 @@
 void mdp4_hsic_set(struct mdp4_overlay_pipe *pipe, struct dpp_ctrl *ctrl);
 void mdp4_hsic_update(struct mdp4_overlay_pipe *pipe);
 int mdp4_csc_config(struct mdp_csc_cfg_data *config);
+void mdp4_csc_write(struct mdp_csc_cfg *data, uint32_t base);
+int mdp4_csc_enable(struct mdp_csc_cfg_data *config);
 
 u32  mdp4_allocate_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
 void mdp4_init_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index ecb0a24..bf53c73 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -43,6 +43,7 @@
 struct mdp4_overlay_ctrl {
 	struct mdp4_overlay_pipe plist[OVERLAY_PIPE_MAX];
 	struct mdp4_overlay_pipe *stage[MDP4_MIXER_MAX][MDP4_MIXER_STAGE_MAX];
+	uint32 mixer_cfg[MDP4_MIXER_MAX];
 	uint32 cs_controller;
 	uint32 panel_3d;
 	uint32 panel_mode;
@@ -109,6 +110,14 @@
 	return overlay_status[type];
 }
 
+void mdp4_overlay_ctrl_db_reset(void)
+{
+	int i;
+
+	for (i = MDP4_MIXER0; i < MDP4_MIXER_MAX; i++)
+		ctrl->mixer_cfg[i] = 0;
+}
+
 int mdp4_overlay_mixer_play(int mixer_num)
 {
 	if (mixer_num == MDP4_MIXER2)
@@ -239,13 +248,27 @@
 
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 
-	/* dma_p source */
 	MDP_OUTP(MDP_BASE + 0xb0004,
 			(pipe->src_height << 16 | pipe->src_width));
-	MDP_OUTP(MDP_BASE + 0xb0008, pipe->srcp0_addr);
-	MDP_OUTP(MDP_BASE + 0xb000c, pipe->srcp0_ystride);
-
-	/* dma_p dest */
+	if (pipe->blt_addr) {
+		uint32 off, bpp;
+#ifdef BLT_RGB565
+		bpp = 2; /* overlay ouput is RGB565 */
+#else
+		bpp = 3; /* overlay ouput is RGB888 */
+#endif
+		off = 0;
+		if (pipe->ov_cnt & 0x01)
+			off = pipe->src_height * pipe->src_width * bpp;
+		MDP_OUTP(MDP_BASE + 0xb0008, pipe->blt_addr + off);
+		/* RGB888, output of overlay blending */
+		MDP_OUTP(MDP_BASE + 0xb000c, pipe->src_width * bpp);
+	} else {
+		/* dma_e source */
+		MDP_OUTP(MDP_BASE + 0xb0008, pipe->srcp0_addr);
+		MDP_OUTP(MDP_BASE + 0xb000c, pipe->srcp0_ystride);
+	}
+	/* dma_e dest */
 	MDP_OUTP(MDP_BASE + 0xb0010, (pipe->dst_y << 16 | pipe->dst_x));
 
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
@@ -373,7 +396,7 @@
 			return;
 		pipe->op_mode |= MDP4_OP_SCALEY_EN;
 
-		if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {
+		if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
 			if (pipe->alpha_enable && pipe->dst_h > pipe->src_h)
 				pipe->op_mode |= MDP4_OP_SCALEY_PIXEL_RPT;
 			else if (pipe->dst_h <= (pipe->src_h / 4))
@@ -395,7 +418,7 @@
 			return;
 		pipe->op_mode |= MDP4_OP_SCALEX_EN;
 
-		if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {
+		if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
 			if (pipe->alpha_enable && pipe->dst_w > pipe->src_w)
 				pipe->op_mode |= MDP4_OP_SCALEX_PIXEL_RPT;
 			else if (pipe->dst_w <= (pipe->src_w / 4))
@@ -419,9 +442,11 @@
 	uint32 src_size, src_xy, dst_size, dst_xy;
 	uint32 format, pattern;
 	uint32 offset = 0;
+	int pnum;
 
+	pnum = pipe->pipe_num - OVERLAY_PIPE_RGB1; /* start from 0 */
 	rgb_base = MDP_BASE + MDP4_RGB_BASE;
-	rgb_base += (MDP4_RGB_OFF * pipe->pipe_num);
+	rgb_base += (MDP4_RGB_OFF * pnum);
 
 	src_size = ((pipe->src_h << 16) | pipe->src_w);
 	src_xy = ((pipe->src_y << 16) | pipe->src_x);
@@ -532,7 +557,7 @@
 	char *vg_base;
 	uint32 frame_size, src_size, src_xy, dst_size, dst_xy;
 	uint32 format, pattern, luma_offset, chroma_offset;
-	uint32 mask;
+	uint32 mask, curr;
 	int pnum, ptype;
 
 	pnum = pipe->pipe_num - OVERLAY_PIPE_VG1; /* start from 0 */
@@ -550,8 +575,9 @@
 	pattern = mdp4_overlay_unpack_pattern(pipe);
 
 	/* not RGB use VG pipe, pure VG pipe */
+	pipe->op_mode |= MDP4_OP_CSC_EN;
 	if (ptype != OVERLAY_TYPE_RGB)
-		pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR);
+		pipe->op_mode |= MDP4_OP_SRC_DATA_YCBCR;
 
 #ifdef MDP4_IGC_LUT_ENABLE
 	pipe->op_mode |= MDP4_OP_IGC_LUT_EN;
@@ -595,6 +621,17 @@
 			&chroma_offset);
 	}
 
+	/* Ensure proper covert matrix loaded when color space swaps */
+	curr = inpdw(vg_base + 0x0058);
+	mask = 0x600;
+	if ((curr & mask) != (pipe->op_mode & mask)) {
+		curr = ((uint32_t)vg_base) + 0x4000;
+		if (ptype != OVERLAY_TYPE_RGB)
+			mdp4_csc_write(&(mdp_csc_convert[1]), curr);
+		else
+			mdp4_csc_write(&(mdp_csc_convert[0]), curr);
+	}
+
 	/* luma component plane */
 	outpdw(vg_base + 0x0010, pipe->srcp0_addr + luma_offset);
 
@@ -1114,7 +1151,7 @@
 		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 
 	/*
-	 * BLT only siupport at primary display
+	 * BLT support both primary and external external
 	 */
 	if (pipe->blt_addr) {
 		int off, bpp;
@@ -1127,7 +1164,8 @@
 		data <<= 16;
 		data |= pipe->src_width;
 		outpdw(overlay_base + 0x0008, data); /* ROI, height + width */
-		if (pipe->mixer_num == MDP4_MIXER0) {
+		if (pipe->mixer_num == MDP4_MIXER0 ||
+		    pipe->mixer_num == MDP4_MIXER1) {
 			off = 0;
 			if (pipe->ov_cnt & 0x01)
 				off = pipe->src_height * pipe->src_width * bpp;
@@ -1258,107 +1296,111 @@
 	return cnt;
 }
 
+static void mdp4_mixer_stage_commit(int mixer)
+{
+	struct mdp4_overlay_pipe *pipe;
+	int i, j, off;
+	u32 data = 0, stage, flush_bits = 0, pipe_cnt = 0, pull_mode = 0;
+	u32 cfg[MDP4_MIXER_MAX];
+
+	for (i = MDP4_MIXER0; i < MDP4_MIXER_MAX; i++) {
+		cfg[i] = 0;
+		for (j = MDP4_MIXER_STAGE_BASE; j < MDP4_MIXER_STAGE_MAX; j++) {
+			pipe = ctrl->stage[i][j];
+			if (pipe == NULL)
+				break;
+			stage = pipe->mixer_stage;
+			if (i >= MDP4_MIXER1)
+				stage += 8;
+			stage <<= (4 * pipe->pipe_num);
+			cfg[i] |= stage;
+			pipe_cnt++;
+
+			mdp4_mixer_blend_setup(pipe);
+			if (i == mixer && pipe->pipe_num <= OVERLAY_PIPE_RGB2)
+				flush_bits |= (1 << (2 + pipe->pipe_num));
+		}
+	}
+
+	if (ctrl->mixer_cfg[mixer] != cfg[mixer]) {
+		if (mixer <= MDP4_MIXER1) {
+			off = 0x10100;
+			if (ctrl->mixer_cfg[MDP4_MIXER0] != cfg[MDP4_MIXER0]) {
+				flush_bits |= 0x1;
+				ctrl->mixer_cfg[MDP4_MIXER0] = cfg[MDP4_MIXER0];
+			}
+			if (ctrl->mixer_cfg[MDP4_MIXER1] != cfg[MDP4_MIXER1]) {
+				flush_bits |= 0x2;
+				ctrl->mixer_cfg[MDP4_MIXER1] = cfg[MDP4_MIXER1];
+			}
+			data = cfg[MDP4_MIXER0] | cfg[MDP4_MIXER1];
+		} else {
+			off = 0x100F0;
+			ctrl->mixer_cfg[MDP4_MIXER2] = cfg[MDP4_MIXER2];
+			data = cfg[MDP4_MIXER2];
+		}
+
+		pr_debug("%s: mixer=%d data=%x flush=%x\n", __func__,
+		       mixer, data, flush_bits);
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+		outpdw(MDP_BASE + off, data); /* MDP_LAYERMIXER_IN_CFG */
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	}
+
+	if (mixer == MDP4_MIXER0) {
+		if ((ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) ||
+		    (ctrl->panel_mode & MDP4_PANEL_LCDC))
+			pull_mode = 1;
+	} else if (mixer == MDP4_MIXER1) {
+		pull_mode = 1;
+	}
+
+	if (pull_mode) {
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+		outpdw(MDP_BASE + 0x18000, flush_bits);
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	}
+
+	if (data) {
+		if (pipe_cnt == 1) {
+			mdp4_update_perf_level(OVERLAY_PERF_LEVEL4);
+#ifdef CONFIG_MSM_BUS_SCALING
+			mdp_bus_scale_update_request(2);
+#endif
+		}
+	}
+}
+
 void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
 {
-	uint32 data, mask, snum, stage, mixer, pnum, off;
 	struct mdp4_overlay_pipe *spipe;
+	int mixer;
 
-	spipe = mdp4_overlay_stage_pipe(pipe->mixer_num, pipe->mixer_stage);
+	mixer = pipe->mixer_num;
+
+	spipe = ctrl->stage[mixer][pipe->mixer_stage];
 	if ((spipe != NULL) && (spipe->pipe_num != pipe->pipe_num)) {
 		mdp4_stat.err_stage++;
 		return;
 	}
 
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	ctrl->stage[mixer][pipe->mixer_stage] = pipe;	/* keep it */
 
-	stage = pipe->mixer_stage;
-	mixer = pipe->mixer_num;
-	pnum = pipe->pipe_num;
-
-	if (mixer == MDP4_MIXER2)
-		off = 0x100F0;
-	else
-		off = 0x10100;
-
-	/* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1  */
-	data = inpdw(MDP_BASE + off);
-
-	if (mixer >= MDP4_MIXER1)
-		stage += 8;
-
-	if (pipe->pipe_type == OVERLAY_TYPE_BF) {
-		snum = 16 + (4 * mixer);
-	} else if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {/* VG1 and VG2 */
-		pnum -= OVERLAY_PIPE_VG1; /* start from 0 */
-		snum = 0;
-		snum += (4 * pnum);
-	} else {
-		snum = 8;
-		snum += (4 * pnum);	/* RGB1 and RGB2 */
-	}
-
-	mask = 0x0f;
-	mask <<= snum;
-	stage <<= snum;
-	data &= ~mask;	/* clear old bits */
-
-	data |= stage;
-
-	outpdw(MDP_BASE + off, data); /* MDP_LAYERMIXER_IN_CFG */
-
-	data = inpdw(MDP_BASE + off);
-
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
-	ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = pipe;	/* keep it */
+	if (!(pipe->flags & MDP_OV_PLAY_NOWAIT))
+		mdp4_mixer_stage_commit(mixer);
 }
 
 void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe)
 {
-	uint32 data, mask, snum, stage, mixer, pnum, off;
+	struct mdp4_overlay_pipe *spipe;
 
-	stage = pipe->mixer_stage;
-	mixer = pipe->mixer_num;
-	pnum = pipe->pipe_num;
-
-	if (pipe != ctrl->stage[mixer][stage])	/* not runing */
+	spipe = ctrl->stage[pipe->mixer_num][pipe->mixer_stage];
+	if (spipe == NULL)	/* not running */
 		return;
 
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-
-	if (mixer == MDP4_MIXER2)
-		off = 0x100F0;
-	else
-		off = 0x10100;
-
-	/* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1  */
-	data = inpdw(MDP_BASE + off);
-
-	if (mixer >= MDP4_MIXER1)
-		stage += 8;
-
-	if (pipe->pipe_type == OVERLAY_TYPE_BF) {
-		snum = 16 + (4 * mixer);
-	} else if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {
-		pnum -= OVERLAY_PIPE_VG1; /* start from 0 */
-		snum = 0;
-		snum += (4 * pnum);
-	} else {
-		snum = 8;
-		snum += (4 * pnum);	/* RGB1 and RGB2 */
-	}
-
-	mask = 0x0f;
-	mask <<= snum;
-	data &= ~mask;	/* clear old bits */
-
-	outpdw(MDP_BASE + off, data); /* MDP_LAYERMIXER_IN_CFG */
-
-	data = inpdw(MDP_BASE + off);
-
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
 	ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL;	/* clear it */
+
+	mdp4_mixer_stage_commit(pipe->mixer_num);
 }
 
 void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe)
@@ -1367,7 +1409,7 @@
 	unsigned char *overlay_base, *rgb_base;
 	uint32 c0, c1, c2, blend_op, constant_color = 0, rgb_src_format;
 	uint32 fg_color3_out, fg_alpha = 0, bg_alpha = 0;
-	int off;
+	int off, pnum;
 
 	if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE)
 		return;
@@ -1431,9 +1473,10 @@
 
 	if (pipe->is_fg) {
 		if (pipe->alpha == 0xff &&
-		    bg_pipe && bg_pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
+			bg_pipe->pipe_type == OVERLAY_TYPE_RGB) {
+			pnum = bg_pipe->pipe_num - OVERLAY_PIPE_RGB1;
 			rgb_base = MDP_BASE + MDP4_RGB_BASE;
-			rgb_base += MDP4_RGB_OFF * bg_pipe->pipe_num;
+			rgb_base += MDP4_RGB_OFF * pnum;
 			rgb_src_format = inpdw(rgb_base + 0x50);
 			rgb_src_format |= MDP4_FORMAT_SOLID_FILL;
 			outpdw(rgb_base + 0x50, rgb_src_format);
@@ -1488,7 +1531,6 @@
 
 void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all)
 {
-	struct mdp4_overlay_pipe *bg_pipe;
 	uint32 bits = 0;
 
 	if (pipe->mixer_num == MDP4_MIXER1)
@@ -1496,31 +1538,8 @@
 	else
 		bits |= 0x01;
 
-	if (all && pipe->pipe_type != OVERLAY_TYPE_BF) {
-		if (pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
-			if (pipe->pipe_num == OVERLAY_PIPE_RGB2)
-				bits |= 0x20;
-			else
-				bits |= 0x10;
-		} else {
-			if (pipe->is_fg && pipe->alpha == 0xFF) {
-				bg_pipe = mdp4_overlay_stage_pipe(
-							pipe->mixer_num,
-							MDP4_MIXER_STAGE_BASE);
-				if (bg_pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
-					if (bg_pipe->pipe_num ==
-							OVERLAY_PIPE_RGB2)
-						bits |= 0x20;
-					else
-						bits |= 0x10;
-				}
-			}
-			if (pipe->pipe_num == OVERLAY_PIPE_VG2)
-				bits |= 0x08;
-			else
-				bits |= 0x04;
-		}
-	}
+	if (all && pipe->pipe_num <= OVERLAY_PIPE_RGB2)
+		bits |= 1 << (2 + pipe->pipe_num);
 
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	outpdw(MDP_BASE + 0x18000, bits);	/* MDP_OVERLAY_REG_FLUSH */
@@ -1562,7 +1581,7 @@
 				continue;
 			init_completion(&pipe->comp);
 			init_completion(&pipe->dmas_comp);
-			pr_info("%s: pipe=%x ndx=%d num=%d\n", __func__,
+			pr_debug("%s: pipe=%x ndx=%d num=%d\n", __func__,
 				(int)pipe, pipe->pipe_ndx, pipe->pipe_num);
 			return pipe;
 		}
@@ -1578,7 +1597,7 @@
 {
 	uint32 ptype, num, ndx, mixer;
 
-	pr_info("%s: pipe=%x ndx=%d\n", __func__, (int)pipe, pipe->pipe_ndx);
+	pr_debug("%s: pipe=%x ndx=%d\n", __func__, (int)pipe, pipe->pipe_ndx);
 
 	ptype = pipe->pipe_type;
 	num = pipe->pipe_num;
@@ -1593,26 +1612,6 @@
 	pipe->mixer_num = mixer;
 }
 
-int mdp4_overlay_req_check(uint32 id, uint32 z_order, uint32 mixer)
-{
-	struct mdp4_overlay_pipe *pipe;
-
-	pipe = ctrl->stage[mixer][z_order];
-
-	if (pipe == NULL)
-		return 0;
-
-	if (pipe->pipe_ndx == id)	/* same req, recycle */
-		return 0;
-
-	if (id == MSMFB_NEW_REQUEST) {  /* new request */
-		if (pipe->pipe_num >= OVERLAY_PIPE_VG1) /* share pipe */
-			return 0;
-	}
-
-	return -EPERM;
-}
-
 static int mdp4_overlay_validate_downscale(struct mdp_overlay *req,
 	struct msm_fb_data_type *mfd, uint32 perf_level, uint32 pclk_rate)
 {
@@ -2263,7 +2262,6 @@
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
 	struct mdp4_overlay_pipe *pipe;
-	uint32 flags;
 	struct dpp_ctrl dpp;
 	int i;
 
@@ -2301,50 +2299,35 @@
 #endif
 	}
 
-	mdp4_mixer_stage_down(pipe);
+	if (mfd->mdp_rev >= MDP_REV_42 && !mfd->use_ov0_blt &&
+	    !(ctrl->panel_mode & (MDP4_PANEL_MDDI | MDP4_PANEL_DSI_CMD))) {
+		ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL;
+	} else {
+		mdp4_mixer_stage_down(pipe);
 
-	if (pipe->mixer_num == MDP4_MIXER0) {
-
+		if (pipe->mixer_num == MDP4_MIXER0) {
 #ifdef CONFIG_FB_MSM_MIPI_DSI
-		if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
-			if (mfd->panel_power_on)
-				mdp4_dsi_cmd_overlay_restore();
-		}  else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
-			mdp4_overlay_reg_flush(pipe, 1);
-			if (mfd->panel_power_on) {
-				flags = pipe->flags;
-				pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
-				mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
-				pipe->flags = flags;
+			if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
+				if (mfd->panel_power_on)
+					mdp4_dsi_cmd_overlay_restore();
 			}
-		}
 #else
-		if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
-			if (mdp_hw_revision == MDP4_REVISION_V2_1)
-				mdp4_overlay_status_write(
-					MDP4_OVERLAY_TYPE_UNSET, true);
-			if (mfd->panel_power_on)
-				mdp4_mddi_overlay_restore();
-		}
-#endif
-		else if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
-			mdp4_overlay_reg_flush(pipe, 1);
-			if (mfd->panel_power_on) {
-				flags = pipe->flags;
-				pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
-				mdp4_overlay_lcdc_vsync_push(mfd, pipe);
-				pipe->flags = flags;
+			if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
+				if (mdp_hw_revision == MDP4_REVISION_V2_1)
+					mdp4_overlay_status_write(
+						MDP4_OVERLAY_TYPE_UNSET, true);
+				if (mfd->panel_power_on)
+					mdp4_mddi_overlay_restore();
 			}
+#endif
+			mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
+			mdp4_overlay_update_blt_mode(mfd);
+			if (!mfd->use_ov0_blt)
+				mdp4_free_writeback_buf(mfd, MDP4_MIXER0);
+		} else {	/* mixer1, DTV, ATV */
+			if (ctrl->panel_mode & MDP4_PANEL_DTV)
+				mdp4_overlay_dtv_unset(mfd, pipe);
 		}
-
-		mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
-		mdp4_overlay_update_blt_mode(mfd);
-		if (!mfd->use_ov0_blt)
-			mdp4_free_writeback_buf(mfd, MDP4_MIXER0);
-	}
-	else {	/* mixer1, DTV, ATV */
-		if (ctrl->panel_mode & MDP4_PANEL_DTV)
-			mdp4_overlay_dtv_unset(mfd, pipe);
 	}
 
 	/* Reset any HSIC settings to default */
@@ -2359,21 +2342,12 @@
 	mdp4_stat.overlay_unset[pipe->mixer_num]++;
 
 	mdp4_overlay_pipe_free(pipe);
-
-	if (!(ctrl->plist[OVERLAY_PIPE_VG1].pipe_used +
-	      ctrl->plist[OVERLAY_PIPE_VG2].pipe_used))
-		mdp4_update_perf_level(OVERLAY_PERF_LEVEL4);
-
 	mutex_unlock(&mfd->dma->ov_mutex);
 
-#ifdef CONFIG_MSM_BUS_SCALING
-	if (pipe->mixer_num == MDP4_MIXER0)
-		if (mfd->panel_power_on)
-			mdp_bus_scale_update_request(2);
-#endif
 	return 0;
 }
 
+
 struct tile_desc {
 	uint32 width;  /* tile's width */
 	uint32 height; /* tile's height */
@@ -2426,10 +2400,11 @@
 	if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
 		return -EINTR;
 
+	mdp4_mixer_stage_commit(pipe->mixer_num);
+
 	mdp4_overlay_dtv_wait_for_ov(mfd, pipe);
 
 	mutex_unlock(&mfd->dma->ov_mutex);
-
 	return 0;
 }
 
@@ -2568,9 +2543,9 @@
 	if (mfd->use_ov0_blt)
 		mdp4_overlay_update_blt_mode(mfd);
 
-	if (pipe->pipe_num >= OVERLAY_PIPE_VG1)
+	if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
 		mdp4_overlay_vg_setup(pipe);	/* video/graphic pipe */
-	else {
+	} else {
 		if (pipe->flags & MDP_SHARPENING) {
 			pr_warn(
 			"%s: Sharpening/Smoothing not supported on RGB pipe\n",
@@ -2580,7 +2555,6 @@
 		mdp4_overlay_rgb_setup(pipe);	/* rgb pipe */
 	}
 
-	mdp4_mixer_blend_setup(pipe);
 	mdp4_mixer_stage_up(pipe);
 
 	if (pipe->mixer_num == MDP4_MIXER2) {
@@ -2595,26 +2569,18 @@
 		ctrl->mixer1_played++;
 		/* enternal interface */
 		if (ctrl->panel_mode & MDP4_PANEL_DTV)
-#ifdef CONFIG_FB_MSM_DTV
 			mdp4_overlay_dtv_ov_done_push(mfd, pipe);
-#else
-			mdp4_overlay_reg_flush(pipe, 1);
-#endif
-		else if (ctrl->panel_mode & MDP4_PANEL_ATV)
-			mdp4_overlay_reg_flush(pipe, 1);
 	} else {
 
 		/* primary interface */
 		ctrl->mixer0_played++;
 		if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
-			mdp4_overlay_reg_flush(pipe, 1);
 			if (!mfd->use_ov0_blt)
 				mdp4_overlay_update_blt_mode(mfd);
 			mdp4_overlay_lcdc_vsync_push(mfd, pipe);
 		}
 #ifdef CONFIG_FB_MSM_MIPI_DSI
 		else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
-			mdp4_overlay_reg_flush(pipe, 1);
 			if (!mfd->use_ov0_blt)
 				mdp4_overlay_update_blt_mode(mfd);
 			mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
diff --git a/drivers/video/msm/mdp4_overlay_atv.c b/drivers/video/msm/mdp4_overlay_atv.c
index f9951e9..5cdafe1 100644
--- a/drivers/video/msm/mdp4_overlay_atv.c
+++ b/drivers/video/msm/mdp4_overlay_atv.c
@@ -166,7 +166,7 @@
 	pipe = atv_pipe;
 	pipe->srcp0_addr = (uint32) buf;
 	mdp4_overlay_rgb_setup(pipe);
-	mdp4_overlay_reg_flush(pipe, 1); /* rgb2 and mixer1 */
+	mdp4_mixer_stage_up(pipe);
 
 	printk(KERN_INFO "mdp4_atv_overlay: pipe=%x ndx=%d\n",
 					(int)pipe, pipe->pipe_ndx);
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 88582e4..3f12827 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -110,6 +110,8 @@
 	if (mfd->key != MFD_KEY)
 		return -EINVAL;
 
+	mdp4_overlay_ctrl_db_reset();
+
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
@@ -188,9 +190,9 @@
 	dsi_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
 	dsi_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
 	dsi_width = mfd->panel_info.xres +
-		mfd->panel_info.mipi.xres_pad;
+		mfd->panel_info.lcdc.xres_pad;
 	dsi_height = mfd->panel_info.yres +
-		mfd->panel_info.mipi.yres_pad;
+		mfd->panel_info.lcdc.yres_pad;
 	dsi_bpp = mfd->panel_info.bpp;
 
 	hsync_period = hsync_pulse_width + h_back_porch + dsi_width
@@ -248,7 +250,6 @@
 	MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x2c, dsi_underflow_clr);
 	MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x30, dsi_hsync_skew);
 	MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x38, ctrl_polarity);
-	mdp4_overlay_reg_flush(pipe, 1);
 	mdp_histogram_ctrl(TRUE);
 
 	ret = panel_next_on(pdev);
@@ -281,14 +282,9 @@
 	mdp_histogram_ctrl(FALSE);
 	ret = panel_next_off(pdev);
 
-#ifdef MIPI_DSI_RGB_UNSTAGE
-	/* delay to make sure the last frame finishes */
-	msleep(100);
-
 	/* dis-engage rgb0 from mixer0 */
 	if (dsi_pipe)
 		mdp4_mixer_stage_down(dsi_pipe);
-#endif
 
 	return ret;
 }
@@ -585,7 +581,7 @@
 		dsi_pipe->blt_addr = 0;
 		change++;
 	}
-	pr_info("%s: enable=%d blt_addr=%x\n", __func__,
+	pr_debug("%s: enable=%d blt_addr=%x\n", __func__,
 				enable, (int)dsi_pipe->blt_addr);
 	spin_unlock_irqrestore(&mdp_spin_lock, flag);
 
@@ -668,7 +664,7 @@
 	pipe = dsi_pipe;
 	pipe->srcp0_addr = (uint32) buf;
 	mdp4_overlay_rgb_setup(pipe);
-	mdp4_overlay_reg_flush(pipe, 1);
+	mdp4_mixer_stage_up(pipe);
 	mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
 	mutex_unlock(&mfd->dma->ov_mutex);
 }
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index f2065fd..3a1a9aa 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -264,36 +264,6 @@
 	return ret;
 }
 
-static void mdp4_overlay_dtv_wait4vsync(struct msm_fb_data_type *mfd)
-{
-	unsigned long flag;
-
-	/* enable irq */
-	spin_lock_irqsave(&mdp_spin_lock, flag);
-	mdp_enable_irq(MDP_OVERLAY1_TERM);
-	INIT_COMPLETION(dtv_pipe->comp);
-	mfd->dma->waiting = TRUE;
-	outp32(MDP_INTR_CLEAR, INTR_EXTERNAL_VSYNC);
-	mdp_intr_mask |= INTR_EXTERNAL_VSYNC;
-	outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-	spin_unlock_irqrestore(&mdp_spin_lock, flag);
-	wait_for_completion_killable(&dtv_pipe->comp);
-	mdp_disable_irq(MDP_OVERLAY1_TERM);
-}
-
-void mdp4_overlay_dtv_vsync_push(struct msm_fb_data_type *mfd,
-			struct mdp4_overlay_pipe *pipe)
-{
-	mdp4_overlay_reg_flush(pipe, 1);
-	if (pipe->flags & MDP_OV_PLAY_NOWAIT)
-		return;
-
-	mdp4_overlay_dtv_wait4vsync(mfd);
-
-	/* change mdp clk while mdp is idle` */
-	mdp4_set_perf_level();
-}
-
 static void mdp4_overlay_dtv_alloc_pipe(struct msm_fb_data_type *mfd,
 		int32 ptype)
 {
@@ -390,14 +360,8 @@
 int mdp4_overlay_dtv_unset(struct msm_fb_data_type *mfd,
 			struct mdp4_overlay_pipe *pipe)
 {
-	unsigned int flags;
 	int result = 0;
 
-	flags = pipe->flags;
-	pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
-	mdp4_overlay_dtv_ov_done_push(mfd, pipe);
-	pipe->flags = flags;
-
 	if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE &&
 			pipe->pipe_type == OVERLAY_TYPE_RGB) {
 		result = mdp4_dtv_stop(mfd);
@@ -406,6 +370,54 @@
 	return result;
 }
 
+static void mdp4_dtv_blt_ov_update(struct mdp4_overlay_pipe *pipe)
+{
+	uint32 off, addr;
+	int bpp;
+	char *overlay_base;
+
+	if (pipe->blt_addr == 0)
+		return;
+#ifdef BLT_RGB565
+	bpp = 2; /* overlay ouput is RGB565 */
+#else
+	bpp = 3; /* overlay ouput is RGB888 */
+#endif
+	off = (pipe->ov_cnt & 0x01) ?
+		pipe->src_height * pipe->src_width * bpp : 0;
+
+	addr = pipe->blt_addr + off;
+	pr_debug("%s overlay addr 0x%x\n", __func__, addr);
+	/* overlay 1 */
+	overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+	outpdw(overlay_base + 0x000c, addr);
+	outpdw(overlay_base + 0x001c, addr);
+}
+
+static inline void mdp4_dtv_blt_dmae_update(struct mdp4_overlay_pipe *pipe)
+{
+	uint32 off, addr;
+	int bpp;
+
+	if (pipe->blt_addr == 0)
+		return;
+
+#ifdef BLT_RGB565
+	bpp = 2; /* overlay ouput is RGB565 */
+#else
+	bpp = 3; /* overlay ouput is RGB888 */
+#endif
+	off =  (pipe->dmae_cnt & 0x01) ?
+		pipe->src_height * pipe->src_width * bpp : 0;
+	addr = pipe->blt_addr + off;
+	MDP_OUTP(MDP_BASE + 0xb0008, addr);
+}
+
+static inline void mdp4_overlay_dtv_ov_kick_start(void)
+{
+	outpdw(MDP_BASE + 0x0008, 0);
+}
+
 static void mdp4_overlay_dtv_ov_start(struct msm_fb_data_type *mfd)
 {
 	unsigned long flag;
@@ -414,6 +426,12 @@
 	if (mfd->ov_start)
 		return;
 
+	if (dtv_pipe->blt_addr) {
+		mdp4_dtv_blt_ov_update(dtv_pipe);
+		dtv_pipe->ov_cnt++;
+		mdp4_overlay_dtv_ov_kick_start();
+	}
+
 	spin_lock_irqsave(&mdp_spin_lock, flag);
 	mdp_enable_irq(MDP_OVERLAY1_TERM);
 	INIT_COMPLETION(dtv_pipe->comp);
@@ -437,14 +455,13 @@
 	if (!(data & 0x1) || (pipe == NULL))
 		return;
 	wait_for_completion_timeout(&dtv_pipe->comp,
-		msecs_to_jiffies(VSYNC_PERIOD));
+			msecs_to_jiffies(VSYNC_PERIOD*2));
 	mdp_disable_irq(MDP_OVERLAY1_TERM);
 }
 
 void mdp4_overlay_dtv_ov_done_push(struct msm_fb_data_type *mfd,
 			struct mdp4_overlay_pipe *pipe)
 {
-	mdp4_overlay_reg_flush(pipe, 1);
 	mdp4_overlay_dtv_ov_start(mfd);
 
 	if (pipe->flags & MDP_OV_PLAY_NOWAIT)
@@ -463,6 +480,11 @@
 	mdp4_set_perf_level();
 }
 
+void mdp4_dma_e_done_dtv()
+{
+	complete(&dtv_pipe->comp);
+}
+
 void mdp4_external_vsync_dtv()
 {
 	complete_all(&dtv_pipe->comp);
@@ -473,6 +495,10 @@
  */
 void mdp4_overlay1_done_dtv()
 {
+	if (dtv_pipe->blt_addr) {
+		mdp4_dtv_blt_dmae_update(dtv_pipe);
+		dtv_pipe->dmae_cnt++;
+	}
 	complete_all(&dtv_pipe->comp);
 }
 
@@ -501,11 +527,75 @@
 	*/
 	temp_src_format = inpdw(rgb_base + 0x0050);
 	MDP_OUTP(rgb_base + 0x0050, temp_src_format | BIT(22));
-	mdp4_overlay_reg_flush(dtv_pipe, 1);
+	mdp4_mixer_stage_up(pipe);
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 }
 #endif
 
+static void mdp4_overlay_dtv_wait4dmae(struct msm_fb_data_type *mfd)
+{
+	unsigned long flag;
+
+	/* enable irq */
+	spin_lock_irqsave(&mdp_spin_lock, flag);
+	mdp_enable_irq(MDP_DMA_E_TERM);
+	INIT_COMPLETION(dtv_pipe->comp);
+	mfd->dma->waiting = TRUE;
+	outp32(MDP_INTR_CLEAR, INTR_DMA_E_DONE);
+	mdp_intr_mask |= INTR_DMA_E_DONE;
+	outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+	spin_unlock_irqrestore(&mdp_spin_lock, flag);
+	wait_for_completion_killable(&dtv_pipe->comp);
+	mdp_disable_irq(MDP_DMA_E_TERM);
+}
+
+static void mdp4_dtv_do_blt(struct msm_fb_data_type *mfd, int enable)
+{
+	unsigned long flag;
+	int change = 0;
+
+	if (!mfd->ov1_wb_buf->phys_addr) {
+		pr_debug("%s: no writeback buf assigned\n", __func__);
+		return;
+	}
+
+	spin_lock_irqsave(&mdp_spin_lock, flag);
+	if (enable && dtv_pipe->blt_addr == 0) {
+		dtv_pipe->blt_addr = mfd->ov1_wb_buf->phys_addr;
+		change++;
+		dtv_pipe->ov_cnt = 0;
+		dtv_pipe->dmae_cnt = 0;
+	} else if (enable == 0 && dtv_pipe->blt_addr) {
+		dtv_pipe->blt_addr = 0;
+		change++;
+	}
+	pr_debug("%s: blt_addr=%x\n", __func__, (int)dtv_pipe->blt_addr);
+	spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+	if (!change)
+		return;
+
+	mdp4_overlay_dtv_wait4dmae(mfd);
+
+	MDP_OUTP(MDP_BASE + DTV_BASE, 0);	/* stop dtv */
+	msleep(20);
+	mdp4_overlayproc_cfg(dtv_pipe);
+	mdp4_overlay_dmae_xy(dtv_pipe);
+	MDP_OUTP(MDP_BASE + DTV_BASE, 1);	/* start dtv */
+}
+
+void mdp4_dtv_overlay_blt_start(struct msm_fb_data_type *mfd)
+{
+	mdp4_allocate_writeback_buf(mfd, MDP4_MIXER1);
+	mdp4_dtv_do_blt(mfd, 1);
+}
+
+void mdp4_dtv_overlay_blt_stop(struct msm_fb_data_type *mfd)
+{
+	mdp4_free_writeback_buf(mfd, MDP4_MIXER1);
+	mdp4_dtv_do_blt(mfd, 0);
+}
+
 void mdp4_dtv_overlay(struct msm_fb_data_type *mfd)
 {
 	struct mdp4_overlay_pipe *pipe;
@@ -527,6 +617,7 @@
 		pipe->srcp0_addr = (uint32) mfd->ibuf.buf;
 		mdp4_overlay_rgb_setup(pipe);
 	}
+	mdp4_mixer_stage_up(pipe);
 	mdp4_overlay_dtv_ov_done_push(mfd, pipe);
 	mutex_unlock(&mfd->dma->ov_mutex);
 }
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 5ad6de3f..fdb1ec5 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -45,6 +45,73 @@
 static struct mdp4_overlay_pipe *lcdc_pipe;
 static struct completion lcdc_comp;
 
+static void lvds_init(struct msm_fb_data_type *mfd)
+{
+	unsigned int lvds_intf, lvds_phy_cfg0;
+
+	if (mfd->panel_info.bpp == 24) {
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
+		MDP_OUTP(MDP_BASE +  0xc2014, 0x03040508);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
+		MDP_OUTP(MDP_BASE +  0xc2018, 0x00000102);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
+		MDP_OUTP(MDP_BASE +  0xc201c, 0x0c0d1011);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
+		MDP_OUTP(MDP_BASE +  0xc2020, 0x00090a0b);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
+		MDP_OUTP(MDP_BASE +  0xc2024, 0x1518191a);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
+		MDP_OUTP(MDP_BASE +  0xc2028, 0x00121314);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_3_TO_0 */
+		MDP_OUTP(MDP_BASE +  0xc202c, 0x0f16171b);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_6_TO_4 */
+		MDP_OUTP(MDP_BASE +  0xc2030, 0x0006070e);
+
+		if (mfd->panel_info.lvds.channel_mode ==
+			LVDS_DUAL_CHANNEL_MODE) {
+			lvds_intf = 0x0001ff80;
+			lvds_phy_cfg0 = BIT(6) | BIT(7);
+			if (mfd->panel_info.lvds.channel_swap)
+				lvds_intf |= BIT(4);
+		} else {
+			lvds_intf = 0x00010f84;
+			lvds_phy_cfg0 = BIT(6);
+		}
+	} else if (mfd->panel_info.bpp == 18) {
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
+		MDP_OUTP(MDP_BASE +  0xc2014, 0x03040508);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
+		MDP_OUTP(MDP_BASE +  0xc2018, 0x00000102);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
+		MDP_OUTP(MDP_BASE +  0xc201c, 0x0c0d1011);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
+		MDP_OUTP(MDP_BASE +  0xc2020, 0x00090a0b);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
+		MDP_OUTP(MDP_BASE +  0xc2024, 0x1518191a);
+		/* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
+		MDP_OUTP(MDP_BASE +  0xc2028, 0x00121314);
+
+		if (mfd->panel_info.lvds.channel_mode ==
+			LVDS_DUAL_CHANNEL_MODE) {
+			lvds_intf = 0x00017788;
+			lvds_phy_cfg0 = BIT(6) | BIT(7);
+			if (mfd->panel_info.lvds.channel_swap)
+				lvds_intf |= BIT(4);
+		} else {
+			lvds_intf = 0x0001078c;
+			lvds_phy_cfg0 = BIT(6);
+		}
+	}
+
+	/* MDP_LVDSPHY_CFG0 */
+	MDP_OUTP(MDP_BASE +  0xc3100, lvds_phy_cfg0);
+	/* MDP_LCDC_LVDS_INTF_CTL */
+	MDP_OUTP(MDP_BASE +  0xc2000, lvds_intf);
+	lvds_phy_cfg0 |= BIT(4);
+	/* MDP_LVDSPHY_CFG0, enable serialization */
+	MDP_OUTP(MDP_BASE +  0xc3100, lvds_phy_cfg0);
+}
+
 int mdp_lcdc_on(struct platform_device *pdev)
 {
 	int lcdc_width;
@@ -93,6 +160,8 @@
 	if (mfd->key != MFD_KEY)
 		return -EINVAL;
 
+	mdp4_overlay_ctrl_db_reset();
+
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
@@ -165,8 +234,8 @@
 	lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
 	lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
 
-	lcdc_width = var->xres;
-	lcdc_height = var->yres;
+	lcdc_width = var->xres + mfd->panel_info.lcdc.xres_pad;
+	lcdc_height = var->yres + mfd->panel_info.lcdc.yres_pad;
 	lcdc_bpp = mfd->panel_info.bpp;
 
 	hsync_period =
@@ -231,12 +300,14 @@
 	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x20, active_v_start);
 	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x24, active_v_end);
 
-	mdp4_overlay_reg_flush(pipe, 1);
 #ifdef CONFIG_MSM_BUS_SCALING
 	mdp_bus_scale_update_request(2);
 #endif
 	mdp_histogram_ctrl(TRUE);
 
+	if (mfd->panel.type == LVDS_PANEL)
+		lvds_init(mfd);
+
 	ret = panel_next_on(pdev);
 	if (ret == 0) {
 		/* enable LCDC block */
@@ -273,11 +344,10 @@
 	/* delay to make sure the last frame finishes */
 	msleep(16);
 
-#ifdef LCDC_RGB_UNSTAGE
 	/* dis-engage rgb0 from mixer0 */
 	if (lcdc_pipe)
 		mdp4_mixer_stage_down(lcdc_pipe);
-#endif
+
 #ifdef CONFIG_MSM_BUS_SCALING
 	mdp_bus_scale_update_request(0);
 #endif
@@ -568,7 +638,7 @@
 	pipe = lcdc_pipe;
 	pipe->srcp0_addr = (uint32) buf;
 	mdp4_overlay_rgb_setup(pipe);
-	mdp4_overlay_reg_flush(pipe, 1);
+	mdp4_mixer_stage_up(pipe);
 	mdp4_overlay_lcdc_vsync_push(mfd, pipe);
 	mutex_unlock(&mfd->dma->ov_mutex);
 }
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index bd8ec55..d82672e 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -554,7 +554,7 @@
 		mdp_intr_mask &= ~INTR_DMA_E_DONE;
 		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
 		dma->busy = FALSE;
-
+		mdp4_dma_e_done_dtv();
 		if (dma->waiting) {
 			dma->waiting = FALSE;
 			complete(&dma->comp);
@@ -1232,15 +1232,60 @@
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 }
 
+struct mdp_csc_cfg mdp_csc_convert[4] = {
+	{ /*RGB2RGB*/
+		0,
+		{
+			0x0200, 0x0000, 0x0000,
+			0x0000, 0x0200, 0x0000,
+			0x0000, 0x0000, 0x0200,
+		},
+		{ 0x0, 0x0, 0x0, },
+		{ 0x0, 0x0, 0x0, },
+		{ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+		{ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+	},
+	{ /*YUV2RGB*/
+		0,
+		{
+			0x0254, 0x0000, 0x0331,
+			0x0254, 0xff37, 0xfe60,
+			0x0254, 0x0409, 0x0000,
+		},
+		{ 0xfff0, 0xff80, 0xff80, },
+		{ 0x0, 0x0, 0x0, },
+		{ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+		{ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+	},
+	{ /*RGB2YUV*/
+		0,
+		{
+			0x0083, 0x0102, 0x0032,
+			0x1fb5, 0x1f6c, 0x00e1,
+			0x00e1, 0x1f45, 0x1fdc
+		},
+		{ 0x0, 0x0, 0x0, },
+		{ 0x0010, 0x0080, 0x0080, },
+		{ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+		{ 0x0010, 0x00eb, 0x0010, 0x00f0, 0x0010, 0x00f0, },
+	},
+	{ /*YUV2YUV ???*/
+		0,
+		{
+			0x0200, 0x0000, 0x0000,
+			0x0000, 0x0200, 0x0000,
+			0x0000, 0x0000, 0x0200,
+		},
+		{ 0x0, 0x0, 0x0, },
+		{ 0x0, 0x0, 0x0, },
+		{ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+		{ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+	},
+};
 
-struct mdp4_csc_matrix {
-uint32 csc_mv[9];
-uint32 csc_pre_bv[3];
-uint32 csc_post_bv[3];
-uint32 csc_pre_lv[6];
-uint32 csc_post_lv[6];
-} csc_matrix[3] = {
+struct mdp_csc_cfg csc_matrix[3] = {
 	{
+		(MDP_CSC_FLAG_YUV_OUT),
 		{
 			0x0254, 0x0000, 0x0331,
 			0x0254, 0xff37, 0xfe60,
@@ -1260,6 +1305,7 @@
 		},
 	},
 	{
+		(MDP_CSC_FLAG_YUV_OUT),
 		{
 			0x0254, 0x0000, 0x0331,
 			0x0254, 0xff37, 0xfe60,
@@ -1279,6 +1325,7 @@
 		},
 	},
 	{
+		(0),
 		{
 			0x0200, 0x0000, 0x0000,
 			0x0000, 0x0200, 0x0000,
@@ -1392,6 +1439,25 @@
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 }
 
+void mdp4_vg_csc_convert_setup(int vp_num)
+{
+	struct mdp_csc_cfg_data cfg;
+
+	switch (vp_num) {
+	case 0:
+		cfg.block = MDP_BLOCK_VG_1;
+		break;
+	case 1:
+		cfg.block = MDP_BLOCK_VG_2;
+		break;
+	default:
+		pr_err("%s - invalid vp_num = %d", __func__, vp_num);
+		return;
+	}
+	cfg.csc_data = csc_matrix[vp_num];
+	mdp4_csc_enable(&cfg);
+}
+
 void mdp4_vg_csc_setup(int vp_num)
 {
 		/* yuv2rgb */
@@ -1400,6 +1466,7 @@
 		mdp4_vg_csc_post_bv_setup(vp_num);
 		mdp4_vg_csc_pre_lv_setup(vp_num);
 		mdp4_vg_csc_post_lv_setup(vp_num);
+		mdp4_vg_csc_convert_setup(vp_num);
 }
 void mdp4_vg_csc_update(struct mdp_csc *p)
 {
@@ -2347,13 +2414,15 @@
 	case MDP_BLOCK_DMA_P:
 		base = 0x93000;
 		break;
+	case MDP_BLOCK_DMA_S:
+		base = (mdp_rev >= MDP_REV_42) ? 0xA3000 : 0x0;
 	default:
 		break;
 	}
 	return base;
 }
 
-static int mdp4_csc_enable(struct mdp_csc_cfg_data *config)
+int mdp4_csc_enable(struct mdp_csc_cfg_data *config)
 {
 	uint32_t output, base, temp, mask;
 
@@ -2365,9 +2434,32 @@
 		output |= temp;
 		mask = 0x08 | 0x1800;
 		break;
+	case MDP_BLOCK_DMA_S:
+		base = 0xA0028;
+		output = (config->csc_data.flags << 3) & (0x08);
+		temp = (config->csc_data.flags << 10) & (0x1800);
+		output |= temp;
+		mask = 0x08 | 0x1800;
+		break;
 	case MDP_BLOCK_VG_1:
+		base = 0x20058;
+		output = (config->csc_data.flags << 11) & (0x800);
+		temp = (config->csc_data.flags << 8) & (0x600);
+		output |= temp;
+		mask = 0x800 | 0x600;
+		break;
 	case MDP_BLOCK_VG_2:
+		base = 0x30058;
+		output = (config->csc_data.flags << 11) & (0x800);
+		temp = (config->csc_data.flags << 8) & (0x600);
+		output |= temp;
+		mask = 0x800 | 0x600;
+		break;
 	case MDP_BLOCK_OVERLAY_1:
+		base = 0x18200;
+		output = config->csc_data.flags;
+		mask = 0x07;
+		break;
 	default:
 		pr_err("%s - CSC block does not exist on MDP_BLOCK = %d\n",
 						__func__, config->block);
@@ -2387,46 +2479,49 @@
 #define CSC_LV_OFF	0x600
 #define CSC_POST_OFF	0x80
 
-int mdp4_csc_config(struct mdp_csc_cfg_data *config)
+void mdp4_csc_write(struct mdp_csc_cfg *data, uint32_t base)
 {
-	int ret = 0;
 	int i;
-	uint32_t base, *off;
-
-	base = mdp4_csc_block2base(config->block);
-	if (!base)
-		return -EINVAL;
-
-	/* TODO: implement other CSC block support */
-	if (config->block != MDP_BLOCK_DMA_P) {
-		pr_warn("%s: Only DMA_P currently supported by CSC.\n",
-		__func__);
-		return -EINVAL;
-	}
+	uint32_t *off;
 
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	off = (uint32_t *) (MDP_BASE + base + CSC_MV_OFF);
+	off = (uint32_t *) ((uint32_t) base + CSC_MV_OFF);
 	for (i = 0; i < 9; i++) {
-		outpdw(off, config->csc_data.csc_mv[i]);
+		outpdw(off, data->csc_mv[i]);
 		off++;
 	}
 
-	off = (uint32_t *) (MDP_BASE + base + CSC_BV_OFF);
+	off = (uint32_t *) ((uint32_t) base + CSC_BV_OFF);
 	for (i = 0; i < 3; i++) {
-		outpdw(off, config->csc_data.csc_pre_bv[i]);
+		outpdw(off, data->csc_pre_bv[i]);
 		outpdw((uint32_t *)((uint32_t)off + CSC_POST_OFF),
-					config->csc_data.csc_post_bv[i]);
+					data->csc_post_bv[i]);
 		off++;
 	}
 
-	off = (uint32_t *) (MDP_BASE + base + CSC_LV_OFF);
+	off = (uint32_t *) ((uint32_t) base + CSC_LV_OFF);
 	for (i = 0; i < 6; i++) {
-		outpdw(off, config->csc_data.csc_pre_lv[i]);
+		outpdw(off, data->csc_pre_lv[i]);
 		outpdw((uint32_t *)((uint32_t)off + CSC_POST_OFF),
-					config->csc_data.csc_post_lv[i]);
+					data->csc_post_lv[i]);
 		off++;
 	}
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+int mdp4_csc_config(struct mdp_csc_cfg_data *config)
+{
+	int ret = 0;
+	uint32_t base;
+
+	base = mdp4_csc_block2base(config->block);
+	if (!base) {
+		pr_warn("%s: Block type %d isn't supported by CSC.\n",
+				__func__, config->block);
+		return -EINVAL;
+	}
+
+	mdp4_csc_write(&config->csc_data, (uint32_t) (MDP_BASE + base));
 
 	ret = mdp4_csc_enable(config);
 
@@ -2461,23 +2556,23 @@
 		return 0;
 
 	if (!buf->size) {
-		pr_err("%s:%d In valid size", __func__, __LINE__);
+		pr_err("%s:%d In valid size\n", __func__, __LINE__);
 		return -EINVAL;
 	}
 
 	if (!IS_ERR_OR_NULL(mfd->iclient)) {
-		pr_info("%s:%d ion based allocation", __func__, __LINE__);
+		pr_info("%s:%d ion based allocation\n", __func__, __LINE__);
 		buf->ihdl = ion_alloc(mfd->iclient, buf->size, 4,
 			(1 << mfd->mem_hid));
 		if (!IS_ERR_OR_NULL(buf->ihdl)) {
 			if (ion_phys(mfd->iclient, buf->ihdl,
 				&addr, &len)) {
-				pr_err("%s:%d: ion_phys map failed",
+				pr_err("%s:%d: ion_phys map failed\n",
 					__func__, __LINE__);
 				return -ENOMEM;
 			}
 		} else {
-			pr_err("%s:%d: ion_alloc failed", __func__,
+			pr_err("%s:%d: ion_alloc failed\n", __func__,
 				__LINE__);
 			return -ENOMEM;
 		}
@@ -2507,14 +2602,18 @@
 		buf = mfd->ov1_wb_buf;
 
 	if (!IS_ERR_OR_NULL(mfd->iclient)) {
-		if (!IS_ERR_OR_NULL(buf->ihdl))
+		if (!IS_ERR_OR_NULL(buf->ihdl)) {
 			ion_free(mfd->iclient, buf->ihdl);
-		buf->ihdl = NULL;
-		pr_info("%s:%d free writeback imem", __func__, __LINE__);
+			pr_debug("%s:%d free writeback imem\n", __func__,
+				__LINE__);
+			buf->ihdl = NULL;
+		}
 	} else {
-		if (buf->phys_addr)
+		if (buf->phys_addr) {
 			free_contiguous_memory_by_paddr(buf->phys_addr);
-		pr_info("%s:%d free writeback pmem", __func__, __LINE__);
+			pr_debug("%s:%d free writeback pmem\n", __func__,
+				__LINE__);
+		}
 	}
 	buf->phys_addr = 0;
 }
diff --git a/drivers/video/msm/mdp4_wfd_writeback_panel.c b/drivers/video/msm/mdp4_wfd_writeback_panel.c
index 32b0669..40ffb65 100644
--- a/drivers/video/msm/mdp4_wfd_writeback_panel.c
+++ b/drivers/video/msm/mdp4_wfd_writeback_panel.c
@@ -37,8 +37,8 @@
 static struct msm_fb_panel_data writeback_msm_panel_data = {
 	.panel_info = {
 		.type = WRITEBACK_PANEL,
-		.xres = 800,
-		.yres = 480,
+		.xres = 1280,
+		.yres = 720,
 		.pdest = DISPLAY_3,
 		.wait_cycle = 0,
 		.bpp = 24,
diff --git a/drivers/video/msm/mdp_debugfs.c b/drivers/video/msm/mdp_debugfs.c
index 1b25c21..7defd82 100644
--- a/drivers/video/msm/mdp_debugfs.c
+++ b/drivers/video/msm/mdp_debugfs.c
@@ -437,16 +437,20 @@
 	len = snprintf(bp, dlen, "frame_push:\n");
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "rgb1:  %08lu\t\t", mdp4_stat.pipe[0]);
+	len = snprintf(bp, dlen, "rgb1:  %08lu\t\t",
+		       mdp4_stat.pipe[OVERLAY_PIPE_RGB1]);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "rgb2:  %08lu\n", mdp4_stat.pipe[1]);
+	len = snprintf(bp, dlen, "rgb2:  %08lu\n",
+		       mdp4_stat.pipe[OVERLAY_PIPE_RGB2]);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "vg1:   %08lu\t\t", mdp4_stat.pipe[2]);
+	len = snprintf(bp, dlen, "vg1:   %08lu\t\t",
+		       mdp4_stat.pipe[OVERLAY_PIPE_VG1]);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "vg2:   %08lu\n", mdp4_stat.pipe[3]);
+	len = snprintf(bp, dlen, "vg2:   %08lu\n",
+		       mdp4_stat.pipe[OVERLAY_PIPE_VG2]);
 	bp += len;
 	dlen -= len;
 	len = snprintf(bp, dlen, "err_mixer: %08lu\t", mdp4_stat.err_mixer);
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 19dfe82..199e472 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/msm/mdp_ppp.c
@@ -1,7 +1,7 @@
 /* drivers/video/msm/src/drv/mdp/mdp_ppp.c
  *
  * Copyright (C) 2007 Google Incorporated
- * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -52,6 +52,7 @@
 	[MDP_RGBX_8888] = 4,
 	[MDP_Y_CBCR_H2V1] = 1,
 	[MDP_Y_CBCR_H2V2] = 1,
+	[MDP_Y_CBCR_H2V2_ADRENO] = 1,
 	[MDP_Y_CRCB_H2V1] = 1,
 	[MDP_Y_CRCB_H2V2] = 1,
 	[MDP_YCRYCB_H2V1] = 2,
@@ -535,14 +536,16 @@
 
 #define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \
 				(img == MDP_Y_CBCR_H2V2) | \
+				(img == MDP_Y_CBCR_H2V2_ADRENO) | \
 				(img == MDP_Y_CRCB_H2V1) | \
 				(img == MDP_Y_CBCR_H2V1))
 
 #define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
 
 #define Y_TO_CRCB_RATIO(format) \
-	((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ?  2 :\
-	(format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ?  1 : 1)
+	((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CBCR_H2V2_ADRENO || \
+	  format == MDP_Y_CRCB_H2V2) ?  2 : (format == MDP_Y_CBCR_H2V1 || \
+	  format == MDP_Y_CRCB_H2V1) ?  1 : 1)
 
 #ifdef CONFIG_ANDROID_PMEM
 static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
@@ -589,6 +592,7 @@
 	uint32 src_width;
 	uint32 src_height;
 	uint32 src0_ystride;
+	uint32 src0_y1stride;
 	uint32 dst_roi_width;
 	uint32 dst_roi_height;
 	uint32 ppp_src_cfg_reg, ppp_operation_reg, ppp_dst_cfg_reg;
@@ -868,6 +872,7 @@
 		break;
 
 	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CBCR_H2V2_ADRENO:
 	case MDP_Y_CRCB_H2V2:
 		inpBpp = 1;
 		src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
@@ -1059,7 +1064,16 @@
 		}
 	}
 
-	src0_ystride = src_width * inpBpp;
+	if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO)
+		src0_ystride = ALIGN(src_width, 32) * inpBpp;
+	else
+		src0_ystride = src_width * inpBpp;
+
+	if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO)
+		src0_y1stride = 2 * ALIGN(src_width/2, 32);
+	else
+		src0_y1stride = src0_ystride;
+
 	dest0_ystride = iBuf->ibuf_width * iBuf->bpp;
 
 	/* no need to care about rotation since it's the real-XY. */
@@ -1121,7 +1135,7 @@
 	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x010c, src0); /* comp.plane 0 */
 	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0110, src1); /* comp.plane 1 */
 	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x011c,
-		 (src0_ystride << 16 | src0_ystride));
+		 (src0_y1stride << 16 | src0_ystride));
 
 	/* setup for rgb 565 */
 	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0124, ppp_src_cfg_reg);
@@ -1362,9 +1376,16 @@
 	iBuf.mdpImg.imgType = req->src.format;
 
 	iBuf.mdpImg.bmy_addr = (uint32 *) (src_start + req->src.offset);
-	iBuf.mdpImg.cbcr_addr =
-	    (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
-			req->src.width * req->src.height);
+
+	if (iBuf.mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO)
+		iBuf.mdpImg.cbcr_addr =
+			(uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
+				ALIGN((ALIGN(req->src.width, 32) *
+				ALIGN(req->src.height, 32)), 4096));
+	else
+		iBuf.mdpImg.cbcr_addr =
+			(uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
+				req->src.width * req->src.height);
 
 	iBuf.mdpImg.mdpOp = MDPOP_NOP;
 
diff --git a/drivers/video/msm/mdp_ppp_v20.c b/drivers/video/msm/mdp_ppp_v20.c
index 8828a8f..e2a6564 100644
--- a/drivers/video/msm/mdp_ppp_v20.c
+++ b/drivers/video/msm/mdp_ppp_v20.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1625,6 +1625,7 @@
 		 * offsite in vertical axis
 		 */
 	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CBCR_H2V2_ADRENO:
 	case MDP_Y_CRCB_H2V2:
 		/* floor( luma_interp_point_left / 2) */
 		chroma_interp_point_left = luma_interp_point_left >> 1;
@@ -1678,6 +1679,7 @@
 			break;
 
 		case MDP_Y_CBCR_H2V2:
+		case MDP_Y_CBCR_H2V2_ADRENO:
 		case MDP_Y_CRCB_H2V2:
 			/*
 			 * cosite in horizontal dir, and offsite in vertical dir
diff --git a/drivers/video/msm/mipi_NT35510.c b/drivers/video/msm/mipi_NT35510.c
new file mode 100644
index 0000000..ff513d0
--- /dev/null
+++ b/drivers/video/msm/mipi_NT35510.c
@@ -0,0 +1,586 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_NT35510.h"
+
+static struct msm_panel_common_pdata *mipi_nt35510_pdata;
+static struct dsi_buf nt35510_tx_buf;
+static struct dsi_buf nt35510_rx_buf;
+
+#define NT35510_SLEEP_OFF_DELAY 150
+#define NT35510_DISPLAY_ON_DELAY 150
+
+/* common setting */
+static char exit_sleep[2] = {0x11, 0x00};
+static char display_on[2] = {0x29, 0x00};
+static char display_off[2] = {0x28, 0x00};
+static char enter_sleep[2] = {0x10, 0x00};
+static char write_ram[2] = {0x2c, 0x00}; /* write ram */
+
+static struct dsi_cmd_desc nt35510_display_off_cmds[] = {
+	{DTYPE_DCS_WRITE, 1, 0, 0, 150, sizeof(display_off), display_off},
+	{DTYPE_DCS_WRITE, 1, 0, 0, 150, sizeof(enter_sleep), enter_sleep}
+};
+
+static char cmd0[6] = {
+	0xF0, 0x55, 0xAA, 0x52,
+	0x08, 0x01,
+};
+static char cmd1[4] = {
+	0xBC, 0x00, 0xA0, 0x00,
+};
+static char cmd2[4] = {
+	0xBD, 0x00, 0xA0, 0x00,
+};
+static char cmd3[3] = {
+	0xBE, 0x00, 0x79,
+};
+static char cmd4[53] = {
+	0xD1, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char cmd5[53] = {
+	0xD2, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char cmd6[53] = {
+	0xD3, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char cmd7[53] = {
+	0xD4, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char cmd8[53] = {
+	0xD5, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char cmd9[53] = {
+	0xD6, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char cmd10[4] = {
+	0xB0, 0x0A, 0x0A, 0x0A,
+};
+static char cmd11[4] = {
+	0xB1, 0x0A, 0x0A, 0x0A,
+};
+static char cmd12[4] = {
+	0xBA, 0x24, 0x24, 0x24,
+};
+static char cmd13[4] = {
+	0xB9, 0x24, 0x24, 0x24,
+};
+static char cmd14[4] = {
+	0xB8, 0x24, 0x24, 0x24,
+};
+static char cmd15[6] = {
+	0xF0, 0x55, 0xAA, 0x52,
+	0x08, 0x00,
+};
+static char cmd16[2] = {
+	0xB3, 0x00,
+};
+static char cmd17[2] = {
+	0xB4, 0x10,
+};
+static char cmd18[2] = {
+	0xB6, 0x02,
+};
+static char cmd19[3] = {
+	0xB1, 0xEC, 0x06,
+};
+static char cmd20[4] = {
+	0xBC, 0x05, 0x05, 0x05,
+};
+static char cmd21[3] = {
+	0xB7, 0x20, 0x20,
+};
+static char cmd22[5] = {
+	0xB8, 0x01, 0x03, 0x03,
+	0x03,
+};
+static char cmd23[19] = {
+	0xC8, 0x01, 0x00, 0x78,
+	0x50, 0x78, 0x50, 0x78,
+	0x50, 0x78, 0x50, 0xC8,
+	0x3C, 0x3C, 0xC8, 0xC8,
+	0x3C, 0x3C, 0xC8,
+};
+static char cmd24[6] = {
+	0xBD, 0x01, 0x84, 0x07,
+	0x31, 0x00,
+};
+static char cmd25[6] = {
+	0xBE, 0x01, 0x84, 0x07,
+	0x31, 0x00,
+};
+static char cmd26[6] = {
+	0xBF, 0x01, 0x84, 0x07,
+	0x31, 0x00,
+};
+static char cmd27[2] = {
+	0x35, 0x00,
+};
+static char config_MADCTL[2] = {0x36, 0xC0};
+static struct dsi_cmd_desc nt35510_cmd_display_on_cmds[] = {
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd0), cmd0},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd1), cmd1},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd2), cmd2},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd3), cmd3},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd4), cmd4},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd5), cmd5},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd6), cmd6},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd7), cmd7},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd8), cmd8},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd9), cmd9},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd10), cmd10},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd11), cmd11},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd12), cmd12},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd13), cmd13},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd14), cmd14},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd15), cmd15},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd16), cmd16},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd17), cmd17},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd18), cmd18},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd19), cmd19},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd20), cmd20},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd21), cmd21},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd22), cmd22},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd23), cmd23},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd24), cmd24},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd25), cmd25},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd26), cmd26},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd27), cmd27},
+
+	{DTYPE_DCS_WRITE, 1, 0, 0, 150,	sizeof(exit_sleep), exit_sleep},
+	{DTYPE_DCS_WRITE, 1, 0, 0, 10,	sizeof(display_on), display_on},
+
+	{DTYPE_DCS_WRITE1, 1, 0, 0, 150,
+		sizeof(config_MADCTL), config_MADCTL},
+
+	{DTYPE_DCS_WRITE, 1, 0, 0, 10,	sizeof(write_ram), write_ram},
+};
+
+static char video0[6] = {
+	0xF0, 0x55, 0xAA, 0x52,
+	0x08, 0x01,
+};
+static char video1[4] = {
+	0xBC, 0x00, 0xA0, 0x00,
+};
+static char video2[4] = {
+	0xBD, 0x00, 0xA0, 0x00,
+};
+static char video3[3] = {
+	0xBE, 0x00, 0x79,
+};
+static char video4[53] = {
+	0xD1, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char video5[53] = {
+	0xD2, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char video6[53] = {
+	0xD3, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char video7[53] = {
+	0xD4, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char video8[53] = {
+	0xD5, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char video9[53] = {
+	0xD6, 0x00, 0x00, 0x00,
+	0x14, 0x00, 0x32, 0x00,
+	0x4F, 0x00, 0x65, 0x00,
+	0x8B, 0x00, 0xA8, 0x00,
+	0xD5, 0x00, 0xF7, 0x01,
+	0x2B, 0x01, 0x54, 0x01,
+	0x8E, 0x01, 0xBB, 0x01,
+	0xBC, 0x01, 0xE3, 0x02,
+	0x08, 0x02, 0x1C, 0x02,
+	0x39, 0x02, 0x4F, 0x02,
+	0x76, 0x02, 0xA3, 0x02,
+	0xE3, 0x03, 0x12, 0x03,
+	0x4C, 0x03, 0x66, 0x03,
+	0x9A,
+};
+static char video10[4] = {
+	0xB0, 0x0A, 0x0A, 0x0A,
+};
+static char video11[4] = {
+	0xB1, 0x0A, 0x0A, 0x0A,
+};
+static char video12[4] = {
+	0xBA, 0x24, 0x24, 0x24,
+};
+static char video13[4] = {
+	0xB9, 0x24, 0x24, 0x24,
+};
+static char video14[4] = {
+	0xB8, 0x24, 0x24, 0x24,
+};
+static char video15[6] = {
+	0xF0, 0x55, 0xAA, 0x52,
+	0x08, 0x00,
+};
+static char video16[2] = {
+	0xB3, 0x00,
+};
+static char video17[2] = {
+	0xB4, 0x10,
+};
+static char video18[2] = {
+	0xB6, 0x02,
+};
+static char video19[3] = {
+	0xB1, 0xFC, 0x06,
+};
+static char video20[4] = {
+	0xBC, 0x05, 0x05, 0x05,
+};
+static char video21[3] = {
+	0xB7, 0x20, 0x20,
+};
+static char video22[5] = {
+	0xB8, 0x01, 0x03, 0x03,
+	0x03,
+};
+static char video23[19] = {
+	0xC8, 0x01, 0x00, 0x78,
+	0x50, 0x78, 0x50, 0x78,
+	0x50, 0x78, 0x50, 0xC8,
+	0x3C, 0x3C, 0xC8, 0xC8,
+	0x3C, 0x3C, 0xC8,
+};
+static char video24[6] = {
+	0xBD, 0x01, 0x84, 0x07,
+	0x31, 0x00,
+};
+static char video25[6] = {
+	0xBE, 0x01, 0x84, 0x07,
+	0x31, 0x00,
+};
+static char video26[6] = {
+	0xBF, 0x01, 0x84, 0x07,
+	0x31, 0x00,
+};
+static char video27[2] = {
+	0x35, 0x00,
+};
+static struct dsi_cmd_desc nt35510_video_display_on_cmds[] = {
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video0), video0},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video1), video1},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video2), video2},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video3), video3},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video4), video4},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video5), video5},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video6), video6},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video7), video7},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video8), video8},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video9), video9},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video10), video10},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video11), video11},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video12), video12},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video13), video13},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video14), video14},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video15), video15},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video16), video16},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video17), video17},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video18), video18},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video19), video19},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video20), video20},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video21), video21},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video22), video22},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video23), video23},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video24), video24},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video25), video25},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video26), video26},
+	{DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video27), video27},
+	{DTYPE_DCS_WRITE, 1, 0, 0, NT35510_SLEEP_OFF_DELAY, sizeof(exit_sleep),
+			exit_sleep},
+	{DTYPE_DCS_WRITE, 1, 0, 0, NT35510_DISPLAY_ON_DELAY, sizeof(display_on),
+			display_on},
+};
+
+static int mipi_nt35510_lcd_on(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+	struct mipi_panel_info *mipi;
+
+	mfd = platform_get_drvdata(pdev);
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	mipi  = &mfd->panel_info.mipi;
+
+	if (mipi->mode == DSI_VIDEO_MODE) {
+		mipi_dsi_cmds_tx(mfd, &nt35510_tx_buf,
+			nt35510_video_display_on_cmds,
+			ARRAY_SIZE(nt35510_video_display_on_cmds));
+	} else if (mipi->mode == DSI_CMD_MODE) {
+		mipi_dsi_cmds_tx(mfd, &nt35510_tx_buf,
+			nt35510_cmd_display_on_cmds,
+			ARRAY_SIZE(nt35510_cmd_display_on_cmds));
+	}
+
+	return 0;
+}
+
+static int mipi_nt35510_lcd_off(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+
+	pr_debug("mipi_nt35510_lcd_off E\n");
+
+	mfd = platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return -ENODEV;
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	mipi_dsi_cmds_tx(mfd, &nt35510_tx_buf, nt35510_display_off_cmds,
+			ARRAY_SIZE(nt35510_display_off_cmds));
+
+	pr_debug("mipi_nt35510_lcd_off X\n");
+	return 0;
+}
+
+static int __devinit mipi_nt35510_lcd_probe(struct platform_device *pdev)
+{
+	pr_debug("%s\n", __func__);
+
+	if (pdev->id == 0) {
+		mipi_nt35510_pdata = pdev->dev.platform_data;
+		return 0;
+	}
+
+	msm_fb_add_device(pdev);
+
+	return 0;
+}
+
+static struct platform_driver this_driver = {
+	.probe  = mipi_nt35510_lcd_probe,
+	.driver = {
+		.name   = "mipi_NT35510",
+	},
+};
+
+static void mipi_nt35510_set_backlight(struct msm_fb_data_type *mfd)
+{
+	/* Add backlight changes later*/
+	return;
+}
+
+static struct msm_fb_panel_data nt35510_panel_data = {
+	.on	= mipi_nt35510_lcd_on,
+	.off = mipi_nt35510_lcd_off,
+	.set_backlight = mipi_nt35510_set_backlight,
+};
+
+static int ch_used[3];
+
+static int mipi_nt35510_lcd_init(void)
+{
+	mipi_dsi_buf_alloc(&nt35510_tx_buf, DSI_BUF_SIZE);
+	mipi_dsi_buf_alloc(&nt35510_rx_buf, DSI_BUF_SIZE);
+
+	return platform_driver_register(&this_driver);
+}
+int mipi_nt35510_device_register(struct msm_panel_info *pinfo,
+					u32 channel, u32 panel)
+{
+	struct platform_device *pdev = NULL;
+	int ret;
+
+	if ((channel >= 3) || ch_used[channel])
+		return -ENODEV;
+
+	ch_used[channel] = TRUE;
+
+	ret = mipi_nt35510_lcd_init();
+	if (ret) {
+		pr_err("mipi_nt35510_lcd_init() failed with ret %u\n", ret);
+		return ret;
+	}
+
+	pdev = platform_device_alloc("mipi_NT35510", (panel << 8)|channel);
+	if (!pdev)
+		return -ENOMEM;
+
+	nt35510_panel_data.panel_info = *pinfo;
+
+	ret = platform_device_add_data(pdev, &nt35510_panel_data,
+				sizeof(nt35510_panel_data));
+	if (ret) {
+		pr_debug("%s: platform_device_add_data failed!\n", __func__);
+		goto err_device_put;
+	}
+
+	ret = platform_device_add(pdev);
+	if (ret) {
+		pr_debug("%s: platform_device_register failed!\n", __func__);
+		goto err_device_put;
+	}
+
+	return 0;
+
+err_device_put:
+	platform_device_put(pdev);
+	return ret;
+}
diff --git a/drivers/video/msm/mipi_NT35510.h b/drivers/video/msm/mipi_NT35510.h
new file mode 100644
index 0000000..5c81875
--- /dev/null
+++ b/drivers/video/msm/mipi_NT35510.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MIPI_NT35510_H
+#define MIPI_NT35510_H
+
+int mipi_nt35510_device_register(struct msm_panel_info *pinfo,
+					u32 channel, u32 panel);
+
+#endif  /* MIPI_NT35510_H */
diff --git a/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c b/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
new file mode 100644
index 0000000..2c4ee3e
--- /dev/null
+++ b/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
@@ -0,0 +1,98 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_NT35510.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_cmd_mode_phy_db = {
+	/* DSI Bit Clock at 500 MHz, 2 lane, RGB888 */
+	/* regulator */
+	{0x03, 0x01, 0x01, 0x00},
+	/* timing   */
+	{0xb9, 0x8e, 0x1f, 0x00, 0x98, 0x9c, 0x22, 0x90,
+	0x18, 0x03, 0x04},
+	/* phy ctrl */
+	{0x7f, 0x00, 0x00, 0x00},
+	/* strength */
+	{0xbb, 0x02, 0x06, 0x00},
+	/* pll control */
+	{0x01, 0xec, 0x31, 0xd2, 0x00, 0x40, 0x37, 0x62,
+	0x01, 0x0f, 0x07,
+	0x05, 0x14, 0x03, 0x0, 0x0, 0x0, 0x20, 0x0, 0x02, 0x0},
+};
+
+static int mipi_cmd_nt35510_wvga_pt_init(void)
+{
+	int ret;
+
+	if (msm_fb_detect_client("mipi_cmd_nt35510_wvga"))
+		return 0;
+
+	pinfo.xres = 480;
+	pinfo.yres = 800;
+	pinfo.type = MIPI_CMD_PANEL;
+	pinfo.pdest = DISPLAY_1;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 24;
+	pinfo.lcdc.h_back_porch = 100;
+	pinfo.lcdc.h_front_porch = 100;
+	pinfo.lcdc.h_pulse_width = 8;
+	pinfo.lcdc.v_back_porch = 20;
+	pinfo.lcdc.v_front_porch = 20;
+	pinfo.lcdc.v_pulse_width = 1;
+
+	pinfo.lcdc.border_clr = 0;	/* blk */
+	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
+	pinfo.lcdc.hsync_skew = 0;
+	pinfo.bl_max = 100;
+	pinfo.bl_min = 1;
+	pinfo.fb_num = 2;
+
+	pinfo.clk_rate = 499000000;
+
+	pinfo.lcd.vsync_enable = TRUE;
+	pinfo.lcd.hw_vsync_mode = TRUE;
+	pinfo.lcd.refx100 = 6000; /* adjust refx100 to prevent tearing */
+
+	pinfo.mipi.mode = DSI_CMD_MODE;
+	pinfo.mipi.dst_format = DSI_CMD_DST_FORMAT_RGB888;
+	pinfo.mipi.vc = 0;
+	pinfo.mipi.rgb_swap = DSI_RGB_SWAP_RGB;
+	pinfo.mipi.data_lane0 = TRUE;
+	pinfo.mipi.data_lane1 = TRUE;
+	pinfo.mipi.t_clk_post = 0x20;
+	pinfo.mipi.t_clk_pre = 0x2F;
+	pinfo.mipi.stream = 0; /* dma_p */
+	pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_SW;
+	pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+	pinfo.mipi.te_sel = 1; /* TE from vsync gpio */
+	pinfo.mipi.interleave_max = 1;
+	pinfo.mipi.insert_dcs_cmd = TRUE;
+	pinfo.mipi.wr_mem_continue = 0x3c;
+	pinfo.mipi.wr_mem_start = 0x2c;
+	pinfo.mipi.dsi_phy_db = &dsi_cmd_mode_phy_db;
+	pinfo.mipi.tx_eot_append = 0x01;
+	pinfo.mipi.rx_eot_ignore = 0x0;
+	pinfo.mipi.dlane_swap = 0x01;
+
+	ret = mipi_nt35510_device_register(&pinfo, MIPI_DSI_PRIM,
+						MIPI_DSI_PANEL_WVGA_PT);
+	if (ret)
+		pr_err("%s: failed to register device!\n", __func__);
+
+	return ret;
+}
+
+module_init(mipi_cmd_nt35510_wvga_pt_init);
diff --git a/drivers/video/msm/mipi_NT35510_video_wvga_pt.c b/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
new file mode 100644
index 0000000..82e03b2
--- /dev/null
+++ b/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
@@ -0,0 +1,108 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_NT35510.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+	/* DSI Bit Clock at 500 MHz, 2 lane, RGB888 */
+	/* regulator */
+	{0x03, 0x01, 0x01, 0x00},
+	/* timing   */
+	{0xb9, 0x8e, 0x1f, 0x00, 0x98, 0x9c, 0x22, 0x90,
+	0x18, 0x03, 0x04},
+	/* phy ctrl */
+	{0x7f, 0x00, 0x00, 0x00},
+	/* strength */
+	{0xbb, 0x02, 0x06, 0x00},
+	/* pll control */
+	{0x00, 0xec, 0x31, 0xd2, 0x00, 0x40, 0x37, 0x62,
+	0x01, 0x0f, 0x07,
+	0x05, 0x14, 0x03, 0x0, 0x0, 0x0, 0x20, 0x0, 0x02, 0x0},
+};
+
+static int mipi_video_nt35510_wvga_pt_init(void)
+{
+	int ret;
+
+	if (msm_fb_detect_client("mipi_video_nt35510_wvga"))
+		return 0;
+
+	pinfo.xres = 480;
+	pinfo.yres = 800;
+	pinfo.type = MIPI_VIDEO_PANEL;
+	pinfo.pdest = DISPLAY_1;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 24;
+	pinfo.lcdc.h_back_porch = 100;
+	pinfo.lcdc.h_front_porch = 100;
+	pinfo.lcdc.h_pulse_width = 8;
+	pinfo.lcdc.v_back_porch = 20;
+	pinfo.lcdc.v_front_porch = 20;
+	pinfo.lcdc.v_pulse_width = 1;
+	pinfo.lcdc.border_clr = 0;	/* blk */
+	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
+	/* number of dot_clk cycles HSYNC active edge is
+	delayed from VSYNC active edge */
+	pinfo.lcdc.hsync_skew = 0;
+	pinfo.clk_rate = 499000000;
+	pinfo.bl_max = 100; /*16; CHECK THIS!!!*/
+	pinfo.bl_min = 1;
+	pinfo.fb_num = 2;
+
+	pinfo.mipi.mode = DSI_VIDEO_MODE;
+	/* send HSA and HE following VS/VE packet */
+	pinfo.mipi.pulse_mode_hsa_he = TRUE;
+	pinfo.mipi.hfp_power_stop = TRUE; /* LP-11 during the HFP period */
+	pinfo.mipi.hbp_power_stop = TRUE; /* LP-11 during the HBP period */
+	pinfo.mipi.hsa_power_stop = TRUE; /* LP-11 during the HSA period */
+	/* LP-11 or let Command Mode Engine send packets in
+	HS or LP mode for the BLLP of the last line of a frame */
+	pinfo.mipi.eof_bllp_power_stop = TRUE;
+	/* LP-11 or let Command Mode Engine send packets in
+	HS or LP mode for packets sent during BLLP period */
+	pinfo.mipi.bllp_power_stop = TRUE;
+
+	pinfo.mipi.traffic_mode = DSI_BURST_MODE;
+	pinfo.mipi.dst_format =  DSI_VIDEO_DST_FORMAT_RGB888;
+	pinfo.mipi.vc = 0;
+	pinfo.mipi.rgb_swap = DSI_RGB_SWAP_RGB; /* RGB */
+	pinfo.mipi.data_lane0 = TRUE;
+	pinfo.mipi.data_lane1 = TRUE;
+
+	pinfo.mipi.t_clk_post = 0x20;
+	pinfo.mipi.t_clk_pre = 0x2f;
+
+	pinfo.mipi.stream = 0; /* dma_p */
+	pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_NONE;
+	pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+	pinfo.mipi.frame_rate = 60; /* FIXME */
+
+	pinfo.mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+	pinfo.mipi.dlane_swap = 0x01;
+	/* append EOT at the end of data burst */
+	pinfo.mipi.tx_eot_append = 0x01;
+
+	ret = mipi_nt35510_device_register(&pinfo, MIPI_DSI_PRIM,
+						MIPI_DSI_PANEL_WVGA_PT);
+
+	if (ret)
+		pr_err("%s: failed to register device!\n", __func__);
+
+	return ret;
+}
+
+module_init(mipi_video_nt35510_wvga_pt_init);
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
index aa210f1..f319072 100644
--- a/drivers/video/msm/mipi_dsi.c
+++ b/drivers/video/msm/mipi_dsi.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
@@ -196,8 +196,8 @@
 
 	mipi  = &mfd->panel_info.mipi;
 	if (mfd->panel_info.type == MIPI_VIDEO_PANEL) {
-		dummy_xres = mfd->panel_info.mipi.xres_pad;
-		dummy_yres = mfd->panel_info.mipi.yres_pad;
+		dummy_xres = mfd->panel_info.lcdc.xres_pad;
+		dummy_yres = mfd->panel_info.lcdc.yres_pad;
 
 		if (mdp_rev >= MDP_REV_41) {
 			MIPI_OUTP(MIPI_DSI_BASE + 0x20,
@@ -539,8 +539,8 @@
 
 	if (mfd->panel_info.type == MIPI_VIDEO_PANEL &&
 		!mfd->panel_info.clk_rate) {
-		h_period += mfd->panel_info.mipi.xres_pad;
-		v_period += mfd->panel_info.mipi.yres_pad;
+		h_period += mfd->panel_info.lcdc.xres_pad;
+		v_period += mfd->panel_info.lcdc.yres_pad;
 
 		if (lanes > 0) {
 			mfd->panel_info.clk_rate =
diff --git a/drivers/video/msm/mipi_novatek.c b/drivers/video/msm/mipi_novatek.c
index caa4114..ed0dee4 100644
--- a/drivers/video/msm/mipi_novatek.c
+++ b/drivers/video/msm/mipi_novatek.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -461,6 +461,7 @@
 	struct mipi_panel_info *mipi;
 	struct platform_device *current_pdev;
 	static struct mipi_dsi_phy_ctrl *phy_settings;
+	static char dlane_swap;
 
 	if (pdev->id == 0) {
 		mipi_novatek_pdata = pdev->dev.platform_data;
@@ -471,6 +472,11 @@
 		}
 
 		if (mipi_novatek_pdata
+			&& mipi_novatek_pdata->dlane_swap) {
+			dlane_swap = (mipi_novatek_pdata->dlane_swap);
+		}
+
+		if (mipi_novatek_pdata
 			 && mipi_novatek_pdata->fpga_3d_config_addr)
 			mipi_novatek_3d_init(mipi_novatek_pdata
 	->fpga_3d_config_addr, mipi_novatek_pdata->fpga_ctrl_mode);
@@ -499,6 +505,9 @@
 
 		if (phy_settings != NULL)
 			mipi->dsi_phy_db = phy_settings;
+
+		if (dlane_swap)
+			mipi->dlane_swap = dlane_swap;
 	}
 	return 0;
 }
diff --git a/drivers/video/msm/mipi_tc358764_dsi2lvds.c b/drivers/video/msm/mipi_tc358764_dsi2lvds.c
index 8055bd0..fcb5163 100644
--- a/drivers/video/msm/mipi_tc358764_dsi2lvds.c
+++ b/drivers/video/msm/mipi_tc358764_dsi2lvds.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -68,7 +68,9 @@
 #include <linux/i2c.h>
 #include <linux/delay.h>
 #include <linux/pwm.h>
+#include <linux/gpio.h>
 #include "msm_fb.h"
+#include "mdp4.h"
 #include "mipi_dsi.h"
 #include "mipi_tc358764_dsi2lvds.h"
 
@@ -186,7 +188,11 @@
 #define DEBUG01		0x05A4	/* LVDS Data */
 
 /* PWM */
-#define PWM_FREQ_HZ	(66*1000)	/* 66 KHZ */
+static u32 d2l_pwm_freq_hz = (66*1000);
+
+/* 1366x768 uses pwm at 66 KHZ */
+/* 1200x1920 uses pwm at 25 KHZ */
+#define PWM_FREQ_HZ	(d2l_pwm_freq_hz)
 #define PWM_LEVEL 15
 #define PWM_PERIOD_USEC (USEC_PER_SEC / PWM_FREQ_HZ)
 #define PWM_DUTY_LEVEL (PWM_PERIOD_USEC / PWM_LEVEL)
@@ -213,10 +219,17 @@
 static struct dsi_buf d2l_rx_buf;
 static int led_pwm;
 static struct pwm_device *bl_pwm;
+static struct pwm_device *tn_pwm;
 static int bl_level;
 static u32 d2l_gpio_out_mask;
 static u32 d2l_gpio_out_val;
+static u32 d2l_3d_gpio_enable;
+static u32 d2l_3d_gpio_mode;
+static int d2l_enable_3d;
+
 static int mipi_d2l_init(void);
+static int mipi_d2l_enable_3d(struct msm_fb_data_type *mfd,
+			      bool enable, bool mode);
 
 /**
  * Read a bridge register
@@ -236,7 +249,7 @@
 	mipi_dsi_buf_init(&d2l_tx_buf);
 	mipi_dsi_buf_init(&d2l_rx_buf);
 
-	/* mutex had been acquried at dsi_on */
+	/* mutex had been acquired at mipi_dsi_on */
 	len = mipi_dsi_cmds_rx(mfd, &d2l_tx_buf, &d2l_rx_buf,
 			       &cmd_read_reg, len);
 
@@ -247,7 +260,6 @@
 
 	pr_debug("%s: reg=0x%x.data=0x%08x.\n", __func__, reg, data);
 
-
 	return data;
 }
 
@@ -256,9 +268,9 @@
  *
  * @param mfd
  *
- * @return register data value
+ * @return int
  */
-static u32 mipi_d2l_write_reg(struct msm_fb_data_type *mfd, u16 reg, u32 data)
+static int mipi_d2l_write_reg(struct msm_fb_data_type *mfd, u16 reg, u32 data)
 {
 	struct wr_cmd_payload payload;
 	struct dsi_cmd_desc cmd_write_reg = {
@@ -268,35 +280,25 @@
 	payload.addr = reg;
 	payload.data = data;
 
-	/* mutex had been acquried at dsi_on */
+	/* mutex had been acquired at mipi_dsi_on */
 	mipi_dsi_cmds_tx(mfd, &d2l_tx_buf, &cmd_write_reg, 1);
 
 	pr_debug("%s: reg=0x%x. data=0x%x.\n", __func__, reg, data);
 
-	return data;
+	return 0;
 }
 
-/*
+static void mipi_d2l_read_status(struct msm_fb_data_type *mfd)
+{
+	mipi_d2l_read_reg(mfd, DSI_LANESTATUS0);	/* 0x214 */
+	mipi_d2l_read_reg(mfd, DSI_LANESTATUS1);	/* 0x218 */
+	mipi_d2l_read_reg(mfd, DSI_INTSTATUS);		/* 0x220 */
+	mipi_d2l_read_reg(mfd, SYSSTAT);		/* 0x500 */
+}
+
+/**
  * Init the D2L bridge via the DSI interface for Video.
  *
- *	Register		Addr	Value
- *  ===================================================
- *  PPI_TX_RX_TA		0x013C	0x00040004
- *  PPI_LPTXTIMECNT	        0x0114	0x00000004
- *  PPI_D0S_CLRSIPOCOUNT	0x0164	0x00000003
- *  PPI_D1S_CLRSIPOCOUNT	0x0168	0x00000003
- *  PPI_D2S_CLRSIPOCOUNT	0x016C	0x00000003
- *  PPI_D3S_CLRSIPOCOUNT	0x0170	0x00000003
- *  PPI_LANEENABLE	        0x0134	0x0000001F
- *  DSI_LANEENABLE	        0x0210	0x0000001F
- *  PPI_STARTPPI	        0x0104	0x00000001
- *  DSI_STARTDSI	        0x0204	0x00000001
- *  VPCTRL			0x0450	0x01000120
- *  HTIM1			0x0454	0x002C0028
- *  VTIM1			0x045C	0x001E0008
- *  VFUEN			0x0464	0x00000001
- *  LVCFG			0x049C	0x00000001
- *
  * VPCTRL.EVTMODE (0x20) configuration bit is needed to determine whether
  * video timing information is delivered in pulse mode or event mode.
  * In pulse mode, both Sync Start and End packets are required.
@@ -304,15 +306,22 @@
  *
  * @param mfd
  *
- * @return register data value
+ * @return int
  */
 static int mipi_d2l_dsi_init_sequence(struct msm_fb_data_type *mfd)
 {
 	struct mipi_panel_info *mipi = &mfd->panel_info.mipi;
 	u32 lanes_enable;
 	u32 vpctrl;
-	u32 htime1 = 0x002C0028;
-	u32 vtime1 = 0x001E0008;
+	u32 htime1;
+	u32 vtime1;
+	u32 ppi_tx_rx_ta; /* BTA Bus-Turn-Around */
+	u32 lvcfg;
+	u32 hbpr;	/* Horizontal Back Porch */
+	u32 hpw;	/* Horizontal Pulse Width */
+	u32 vbpr;	/* Vertical Back Porch */
+	u32 vpw;	/* Vertical Pulse Width */
+	bool vesa_rgb888 = false;
 
 	lanes_enable = 0x01; /* clock-lane enable */
 	lanes_enable |= (mipi->data_lane0 << 1);
@@ -330,25 +339,57 @@
 		return -EINVAL;
 	}
 
+	if (mfd->panel_info.clk_rate > 800*1000*1000) {
+		pr_err("%s.unsupported clk_rate %d.\n",
+		       __func__, mfd->panel_info.clk_rate);
+		return -EINVAL;
+	}
+
+	pr_debug("%s.xres=%d.yres=%d.\n",
+		__func__, mfd->panel_info.xres, mfd->panel_info.yres);
+
+	hbpr = mfd->panel_info.lcdc.h_back_porch;
+	hpw	= mfd->panel_info.lcdc.h_pulse_width;
+	vbpr = mfd->panel_info.lcdc.v_back_porch;
+	vpw	= mfd->panel_info.lcdc.v_pulse_width;
+
+	htime1 = (hbpr << 16) + hpw;
+	vtime1 = (vbpr << 16) + vpw;
+	lvcfg = 0x0003; /* PCLK=DCLK/3, Dual Link, LVEN */
+	vpctrl = 0x01000120; /* Output RGB888 , Event-Mode , */
+	ppi_tx_rx_ta = 0x00040004;
+
+	if (mfd->panel_info.xres == 1366) {
+		ppi_tx_rx_ta = 0x00040004;
+		lvcfg = 0x01; /* LVEN */
+		vesa_rgb888 = true;
+	}
+
+	if (mfd->panel_info.xres == 1200) {
+		lvcfg = 0x0103; /* PCLK=DCLK/4, Dual Link, LVEN */
+		vesa_rgb888 = true;
+	}
+
 	pr_debug("%s.htime1=0x%x.\n", __func__, htime1);
 	pr_debug("%s.vtime1=0x%x.\n", __func__, vtime1);
 	pr_debug("%s.vpctrl=0x%x.\n", __func__, vpctrl);
-	pr_debug("%s.lanes_enable=0x%x.\n", __func__, lanes_enable);
-
+	pr_debug("%s.lvcfg=0x%x.\n", __func__, lvcfg);
 
 	mipi_d2l_write_reg(mfd, SYSRST, 0xFF);
 	msleep(30);
 
-	/* VESA format instead of JEIDA format for RGB888 */
-	mipi_d2l_write_reg(mfd, LVMX0003, 0x03020100);
-	mipi_d2l_write_reg(mfd, LVMX0407, 0x08050704);
-	mipi_d2l_write_reg(mfd, LVMX0811, 0x0F0E0A09);
-	mipi_d2l_write_reg(mfd, LVMX1215, 0x100D0C0B);
-	mipi_d2l_write_reg(mfd, LVMX1619, 0x12111716);
-	mipi_d2l_write_reg(mfd, LVMX2023, 0x1B151413);
-	mipi_d2l_write_reg(mfd, LVMX2427, 0x061A1918);
+	if (vesa_rgb888) {
+		/* VESA format instead of JEIDA format for RGB888 */
+		mipi_d2l_write_reg(mfd, LVMX0003, 0x03020100);
+		mipi_d2l_write_reg(mfd, LVMX0407, 0x08050704);
+		mipi_d2l_write_reg(mfd, LVMX0811, 0x0F0E0A09);
+		mipi_d2l_write_reg(mfd, LVMX1215, 0x100D0C0B);
+		mipi_d2l_write_reg(mfd, LVMX1619, 0x12111716);
+		mipi_d2l_write_reg(mfd, LVMX2023, 0x1B151413);
+		mipi_d2l_write_reg(mfd, LVMX2427, 0x061A1918);
+	}
 
-	mipi_d2l_write_reg(mfd, PPI_TX_RX_TA, 0x00040004); /* BTA */
+	mipi_d2l_write_reg(mfd, PPI_TX_RX_TA, ppi_tx_rx_ta); /* BTA */
 	mipi_d2l_write_reg(mfd, PPI_LPTXTIMECNT, 0x00000004);
 	mipi_d2l_write_reg(mfd, PPI_D0S_CLRSIPOCOUNT, 0x00000003);
 	mipi_d2l_write_reg(mfd, PPI_D1S_CLRSIPOCOUNT, 0x00000003);
@@ -363,7 +404,7 @@
 	mipi_d2l_write_reg(mfd, HTIM1, htime1);
 	mipi_d2l_write_reg(mfd, VTIM1, vtime1);
 	mipi_d2l_write_reg(mfd, VFUEN, 0x00000001);
-	mipi_d2l_write_reg(mfd, LVCFG, 0x00000001); /* Enables LVDS tx */
+	mipi_d2l_write_reg(mfd, LVCFG, lvcfg); /* Enables LVDS tx */
 
 	return 0;
 }
@@ -400,6 +441,35 @@
 		return ret;
 	}
 
+	return 0;
+}
+
+/**
+ * Set TN CLK.
+ *
+ * @param pwm
+ * @param level
+ *
+ * @return int
+ */
+static int mipi_d2l_set_tn_clk(struct pwm_device *pwm, u32 usec)
+{
+	int ret = 0;
+
+	pr_debug("%s: usec=%d.\n", __func__, usec);
+
+	ret = pwm_config(pwm, usec/2 , usec);
+	if (ret) {
+		pr_err("%s: pwm_config() failed err=%d.\n", __func__, ret);
+		return ret;
+	}
+
+	ret = pwm_enable(pwm);
+	if (ret) {
+		pr_err("%s: pwm_enable() failed err=%d\n",
+		       __func__, ret);
+		return ret;
+	}
 
 	return 0;
 }
@@ -446,9 +516,14 @@
 		return ret;
 
 	mipi_d2l_write_reg(mfd, GPIOC, d2l_gpio_out_mask);
-	/* Set GPIOs: gpio#4=U/D=0 , gpio#3=L/R=1 , gpio#2,1=CABC=0. */
+	/* Set gpio#4=U/D=0, gpio#3=L/R=1 , gpio#2,1=CABC=0, gpio#0=NA. */
 	mipi_d2l_write_reg(mfd, GPIOO, d2l_gpio_out_val);
 
+	if (mfd->panel_info.xres == 1366)
+		d2l_pwm_freq_hz = (66*1000);
+	else
+		d2l_pwm_freq_hz = (25*1000);
+
 	if (bl_level == 0)
 		bl_level = PWM_LEVEL * 2 / 3 ; /* Default ON value */
 
@@ -460,6 +535,10 @@
 			       __func__, ret);
 	}
 
+	mipi_d2l_read_status(mfd);
+
+	mipi_d2l_enable_3d(mfd, false, false);
+
 	pr_info("%s.ret=%d.\n", __func__, ret);
 
 	return ret;
@@ -510,6 +589,98 @@
 	.set_backlight = mipi_d2l_set_backlight,
 };
 
+static int mipi_d2l_enable_3d(struct msm_fb_data_type *mfd,
+			      bool enable, bool mode)
+{
+	u32 tn_usec = 1000000 / 66; /* 66 HZ */
+
+	pr_debug("%s.enable=%d.mode=%d.\n", __func__, enable, mode);
+
+	gpio_direction_output(d2l_3d_gpio_enable, enable);
+	gpio_direction_output(d2l_3d_gpio_mode, mode);
+
+	mipi_d2l_set_tn_clk(tn_pwm, tn_usec);
+
+	return 0;
+}
+
+static ssize_t mipi_d2l_enable_3d_read(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	return snprintf((char *)buf, sizeof(buf), "%u\n", d2l_enable_3d);
+}
+
+static ssize_t mipi_d2l_enable_3d_write(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf,
+				size_t count)
+{
+	int ret = -1;
+	u32 data = 0;
+
+	if (sscanf((char *)buf, "%u", &data) != 1) {
+		dev_err(dev, "%s. Invalid input.\n", __func__);
+		ret = -EINVAL;
+	} else {
+		d2l_enable_3d = data;
+		if (data == 1) /* LANDSCAPE */
+			mipi_d2l_enable_3d(d2l_mfd, true, true);
+		else if (data == 2) /* PORTRAIT */
+			mipi_d2l_enable_3d(d2l_mfd, true, false);
+		else if (data == 0)
+			mipi_d2l_enable_3d(d2l_mfd, false, false);
+		else
+			pr_err("%s.Invalid value=%d.\n", __func__, data);
+	}
+
+	return count;
+}
+
+static struct device_attribute mipi_d2l_3d_barrier_attributes[] = {
+	__ATTR(enable_3d_barrier, 0666,
+	       mipi_d2l_enable_3d_read,
+	       mipi_d2l_enable_3d_write),
+};
+
+static int mipi_dsi_3d_barrier_sysfs_register(struct device *dev)
+{
+	int ret;
+
+	pr_debug("%s.d2l_3d_gpio_enable=%d.\n", __func__, d2l_3d_gpio_enable);
+	pr_debug("%s.d2l_3d_gpio_mode=%d.\n", __func__, d2l_3d_gpio_mode);
+
+	ret  = device_create_file(dev, mipi_d2l_3d_barrier_attributes);
+	if (ret) {
+		pr_err("%s.failed to create 3D sysfs.\n", __func__);
+		goto err_device_create_file;
+	}
+
+	ret = gpio_request(d2l_3d_gpio_enable, "d2l_3d_gpio_enable");
+	if (ret) {
+		pr_err("%s.failed to get d2l_3d_gpio_enable=%d.\n",
+		       __func__, d2l_3d_gpio_enable);
+		goto err_d2l_3d_gpio_enable;
+	}
+
+	ret = gpio_request(d2l_3d_gpio_mode, "d2l_3d_gpio_mode");
+	if (ret) {
+		pr_err("%s.failed to get d2l_3d_gpio_mode=%d.\n",
+		       __func__, d2l_3d_gpio_mode);
+		goto err_d2l_3d_gpio_mode;
+	}
+
+	return 0;
+
+err_d2l_3d_gpio_mode:
+	gpio_free(d2l_3d_gpio_enable);
+err_d2l_3d_gpio_enable:
+	device_remove_file(dev, mipi_d2l_3d_barrier_attributes);
+err_device_create_file:
+
+	return ret;
+}
+
 /**
  * Probe for device.
  *
@@ -530,7 +701,6 @@
 	pr_debug("%s.id=%d.\n", __func__, pdev->id);
 
 	if (pdev->id == 0) {
-		/* d2l_common_pdata = platform_get_drvdata(pdev); */
 		d2l_common_pdata = pdev->dev.platform_data;
 
 		if (d2l_common_pdata == NULL) {
@@ -541,6 +711,8 @@
 		led_pwm = d2l_common_pdata->gpio_num[0];
 		d2l_gpio_out_mask = d2l_common_pdata->gpio_num[1] >> 8;
 		d2l_gpio_out_val = d2l_common_pdata->gpio_num[1] & 0xFF;
+		d2l_3d_gpio_enable = d2l_common_pdata->gpio_num[2];
+		d2l_3d_gpio_mode = d2l_common_pdata->gpio_num[3];
 
 		mipi_dsi_buf_alloc(&d2l_tx_buf, DSI_BUF_SIZE);
 		mipi_dsi_buf_alloc(&d2l_rx_buf, DSI_BUF_SIZE);
@@ -567,10 +739,20 @@
 
 		}
 	} else {
-		pr_info("%s. led_pwm is invalid.\n", __func__);
+		pr_err("%s. led_pwm is invalid.\n", __func__);
 	}
 
-	/* pinfo = platform_get_drvdata(pdev); */
+	tn_pwm = pwm_request(1, "3D_TN_clk");
+	if (tn_pwm == NULL || IS_ERR(tn_pwm)) {
+		pr_err("%s pwm_request() failed.id=%d.tn_pwm=%d.\n",
+		       __func__, 1, (int) tn_pwm);
+		tn_pwm = NULL;
+		return -EIO;
+	} else {
+		pr_debug("%s.pwm_request() ok.pwm-id=%d.\n", __func__, 1);
+
+	}
+
 	pinfo = pdev->dev.platform_data;
 
 	if (pinfo == NULL) {
@@ -584,6 +766,9 @@
 
 	msm_fb_add_device(pdev);
 
+	if (pinfo->is_3d_panel)
+		mipi_dsi_3d_barrier_sysfs_register(&(pdev->dev));
+
 	return ret;
 }
 
@@ -667,6 +852,7 @@
 static int mipi_d2l_init(void)
 {
 	pr_debug("%s.\n", __func__);
+
 	return platform_driver_register(&d2l_driver);
 }
 
diff --git a/drivers/video/msm/mipi_toshiba_video_wsvga_pt.c b/drivers/video/msm/mipi_toshiba_video_wsvga_pt.c
index 2c02490..48bdb1d 100644
--- a/drivers/video/msm/mipi_toshiba_video_wsvga_pt.c
+++ b/drivers/video/msm/mipi_toshiba_video_wsvga_pt.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
@@ -49,8 +49,8 @@
 	 * include dummy(pad) data of 200 clk in addition to
 	 * width and porch/sync width values
 	 */
-	pinfo.mipi.xres_pad = 200;
-	pinfo.mipi.yres_pad = 0;
+	pinfo.lcdc.xres_pad = 200;
+	pinfo.lcdc.yres_pad = 0;
 
 	pinfo.type = MIPI_VIDEO_PANEL;
 	pinfo.pdest = DISPLAY_1;
diff --git a/drivers/video/msm/msm_dss_io_8960.c b/drivers/video/msm/msm_dss_io_8960.c
index 52a10ab..3b000ec 100644
--- a/drivers/video/msm/msm_dss_io_8960.c
+++ b/drivers/video/msm/msm_dss_io_8960.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
@@ -643,9 +643,6 @@
 
 	HDMI_OUTP(HDMI_PHY_REG_0, 0x1B);
 	HDMI_OUTP(HDMI_PHY_REG_1, 0xf2);
-	HDMI_OUTP(HDMI_PHY_REG_2, 0x7F);
-	HDMI_OUTP(HDMI_PHY_REG_2, 0x3F);
-	HDMI_OUTP(HDMI_PHY_REG_2, 0x1F);
 
 	offset = HDMI_PHY_REG_4;
 	while (offset <= HDMI_PHY_REG_11) {
@@ -653,12 +650,7 @@
 		offset += 0x4;
 	}
 
-	HDMI_OUTP(HDMI_PHY_REG_12, HDMI_INP(HDMI_PHY_REG_12) | PWRDN_B);
-	msleep(100);
-
 	HDMI_OUTP(HDMI_PHY_REG_3, 0x20);
-	HDMI_OUTP(HDMI_PHY_REG_12, 0x81);
-	HDMI_OUTP(HDMI_PHY_REG_2, 0x81);
 }
 
 void hdmi_msm_powerdown_phy(void)
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 89ccbb9..42fa2ba 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -270,6 +270,9 @@
 	case HDMI_PANEL:
 		ret = snprintf(buf, PAGE_SIZE, "hdmi panel\n");
 		break;
+	case LVDS_PANEL:
+		ret = snprintf(buf, PAGE_SIZE, "lvds panel\n");
+		break;
 	case DTV_PANEL:
 		ret = snprintf(buf, PAGE_SIZE, "dtv panel\n");
 		break;
@@ -603,10 +606,42 @@
 	return 0;
 }
 
+static int msm_fb_ext_suspend(struct device *dev)
+{
+	struct msm_fb_data_type *mfd = dev_get_drvdata(dev);
+	int ret = 0;
+
+	if ((!mfd) || (mfd->key != MFD_KEY))
+		return 0;
+
+	if (mfd->panel_info.type == HDMI_PANEL ||
+		mfd->panel_info.type == DTV_PANEL)
+		ret = msm_fb_suspend_sub(mfd);
+
+	return ret;
+}
+
+static int msm_fb_ext_resume(struct device *dev)
+{
+	struct msm_fb_data_type *mfd = dev_get_drvdata(dev);
+	int ret = 0;
+
+	if ((!mfd) || (mfd->key != MFD_KEY))
+		return 0;
+
+	if (mfd->panel_info.type == HDMI_PANEL ||
+		mfd->panel_info.type == DTV_PANEL)
+		ret = msm_fb_resume_sub(mfd);
+
+	return ret;
+}
+
 static struct dev_pm_ops msm_fb_dev_pm_ops = {
 	.runtime_suspend = msm_fb_runtime_suspend,
 	.runtime_resume = msm_fb_runtime_resume,
 	.runtime_idle = msm_fb_runtime_idle,
+	.suspend = msm_fb_ext_suspend,
+	.resume = msm_fb_ext_resume,
 };
 
 static struct platform_driver msm_fb_driver = {
@@ -3113,6 +3148,9 @@
 		break;
 
 	case MSMFB_HISTOGRAM_START:
+		if (!mfd->panel_power_on)
+			return -EPERM;
+
 		if (!mfd->do_histogram)
 			return -ENODEV;
 		ret = mdp_start_histogram(info);
diff --git a/drivers/video/msm/msm_fb_panel.c b/drivers/video/msm/msm_fb_panel.c
index d8eaea2..8640116 100644
--- a/drivers/video/msm/msm_fb_panel.c
+++ b/drivers/video/msm/msm_fb_panel.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2010, 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
@@ -106,6 +106,10 @@
 		snprintf(dev_name, sizeof(dev_name), "lcdc");
 		break;
 
+	case LVDS_PANEL:
+		snprintf(dev_name, sizeof(dev_name), "lvds");
+		break;
+
 	case DTV_PANEL:
 		snprintf(dev_name, sizeof(dev_name), "dtv");
 		break;
diff --git a/drivers/video/msm/msm_fb_panel.h b/drivers/video/msm/msm_fb_panel.h
index d66d802..903c865 100644
--- a/drivers/video/msm/msm_fb_panel.h
+++ b/drivers/video/msm/msm_fb_panel.h
@@ -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
@@ -38,6 +38,7 @@
 #define MIPI_VIDEO_PANEL	8	/* MIPI */
 #define MIPI_CMD_PANEL		9	/* MIPI */
 #define WRITEBACK_PANEL		10	/* Wifi display */
+#define LVDS_PANEL		11	/* LVDS */
 
 /* panel class */
 typedef enum {
@@ -77,6 +78,10 @@
 	__u32 border_clr;
 	__u32 underflow_clr;
 	__u32 hsync_skew;
+	/* Pad width */
+	uint32 xres_pad;
+	/* Pad height */
+	uint32 yres_pad;
 };
 
 struct mddi_panel_info {
@@ -127,10 +132,17 @@
 	char no_max_pkt_size;
 	/* Clock required during LP commands */
 	char force_clk_lane_hs;
-	/* Pad width */
-	uint32 xres_pad;
-	/* Pad height */
-	uint32 yres_pad;
+};
+
+enum lvds_mode {
+	LVDS_SINGLE_CHANNEL_MODE,
+	LVDS_DUAL_CHANNEL_MODE,
+};
+
+struct lvds_panel_info {
+	enum lvds_mode channel_mode;
+	/* Channel swap in dual mode */
+	char channel_swap;
 };
 
 struct msm_panel_info {
@@ -156,8 +168,8 @@
 	struct mddi_panel_info mddi;
 	struct lcd_panel_info lcd;
 	struct lcdc_panel_info lcdc;
-
 	struct mipi_panel_info mipi;
+	struct lvds_panel_info lvds;
 };
 
 #define MSM_FB_SINGLE_MODE_PANEL(pinfo)		\
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
index d54c01e..75df48d 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -10,10 +10,12 @@
  * GNU General Public License for more details.
  *
  */
+#include <linux/ion.h>
 #include <mach/msm_memtypes.h>
 #include "vcd_ddl.h"
 #include "vcd_ddl_shared_mem.h"
 
+
 struct ddl_context *ddl_get_context(void)
 {
 	static struct ddl_context ddl_context;
@@ -253,6 +255,15 @@
 				memset(frame[i].vcd_frm.virtual + luma_size,
 					 0x80808080,
 					frame[i].vcd_frm.alloc_len - luma_size);
+				if (frame[i].vcd_frm.ion_flag == CACHED) {
+					clean_and_invalidate_caches(
+					(unsigned long)frame[i].
+					vcd_frm.virtual,
+					(unsigned long)frame[i].
+					vcd_frm.alloc_len,
+					(unsigned long)frame[i].
+					vcd_frm.physical);
+				}
 			} else {
 				DDL_MSG_ERROR("luma size error");
 				return VCD_ERR_FAIL;
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/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index 795d1e3..c32ac81 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -255,11 +255,11 @@
 		VCDRES_MSG_LOW("%s(): Enabling the clocks\n", __func__);
 		if (resource_context.vcodec_clk &&
 			resource_context.vcodec_pclk) {
-			if (clk_enable(resource_context.vcodec_pclk)) {
+			if (clk_prepare_enable(resource_context.vcodec_pclk)) {
 				VCDRES_MSG_ERROR("vidc pclk Enable fail\n");
 				goto bail_out;
 			}
-			if (clk_enable(resource_context.vcodec_clk)) {
+			if (clk_prepare_enable(resource_context.vcodec_clk)) {
 				VCDRES_MSG_ERROR("vidc core clk Enable fail\n");
 				goto vidc_disable_pclk;
 			}
@@ -275,7 +275,7 @@
 	mutex_unlock(&resource_context.lock);
 	return true;
 vidc_disable_pclk:
-	clk_disable(resource_context.vcodec_pclk);
+	clk_disable_unprepare(resource_context.vcodec_pclk);
 bail_out:
 	mutex_unlock(&resource_context.lock);
 	return false;
@@ -322,9 +322,9 @@
 		VCDRES_MSG_LOW("%s(): Disabling the clocks ...\n", __func__);
 		resource_context.clock_enabled = 0;
 		if (resource_context.vcodec_clk)
-			clk_disable(resource_context.vcodec_clk);
+			clk_disable_unprepare(resource_context.vcodec_clk);
 		if (resource_context.vcodec_pclk)
-			clk_disable(resource_context.vcodec_pclk);
+			clk_disable_unprepare(resource_context.vcodec_pclk);
 		status = true;
 	}
 	mutex_unlock(&resource_context.lock);
@@ -696,7 +696,7 @@
 			ret = PTR_ERR(vidc_mmu_clks[i].mmu_clk);
 		}
 		if (!ret) {
-			ret = clk_enable(vidc_mmu_clks[i].mmu_clk);
+			ret = clk_prepare_enable(vidc_mmu_clks[i].mmu_clk);
 			if (ret) {
 				clk_put(vidc_mmu_clks[i].mmu_clk);
 				vidc_mmu_clks[i].mmu_clk = NULL;
@@ -704,7 +704,7 @@
 		}
 		if (ret) {
 			for (i--; i >= 0; i--) {
-				clk_disable(vidc_mmu_clks[i].mmu_clk);
+				clk_disable_unprepare(vidc_mmu_clks[i].mmu_clk);
 				clk_put(vidc_mmu_clks[i].mmu_clk);
 				vidc_mmu_clks[i].mmu_clk = NULL;
 			}
@@ -725,7 +725,7 @@
 	}
 	resource_context.mmu_clks_on = 0;
 	for (i = 0; i < ARRAY_SIZE(vidc_mmu_clks); i++) {
-		clk_disable(vidc_mmu_clks[i].mmu_clk);
+		clk_disable_unprepare(vidc_mmu_clks[i].mmu_clk);
 		clk_put(vidc_mmu_clks[i].mmu_clk);
 		vidc_mmu_clks[i].mmu_clk = NULL;
 	}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
index e17107e..eb08b7e 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -353,6 +353,10 @@
 	case INVALID_MMCO:
 	case INVALID_PIC_REORDERING:
 	case INVALID_POC_TYPE:
+		{
+			vcd_status = VCD_ERR_BITSTREAM_ERR;
+			break;
+		}
 	case ACTIVE_SPS_NOT_PRESENT:
 	case ACTIVE_PPS_NOT_PRESENT:
 		{
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
index 7c3325a..522ff16 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
@@ -92,17 +92,17 @@
 			goto bail_out;
 		}
 
-		if (clk_enable(resource_context.pclk)) {
+		if (clk_prepare_enable(resource_context.pclk)) {
 			VCDRES_MSG_ERROR("vidc pclk Enable failed\n");
 			goto bail_out;
 		}
 
-		if (clk_enable(resource_context.hclk)) {
+		if (clk_prepare_enable(resource_context.hclk)) {
 			VCDRES_MSG_ERROR("vidc hclk Enable failed\n");
 			goto disable_pclk;
 		}
 
-		if (clk_enable(resource_context.hclk_div2)) {
+		if (clk_prepare_enable(resource_context.hclk_div2)) {
 			VCDRES_MSG_ERROR("vidc hclk_div2 Enable failed\n");
 			goto disable_hclk;
 		}
@@ -120,9 +120,9 @@
 	}
 	msleep(20);
 
-	clk_disable(resource_context.pclk);
-	clk_disable(resource_context.hclk);
-	clk_disable(resource_context.hclk_div2);
+	clk_disable_unprepare(resource_context.pclk);
+	clk_disable_unprepare(resource_context.hclk);
+	clk_disable_unprepare(resource_context.hclk_div2);
 
 	clk_put(resource_context.hclk_div2);
 	clk_put(resource_context.hclk);
@@ -144,9 +144,9 @@
 	return true;
 
 disable_hclk:
-	clk_disable(resource_context.hclk);
+	clk_disable_unprepare(resource_context.hclk);
 disable_pclk:
-	clk_disable(resource_context.pclk);
+	clk_disable_unprepare(resource_context.pclk);
 bail_out:
 	if (resource_context.pclk) {
 		clk_put(resource_context.pclk);
@@ -175,7 +175,7 @@
 
 		VCDRES_MSG_LOW("%s(): Enabling the clocks ...\n", __func__);
 
-		if (clk_enable(resource_context.pclk)) {
+		if (clk_prepare_enable(resource_context.pclk)) {
 			VCDRES_MSG_ERROR("vidc pclk Enable failed\n");
 
 			clk_put(resource_context.hclk);
@@ -184,7 +184,7 @@
 			return false;
 		}
 
-		if (clk_enable(resource_context.hclk)) {
+		if (clk_prepare_enable(resource_context.hclk)) {
 			VCDRES_MSG_ERROR("vidc  hclk Enable failed\n");
 			clk_put(resource_context.pclk);
 			clk_put(resource_context.hclk_div2);
@@ -192,7 +192,7 @@
 			return false;
 		}
 
-		if (clk_enable(resource_context.hclk_div2)) {
+		if (clk_prepare_enable(resource_context.hclk_div2)) {
 			VCDRES_MSG_ERROR("vidc  hclk Enable failed\n");
 			clk_put(resource_context.hclk);
 			clk_put(resource_context.pclk);
@@ -253,9 +253,9 @@
 	VCDRES_MSG_LOW("%s(): Disabling the clocks ...\n", __func__);
 
 	resource_context.clock_enabled = 0;
-	clk_disable(resource_context.hclk);
-	clk_disable(resource_context.hclk_div2);
-	clk_disable(resource_context.pclk);
+	clk_disable_unprepare(resource_context.hclk);
+	clk_disable_unprepare(resource_context.hclk_div2);
+	clk_disable_unprepare(resource_context.pclk);
 	mutex_unlock(&resource_context.lock);
 
 	return true;
@@ -311,17 +311,17 @@
 			goto release_all_clks;
 		}
 
-		if (clk_enable(resource_context.pclk)) {
+		if (clk_prepare_enable(resource_context.pclk)) {
 			VCDRES_MSG_ERROR("vidc pclk Enable failed\n");
 			goto release_all_clks;
 		}
 
-		if (clk_enable(resource_context.hclk)) {
+		if (clk_prepare_enable(resource_context.hclk)) {
 			VCDRES_MSG_ERROR("vidc hclk Enable failed\n");
 			goto disable_pclk;
 		}
 
-		if (clk_enable(resource_context.hclk_div2)) {
+		if (clk_prepare_enable(resource_context.hclk_div2)) {
 			VCDRES_MSG_ERROR("vidc hclk_div2 Enable failed\n");
 			goto disable_hclk_pclk;
 		}
@@ -333,9 +333,9 @@
 		}
 		msleep(20);
 
-		clk_disable(resource_context.pclk);
-		clk_disable(resource_context.hclk);
-		clk_disable(resource_context.hclk_div2);
+		clk_disable_unprepare(resource_context.pclk);
+		clk_disable_unprepare(resource_context.hclk);
+		clk_disable_unprepare(resource_context.hclk_div2);
 
 	}
 	resource_context.rail_enabled = 1;
@@ -343,11 +343,11 @@
 	return true;
 
 disable_and_release_all_clks:
-	clk_disable(resource_context.hclk_div2);
+	clk_disable_unprepare(resource_context.hclk_div2);
 disable_hclk_pclk:
-	clk_disable(resource_context.hclk);
+	clk_disable_unprepare(resource_context.hclk);
 disable_pclk:
-	clk_disable(resource_context.pclk);
+	clk_disable_unprepare(resource_context.pclk);
 release_all_clks:
 	clk_put(resource_context.hclk_div2);
 	resource_context.hclk_div2 = NULL;
@@ -412,7 +412,7 @@
 		VCDRES_MSG_ERROR("Request AXI bus QOS fails.");
 		return false;
 	}
-	clk_enable(ebi1_clk);
+	clk_prepare_enable(ebi1_clk);
 }
 #endif
 
@@ -427,7 +427,7 @@
 #ifdef AXI_CLK_SCALING
 	VCDRES_MSG_MED("\n res_trk_power_down()::"
 		"Calling AXI remove requirement\n");
-	clk_disable(ebi1_clk);
+	clk_disable_unprepare(ebi1_clk);
 	clk_put(ebi1_clk);
 #endif
 	VCDRES_MSG_MED("\n res_trk_power_down():: Calling "
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index 980ec21..b300fbc 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -235,6 +235,7 @@
 	struct file *file;
 	s32 buffer_index = -1;
 	enum vdec_picture pic_type;
+	u32 ion_flag = 0;
 
 	if (!client_ctx || !vcd_frame_data) {
 		ERR("vid_dec_input_frame_done() NULL pointer\n");
@@ -268,7 +269,6 @@
 				      &phy_addr, &pmem_fd, &file,
 				      &buffer_index) ||
 		(vcd_frame_data->flags & VCD_FRAME_FLAG_EOS)) {
-
 		/* Buffer address in user space */
 		vdec_msg->vdec_msg_info.msgdata.output_frame.bufferaddr =
 		    (u8 *) user_vaddr;
@@ -334,7 +334,15 @@
 		ERR("vid_dec_output_frame_done UVA can not be found\n");
 		vdec_msg->vdec_msg_info.status_code = VDEC_S_EFATAL;
 	}
-
+	if (vcd_frame_data->data_len > 0) {
+		ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_OUTPUT,
+				pmem_fd, kernel_vaddr, buffer_index);
+		if (ion_flag == CACHED) {
+			invalidate_caches(kernel_vaddr,
+					(unsigned long)vcd_frame_data->data_len,
+					phy_addr);
+		}
+	}
 	mutex_lock(&client_ctx->msg_queue_lock);
 	list_add_tail(&vdec_msg->list, &client_ctx->msg_queue);
 	mutex_unlock(&client_ctx->msg_queue_lock);
@@ -804,6 +812,7 @@
 	u32 len = 0, flags = 0;
 	struct file *file;
 	int rc = 0;
+	unsigned long ionflag;
 
 	if (!client_ctx || !mv_data)
 		return false;
@@ -838,10 +847,18 @@
 			ERR("%s(): get_ION_handle failed\n", __func__);
 			goto ion_error;
 		}
+		rc = ion_handle_get_flags(client_ctx->user_ion_client,
+					client_ctx->h264_mv_ion_handle,
+					&ionflag);
+		if (rc) {
+			ERR("%s():get_ION_flags fail\n",
+					 __func__);
+			goto ion_error;
+		}
 		vcd_h264_mv_buffer->kernel_virtual_addr = (u8 *) ion_map_kernel(
 			client_ctx->user_ion_client,
 			client_ctx->h264_mv_ion_handle,
-			0);
+			ionflag);
 		if (!vcd_h264_mv_buffer->kernel_virtual_addr) {
 			ERR("%s(): get_ION_kernel virtual addr failed\n",
 				 __func__);
@@ -1025,7 +1042,6 @@
 		    __func__, buffer_info->buffer.bufferaddr);
 		return false;
 	}
-
 	vcd_status = vcd_set_buffer(client_ctx->vcd_handle,
 		buffer, (u8 *) kernel_vaddr,
 		buffer_info->buffer.buffer_len);
@@ -1171,6 +1187,7 @@
 	struct file *file;
 	s32 buffer_index = -1;
 	u32 vcd_status = VCD_ERR_FAIL;
+	u32 ion_flag = 0;
 
 	if (!client_ctx || !input_frame_info)
 		return false;
@@ -1198,7 +1215,18 @@
 		vcd_input_buffer.flags = input_frame_info->flags;
 		vcd_input_buffer.desc_buf = desc_buf;
 		vcd_input_buffer.desc_size = desc_size;
-
+		if (vcd_input_buffer.data_len > 0) {
+			ion_flag = vidc_get_fd_info(client_ctx,
+						BUFFER_TYPE_INPUT,
+						pmem_fd,
+						kernel_vaddr,
+						buffer_index);
+			if (ion_flag == CACHED) {
+				clean_caches(kernel_vaddr,
+				(unsigned long)vcd_input_buffer.data_len,
+				phy_addr);
+			}
+		}
 		vcd_status = vcd_decode_frame(client_ctx->vcd_handle,
 					      &vcd_input_buffer);
 		if (!vcd_status)
@@ -1241,7 +1269,10 @@
 		vcd_frame.virtual = (u8 *) kernel_vaddr;
 		vcd_frame.frm_clnt_data = (u32) fill_buffer_cmd->client_data;
 		vcd_frame.alloc_len = fill_buffer_cmd->buffer.buffer_len;
-
+		vcd_frame.ion_flag = vidc_get_fd_info(client_ctx,
+						 BUFFER_TYPE_OUTPUT,
+						pmem_fd, kernel_vaddr,
+						buffer_index);
 		vcd_status = vcd_fill_output_buffer(client_ctx->vcd_handle,
 						    &vcd_frame);
 		if (!vcd_status)
@@ -1651,6 +1682,7 @@
 	{
 		struct vdec_seqheader seq_header;
 		struct vcd_sequence_hdr vcd_seq_hdr;
+		unsigned long ionflag;
 		DBG("VDEC_IOCTL_SET_SEQUENCE_HEADER\n");
 		if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg))) {
 			ERR("Copy from user vdec_msg failed\n");
@@ -1681,9 +1713,19 @@
 				ERR("%s(): get_ION_handle failed\n", __func__);
 				return false;
 			}
+			rc = ion_handle_get_flags(client_ctx->user_ion_client,
+						client_ctx->seq_hdr_ion_handle,
+						&ionflag);
+			if (rc) {
+				ERR("%s():get_ION_flags fail\n",
+							 __func__);
+				ion_free(client_ctx->user_ion_client,
+					client_ctx->seq_hdr_ion_handle);
+				return false;
+			}
 			ker_vaddr = (unsigned long) ion_map_kernel(
 				client_ctx->user_ion_client,
-				client_ctx->seq_hdr_ion_handle, 0);
+				client_ctx->seq_hdr_ion_handle, ionflag);
 			if (!ker_vaddr) {
 				ERR("%s():get_ION_kernel virtual addr fail\n",
 							 __func__);
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index 97fc758..cc6606c 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -197,6 +197,7 @@
 	int pmem_fd;
 	struct file *file;
 	s32 buffer_index = -1;
+	u32 ion_flag = 0;
 
 	if (!client_ctx || !vcd_frame_data) {
 		ERR("vid_enc_input_frame_done() NULL pointer\n");
@@ -259,7 +260,15 @@
 		venc_msg->venc_msg_info.statuscode =
 			VEN_S_EFATAL;
 	}
-
+	if (venc_msg->venc_msg_info.buf.len > 0) {
+		ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_OUTPUT,
+					pmem_fd, kernel_vaddr, buffer_index);
+		if (ion_flag == CACHED) {
+			clean_and_invalidate_caches(kernel_vaddr,
+				(unsigned long)venc_msg->venc_msg_info.buf.len,
+				phy_addr);
+		}
+	}
 	mutex_lock(&client_ctx->msg_queue_lock);
 	list_add_tail(&venc_msg->list, &client_ctx->msg_queue);
 	mutex_unlock(&client_ctx->msg_queue_lock);
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
index 1dbd170..e3bb9db 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -1609,6 +1609,7 @@
 	int pmem_fd;
 	struct file *file;
 	s32 buffer_index = -1;
+	u32 ion_flag = 0;
 
 	u32 vcd_status = VCD_ERR_FAIL;
 
@@ -1640,6 +1641,18 @@
 		/* Rely on VCD using the same flags as OMX */
 		vcd_input_buffer.flags = input_frame_info->flags;
 
+		ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_INPUT,
+				pmem_fd, kernel_vaddr, buffer_index);
+
+		if (vcd_input_buffer.data_len > 0) {
+			if (ion_flag == CACHED) {
+				clean_caches(
+				(unsigned long) vcd_input_buffer.virtual,
+				(unsigned long) vcd_input_buffer.data_len,
+				(phy_addr + input_frame_info->offset));
+			}
+		}
+
 		vcd_status = vcd_encode_frame(client_ctx->vcd_handle,
 		&vcd_input_buffer);
 		if (!vcd_status)
@@ -1710,6 +1723,7 @@
 	size_t ion_len = -1;
 	unsigned long phy_addr;
 	int rc = -1;
+	unsigned long ionflag;
 	if (!client_ctx || !venc_recon) {
 		pr_err("%s() Invalid params", __func__);
 		return false;
@@ -1749,10 +1763,18 @@
 			ERR("%s(): get_ION_handle failed\n", __func__);
 			goto ion_error;
 		}
+		rc = ion_handle_get_flags(client_ctx->user_ion_client,
+					client_ctx->recon_buffer_ion_handle[i],
+					&ionflag);
+		if (rc) {
+			ERR("%s():get_ION_flags fail\n",
+				 __func__);
+			goto ion_error;
+		}
 		control->kernel_virtual_addr = (u8 *) ion_map_kernel(
 			client_ctx->user_ion_client,
 			client_ctx->recon_buffer_ion_handle[i],
-			0);
+			ionflag);
 		if (!control->kernel_virtual_addr) {
 			ERR("%s(): get_ION_kernel virtual addr fail\n",
 				 __func__);
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index 1709cc2..cd3f954 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -364,6 +364,26 @@
 }
 EXPORT_SYMBOL(vidc_release_firmware);
 
+u32 vidc_get_fd_info(struct video_client_ctx *client_ctx,
+		enum buffer_dir buffer, int pmem_fd,
+		unsigned long kvaddr, int index)
+{
+	struct buf_addr_table *buf_addr_table;
+	u32 rc = 0;
+	if (!client_ctx)
+		return false;
+	if (buffer == BUFFER_TYPE_INPUT)
+		buf_addr_table = client_ctx->input_buf_addr_table;
+	else
+		buf_addr_table = client_ctx->output_buf_addr_table;
+	if (buf_addr_table[index].pmem_fd == pmem_fd) {
+		if (buf_addr_table[index].kernel_vaddr == kvaddr)
+			rc = buf_addr_table[index].buff_ion_flag;
+	}
+	return rc;
+}
+EXPORT_SYMBOL(vidc_get_fd_info);
+
 u32 vidc_lookup_addr_table(struct video_client_ctx *client_ctx,
 	enum buffer_dir buffer,
 	u32 search_with_user_vaddr,
@@ -459,6 +479,7 @@
 	struct msm_mapped_buffer *mapped_buffer = NULL;
 	size_t ion_len;
 	struct ion_handle *buff_ion_handle = NULL;
+	unsigned long ionflag = 0;
 
 	if (!client_ctx || !length)
 		return false;
@@ -505,13 +526,20 @@
 			if (IS_ERR_OR_NULL(buff_ion_handle)) {
 				ERR("%s(): get_ION_handle failed\n",
 				 __func__);
+				goto bail_out_add;
+			}
+			if (ion_handle_get_flags(client_ctx->user_ion_client,
+						buff_ion_handle,
+						&ionflag)) {
+				ERR("%s():ION flags fail\n",
+				 __func__);
 				goto ion_error;
 			}
 			*kernel_vaddr = (unsigned long)
 				ion_map_kernel(
 				client_ctx->user_ion_client,
 				buff_ion_handle,
-				0);
+				ionflag);
 			if (!(*kernel_vaddr)) {
 				ERR("%s():ION virtual addr fail\n",
 				 __func__);
@@ -548,10 +576,13 @@
 		buf_addr_table[*num_of_buffers].phy_addr = phys_addr;
 		buf_addr_table[*num_of_buffers].buff_ion_handle =
 						buff_ion_handle;
+		buf_addr_table[*num_of_buffers].buff_ion_flag =
+						ionflag;
 		*num_of_buffers = *num_of_buffers + 1;
 		DBG("%s() : client_ctx = %p, user_virt_addr = 0x%08lx, "
-			"kernel_vaddr = 0x%08lx inserted!", __func__,
-			client_ctx, user_vaddr, *kernel_vaddr);
+			"kernel_vaddr = 0x%08lx phys_addr=%lu inserted!",
+			__func__, client_ctx, user_vaddr, *kernel_vaddr,
+			phys_addr);
 	}
 	mutex_unlock(&client_ctx->enrty_queue_lock);
 	return true;
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.h b/drivers/video/msm/vidc/common/init/vidc_init.h
index 717d0c8..ced99ff 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.h
+++ b/drivers/video/msm/vidc/common/init/vidc_init.h
@@ -28,6 +28,7 @@
 	unsigned long user_vaddr;
 	unsigned long kernel_vaddr;
 	unsigned long phy_addr;
+	unsigned long buff_ion_flag;
 	struct ion_handle *buff_ion_handle;
 	int pmem_fd;
 	struct file *file;
@@ -63,6 +64,9 @@
 void __iomem *vidc_get_ioaddr(void);
 int vidc_load_firmware(void);
 void vidc_release_firmware(void);
+u32 vidc_get_fd_info(struct video_client_ctx *client_ctx,
+		enum buffer_dir buffer, int pmem_fd,
+		unsigned long kvaddr, int index);
 u32 vidc_lookup_addr_table(struct video_client_ctx *client_ctx,
 	enum buffer_dir buffer, u32 search_with_user_vaddr,
 	unsigned long *user_vaddr, unsigned long *kernel_vaddr,
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_api.h b/drivers/video/msm/vidc/common/vcd/vcd_api.h
index badab1e..9580ece 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_api.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_api.h
@@ -56,6 +56,7 @@
 struct vcd_frame_data {
 	u8 *virtual;
 	u8 *physical;
+	u32 ion_flag;
 	u32 alloc_len;
 	u32 data_len;
 	u32 offset;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index b5fcc1c..509b897 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -188,6 +188,36 @@
 
 }
 
+u32 vcd_get_ion_flag(struct video_client_ctx *client_ctx,
+			  unsigned long kernel_vaddr)
+{
+	unsigned long phy_addr, user_vaddr;
+	int pmem_fd;
+	struct file *file;
+	s32 buffer_index = -1;
+	u32 ion_flag = 0;
+
+	if (vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_INPUT,
+					  false, &user_vaddr, &kernel_vaddr,
+					  &phy_addr, &pmem_fd, &file,
+					  &buffer_index)) {
+
+		ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_INPUT,
+				pmem_fd, kernel_vaddr, buffer_index);
+		return ion_flag;
+	} else if (vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT,
+		false, &user_vaddr, &kernel_vaddr, &phy_addr, &pmem_fd, &file,
+		&buffer_index)) {
+		ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_OUTPUT,
+				pmem_fd, kernel_vaddr, buffer_index);
+		return ion_flag;
+	} else {
+		VCD_MSG_ERROR("Couldn't get ion flag");
+		return 0;
+	}
+
+}
+
 void vcd_reset_device_channels(struct vcd_dev_ctxt *dev_ctxt)
 {
 	dev_ctxt->ddl_frame_ch_free = dev_ctxt->ddl_frame_ch_depth;
@@ -523,6 +553,7 @@
 {
 	struct vcd_buffer_entry *buf_entry;
 	u8 *physical;
+	u32 ion_flag = 0;
 
 	buf_entry = vcd_find_buffer_pool_entry(buf_pool, buffer);
 	if (buf_entry) {
@@ -534,6 +565,9 @@
 	physical = (u8 *) vcd_pmem_get_physical(
 		cctxt->client_data, (unsigned long)buffer);
 
+	ion_flag = vcd_get_ion_flag(cctxt->client_data,
+				(unsigned long)buffer);
+
 	if (!physical) {
 		VCD_MSG_ERROR("Couldn't get physical address");
 		return VCD_ERR_BAD_POINTER;
@@ -548,7 +582,6 @@
 		VCD_MSG_ERROR("Can't allocate buffer pool is full");
 		return VCD_ERR_FAIL;
 	}
-
 	buf_entry->virtual = buffer;
 	buf_entry->physical = physical;
 	buf_entry->sz = buf_size;
@@ -557,6 +590,7 @@
 
 	buf_entry->frame.virtual = buf_entry->virtual;
 	buf_entry->frame.physical = buf_entry->physical;
+	buf_entry->frame.ion_flag = ion_flag;
 
 	buf_pool->validated++;
 
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 bdbaffd..1cb5401 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -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
@@ -40,6 +40,7 @@
 #define APQ8060_MACHINE_ID	86
 #define AO8960_MACHINE_ID	87
 #define MSM8660_MACHINE_ID	71
+#define MDM9615_MACHINE_ID	104
 #define APQ8064_MACHINE_ID	109
 #define MSM8930_MACHINE_ID	116
 #define MSM8630_MACHINE_ID	117
@@ -47,10 +48,18 @@
 #define APQ8030_MACHINE_ID	119
 #define MSM8627_MACHINE_ID	120
 #define MSM8227_MACHINE_ID	121
+#define MSM8260A_MACHINE_ID	123
+#define MSM8974_MACHINE_ID	126
 #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)
 #define MSG_MASK_1			(0x00000002)
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/genlock.h b/include/linux/genlock.h
index 2e9f9d6..9351a15 100644
--- a/include/linux/genlock.h
+++ b/include/linux/genlock.h
@@ -12,7 +12,7 @@
 struct genlock *genlock_create_lock(struct genlock_handle *);
 struct genlock *genlock_attach_lock(struct genlock_handle *, int fd);
 int genlock_wait(struct genlock_handle *handle, u32 timeout);
-void genlock_release_lock(struct genlock_handle *);
+/* genlock_release_lock was deprecated */
 int genlock_lock(struct genlock_handle *handle, int op, int flags,
 	u32 timeout);
 #endif
@@ -39,6 +39,8 @@
 	struct genlock_lock)
 #define GENLOCK_IOC_LOCK _IOW(GENLOCK_IOC_MAGIC, 3, \
 	struct genlock_lock)
+
+/* Deprecated */
 #define GENLOCK_IOC_RELEASE _IO(GENLOCK_IOC_MAGIC, 4)
 #define GENLOCK_IOC_WAIT _IOW(GENLOCK_IOC_MAGIC, 5, \
 	struct genlock_lock)
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index 9aa557a..500ee6b 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -29,13 +29,25 @@
 /* MXT_TOUCH_KEYARRAY_T15 */
 #define MXT_KEYARRAY_MAX_KEYS	32
 
-/* The platform data for the Atmel maXTouch touchscreen driver */
-struct mxt_platform_data {
+/* Config data for a given maXTouch controller with a specific firmware */
+struct mxt_config_info {
 	const u8 *config;
 	size_t config_length;
+	u8 family_id;
+	u8 variant_id;
+	u8 version;
+	u8 build;
+};
+
+/* The platform data for the Atmel maXTouch touchscreen driver */
+struct mxt_platform_data {
+	const struct mxt_config_info *config_array;
+	size_t config_array_size;
 
 	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/i2c/tsc2007.h b/include/linux/i2c/tsc2007.h
index 195e904..f439ebd 100644
--- a/include/linux/i2c/tsc2007.h
+++ b/include/linux/i2c/tsc2007.h
@@ -13,6 +13,10 @@
 	int	fuzzx; /* fuzz factor for X, Y and pressure axes */
 	int	fuzzy;
 	int	fuzzz;
+	u16	min_x;
+	u16	min_y;
+	u16	max_x;
+	u16	max_y;
 	unsigned long irq_flags;
 	bool	invert_x;
 	bool	invert_y;
diff --git a/include/linux/idle_stats_device.h b/include/linux/idle_stats_device.h
index a531b7a..cd613af 100644
--- a/include/linux/idle_stats_device.h
+++ b/include/linux/idle_stats_device.h
@@ -34,6 +34,7 @@
 struct msm_idle_write_stats {
 	__u32 busy_timer;
 	__u32 next_busy_timer;
+	__u32 max_samples;
 };
 
 #define MSM_IDLE_STATS_IOC_MAGIC  0xD8
@@ -60,6 +61,7 @@
 	ktime_t busy_timer_interval;
 	ktime_t idle_start;
 	ktime_t remaining_time;
+	__u32 max_samples;
 
 	struct msm_idle_read_stats *stats;
 	struct msm_idle_read_stats stats_vector[2];
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/core.h b/include/linux/mfd/pm8xxx/core.h
index 5ed615b..e7bf820 100644
--- a/include/linux/mfd/pm8xxx/core.h
+++ b/include/linux/mfd/pm8xxx/core.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
@@ -28,6 +28,7 @@
 	PM8XXX_VERSION_8018,
 	PM8XXX_VERSION_8922,
 	PM8XXX_VERSION_8038,
+	PM8XXX_VERSION_8917,
 };
 
 /* PMIC version specific silicon revisions */
@@ -68,6 +69,9 @@
 #define PM8XXX_REVISION_8038_2p0	2
 #define PM8XXX_REVISION_8038_2p1	3
 
+#define PM8XXX_REVISION_8917_TEST	0
+#define PM8XXX_REVISION_8917_1p0	1
+
 struct pm8xxx_drvdata {
 	int			(*pmic_readb) (const struct device *dev,
 						u16 addr, u8 *val);
diff --git a/include/linux/mfd/pm8xxx/misc.h b/include/linux/mfd/pm8xxx/misc.h
index 32189b2..c4f601b 100644
--- a/include/linux/mfd/pm8xxx/misc.h
+++ b/include/linux/mfd/pm8xxx/misc.h
@@ -160,6 +160,27 @@
  */
 int pm8xxx_stay_on(void);
 
+/**
+ * pm8xxx_preload_dVdd - preload the dVdd regulator during off state.
+ *
+ * This can help to reduce fluctuations in the dVdd voltage during startup
+ * at the cost of additional off state current draw.
+ *
+ * This API should only be called if dVdd startup issues are suspected.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+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)
@@ -196,6 +217,14 @@
 {
 	return -ENODEV;
 }
+static inline int pm8xxx_preload_dVdd(void)
+{
+	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/pm8038.h b/include/linux/mfd/pm8xxx/pm8038.h
index 203095a..4d3c78f 100644
--- a/include/linux/mfd/pm8xxx/pm8038.h
+++ b/include/linux/mfd/pm8xxx/pm8038.h
@@ -30,6 +30,7 @@
 #include <linux/mfd/pm8xxx/pm8xxx-adc.h>
 #include <linux/mfd/pm8xxx/pm8921-charger.h>
 #include <linux/mfd/pm8xxx/pm8921-bms.h>
+#include <linux/leds-pm8xxx.h>
 #include <linux/mfd/pm8xxx/ccadc.h>
 
 #define PM8038_CORE_DEV_NAME "pm8038-core"
@@ -75,6 +76,7 @@
 	struct pm8921_charger_platform_data	*charger_pdata;
 	struct pm8921_bms_platform_data		*bms_pdata;
 	struct pm8xxx_adc_platform_data		*adc_pdata;
+	struct pm8xxx_led_platform_data		*leds_pdata;
 	struct pm8xxx_ccadc_platform_data	*ccadc_pdata;
 };
 
diff --git a/include/linux/mfd/pm8xxx/pm8921-charger.h b/include/linux/mfd/pm8xxx/pm8921-charger.h
index a954364..31af535 100644
--- a/include/linux/mfd/pm8xxx/pm8921-charger.h
+++ b/include/linux/mfd/pm8xxx/pm8921-charger.h
@@ -63,9 +63,11 @@
  *				after the battery has been fully charged
  * @term_current:	the charger current (mA) at which EOC happens
  * @cool_temp:		the temperature (degC) at which the battery is
- *			considered cool charging current and voltage is reduced
+ *			considered cool charging current and voltage is reduced.
+ *			Use INT_MIN to indicate not valid.
  * @warm_temp:		the temperature (degC) at which the battery is
  *			considered warm charging current and voltage is reduced
+ *			Use INT_MIN to indicate not valid.
  * @temp_check_period:	The polling interval in seconds to check battery
  *			temeperature if it has gone to cool or warm temperature
  *			area
@@ -108,8 +110,8 @@
 	unsigned int			min_voltage;
 	unsigned int			resume_voltage_delta;
 	unsigned int			term_current;
-	unsigned int			cool_temp;
-	unsigned int			warm_temp;
+	int				cool_temp;
+	int				warm_temp;
 	unsigned int			temp_check_period;
 	unsigned int			max_bat_chg_current;
 	unsigned int			cool_bat_chg_current;
diff --git a/include/linux/mfd/pm8xxx/pm8921.h b/include/linux/mfd/pm8xxx/pm8921.h
index 35792d5..22293fe 100644
--- a/include/linux/mfd/pm8xxx/pm8921.h
+++ b/include/linux/mfd/pm8xxx/pm8921.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
@@ -40,8 +40,10 @@
 #define PM8921_NR_IRQS		256
 
 #define PM8921_NR_GPIOS		44
+#define PM8917_NR_GPIOS		38
 
 #define PM8921_NR_MPPS		12
+#define PM8917_NR_MPPS		10
 
 #define PM8921_GPIO_BLOCK_START	24
 #define PM8921_MPP_BLOCK_START	16
@@ -110,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/pwm.h b/include/linux/mfd/pm8xxx/pwm.h
index be3ec65..9169e90 100644
--- a/include/linux/mfd/pm8xxx/pwm.h
+++ b/include/linux/mfd/pm8xxx/pwm.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
@@ -17,8 +17,8 @@
 
 #define PM8XXX_PWM_DEV_NAME	"pm8xxx-pwm"
 
-#define PM8XXX_PWM_PERIOD_MAX		(327 * USEC_PER_SEC)
-#define PM8XXX_PWM_PERIOD_MIN		7 /* micro seconds */
+#define PM8XXX_PWM_PERIOD_MIN	7 /* usec: 19.2M, n=6, m=0, pre=2 */
+#define PM8XXX_PWM_PERIOD_MAX	(384 * USEC_PER_SEC) /* 1K, n=9, m=7, pre=6 */
 
 #define PM_PWM_LUT_SIZE			64
 #define PM_PWM_LUT_DUTY_TIME_MAX	512	/* ms */
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_audio_acdb.h b/include/linux/msm_audio_acdb.h
index 3d756c2..e7f06b5 100644
--- a/include/linux/msm_audio_acdb.h
+++ b/include/linux/msm_audio_acdb.h
@@ -35,6 +35,13 @@
 			(AUDIO_MAX_COMMON_IOCTL_NUM+14), unsigned)
 #define AUDIO_SET_ASM_TOPOLOGY	_IOW(AUDIO_IOCTL_MAGIC, \
 			(AUDIO_MAX_COMMON_IOCTL_NUM+15), unsigned)
+#define AUDIO_SET_AFE_TX_CAL		_IOW(AUDIO_IOCTL_MAGIC, \
+			(AUDIO_MAX_COMMON_IOCTL_NUM+16), unsigned)
+#define AUDIO_SET_AFE_RX_CAL		_IOW(AUDIO_IOCTL_MAGIC, \
+			(AUDIO_MAX_COMMON_IOCTL_NUM+17), unsigned)
+
+
+#define	AUDIO_MAX_ACDB_IOCTL	(AUDIO_MAX_COMMON_IOCTL_NUM+30)
 
 /* ACDB structures */
 struct cal_block {
@@ -49,25 +56,26 @@
 
 /* For Real-Time Audio Calibration */
 #define AUDIO_GET_RTAC_ADM_INFO		_IOR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+16), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+1), unsigned)
 #define AUDIO_GET_RTAC_VOICE_INFO	_IOR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+17), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+2), unsigned)
 #define AUDIO_GET_RTAC_ADM_CAL	_IOWR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+18), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+3), unsigned)
 #define AUDIO_SET_RTAC_ADM_CAL	_IOWR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+19), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+4), unsigned)
 #define AUDIO_GET_RTAC_ASM_CAL	_IOWR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+20), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+5), unsigned)
 #define AUDIO_SET_RTAC_ASM_CAL	_IOWR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+21), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+6), unsigned)
 #define AUDIO_GET_RTAC_CVS_CAL	_IOWR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+22), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+7), unsigned)
 #define AUDIO_SET_RTAC_CVS_CAL	_IOWR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+23), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+8), unsigned)
 #define AUDIO_GET_RTAC_CVP_CAL	_IOWR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+24), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+9), unsigned)
 #define AUDIO_SET_RTAC_CVP_CAL	_IOWR(AUDIO_IOCTL_MAGIC, \
-			(AUDIO_MAX_COMMON_IOCTL_NUM+25), unsigned)
+			(AUDIO_MAX_ACDB_IOCTL+10), unsigned)
 
+#define	AUDIO_MAX_RTAC_IOCTL	(AUDIO_MAX_ACDB_IOCTL+20)
 
 #endif /* __MSM_AUDIO_ACDB_H */
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 1f898b0..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
@@ -51,6 +52,7 @@
 	KGSL_USER_MEM_TYPE_ASHMEM	= 0x00000001,
 	KGSL_USER_MEM_TYPE_ADDR		= 0x00000002,
 	KGSL_USER_MEM_TYPE_ION		= 0x00000003,
+	KGSL_USER_MEM_TYPE_MAX		= 0x00000004,
 };
 
 struct kgsl_devinfo {
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index cac7758..07d5af6 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -1,6 +1,7 @@
 /* include/linux/msm_mdp.h
  *
  * Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2012 Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -77,6 +78,7 @@
 	MDP_RGB_565,      /* RGB 565 planer */
 	MDP_XRGB_8888,    /* RGB 888 padded */
 	MDP_Y_CBCR_H2V2,  /* Y and CbCr, pseudo planer w/ Cb is in MSB */
+	MDP_Y_CBCR_H2V2_ADRENO,
 	MDP_ARGB_8888,    /* ARGB 888 */
 	MDP_RGB_888,      /* RGB 888 planer */
 	MDP_Y_CRCB_H2V2,  /* Y and CrCb, pseudo planer w/ Cr is in MSB */
@@ -335,6 +337,10 @@
 	struct mdp_pcc_coeff r, g, b;
 };
 
+#define MDP_CSC_FLAG_ENABLE	0x1
+#define MDP_CSC_FLAG_YUV_IN	0x2
+#define MDP_CSC_FLAG_YUV_OUT	0x4
+
 struct mdp_csc_cfg {
 	/* flags for enable CSC, toggling RGB,YUV input/output */
 	uint32_t flags;
diff --git a/include/linux/msm_ssbi.h b/include/linux/msm_ssbi.h
index e90398a..647bc06 100644
--- a/include/linux/msm_ssbi.h
+++ b/include/linux/msm_ssbi.h
@@ -1,5 +1,5 @@
 /* Copyright (C) 2010 Google, Inc.
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  * Author: Dima Zavin <dima@android.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -30,6 +30,7 @@
 };
 
 struct msm_ssbi_platform_data {
+	const char *rsl_id;
 	struct msm_ssbi_slave_info	slave;
 	enum msm_ssbi_controller_type controller_type;
 };
diff --git a/include/linux/msm_tsens.h b/include/linux/msm_tsens.h
index 2a92899..189548c 100644
--- a/include/linux/msm_tsens.h
+++ b/include/linux/msm_tsens.h
@@ -32,4 +32,11 @@
 	enum platform_type		hw_type;
 };
 
+struct tsens_device {
+	uint32_t			sensor_num;
+};
+
+int32_t tsens_get_temp(struct tsens_device *dev, unsigned long *temp);
+int msm_tsens_early_init(struct tsens_platform_data *pdata);
+
 #endif /*MSM_TSENS_H */
diff --git a/include/linux/of_spmi.h b/include/linux/of_spmi.h
new file mode 100644
index 0000000..d07ce63
--- /dev/null
+++ b/include/linux/of_spmi.h
@@ -0,0 +1,23 @@
+/* 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/spmi.h>
+#include <linux/of_irq.h>
+
+#ifdef CONFIG_OF_SPMI
+int of_spmi_register_devices(struct spmi_controller *ctrl);
+#else
+static int of_spmi_register_devices(struct spmi_controller *ctrl)
+{
+	return -ENXIO;
+}
+#endif /* CONFIG_OF_SPMI */
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/slimbus/slimbus.h b/include/linux/slimbus/slimbus.h
index 2b5adb3..448d9ab 100644
--- a/include/linux/slimbus/slimbus.h
+++ b/include/linux/slimbus/slimbus.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
@@ -378,9 +378,19 @@
  * @seglen: Segment length of this channel.
  * @rootexp: root exponent of this channel. Rate can be found using rootexp and
  *	coefficient. Used during scheduling.
- * @srch: Source ports used by this channel.
- * @nsrc: number of source ports used by this channel.
- * @sinkh: Sink port used by this channel.
+ * @srch: Source port used by this channel.
+ * @sinkh: Sink ports used by this channel.
+ * @nsink: number of sink ports used by this channel.
+ * @chan: Channel number sent on hardware lines for this channel. May not be
+ *	equal to array-index into chans if client requested to use number beyond
+ *	channel-array for the controller.
+ * @ref: Reference number to keep track of how many clients (upto 2) are using
+ *	this channel.
+ * @def: Used to keep track of how many times the channel definition is sent
+ *	to hardware and this will decide if channel-remove can be sent for the
+ *	channel. Channel definition may be sent upto twice (once per producer
+ *	and once per consumer). Channel removal should be sent only once to
+ *	avoid clients getting underflow/overflow errors.
  */
 struct slim_ich {
 	struct slim_ch		prop;
@@ -394,9 +404,12 @@
 	u32			newintr;
 	u32			seglen;
 	u8			rootexp;
-	u32			*srch;
-	int			nsrc;
-	u32			sinkh;
+	u32			srch;
+	u32			*sinkh;
+	int			nsink;
+	u8			chan;
+	int			ref;
+	int			def;
 };
 
 /*
@@ -472,6 +485,8 @@
  * @nports: Number of ports supported by the controller
  * @chans: Channels associated with this controller
  * @nchans: Number of channels supported
+ * @reserved: Reserved channels that controller wants to use internally
+ *		Clients will be assigned channel numbers after this number
  * @sched: scheduler structure used by the controller
  * @dev_released: completion used to signal when sysfs has released this
  *	controller so that it can be deleted during shutdown
@@ -516,6 +531,7 @@
 	int			nports;
 	struct slim_ich		*chans;
 	int			nchans;
+	u8			reserved;
 	struct slim_sched	sched;
 	struct completion	dev_released;
 	int			(*xfer_msg)(struct slim_controller *ctrl,
@@ -744,19 +760,31 @@
 			u32 ph, u8 **done_buf, u32 *done_len);
 
 /*
- * slim_connect_ports: Connect port(s) to channel.
+ * slim_connect_src: Connect source port to channel.
  * @sb: client handle
- * @srch: source handles to be connected to this channel
- * @nrsc: number of source ports
- * @sinkh: sink handle to be connected to this channel
+ * @srch: source handle to be connected to this channel
  * @chanh: Channel with which the ports need to be associated with.
- * Per slimbus specification, a channel may have multiple source-ports and 1
- * sink port.Channel specified in chanh needs to be allocated first.
+ * Per slimbus specification, a channel may have 1 source port.
+ * Channel specified in chanh needs to be allocated first.
+ * Returns -EALREADY if source is already configured for this channel.
+ * Returns -ENOTCONN if channel is not allocated
  */
-extern int slim_connect_ports(struct slim_device *sb, u32 *srch, int nsrc,
-				u32 sinkh, u16 chanh);
+extern int slim_connect_src(struct slim_device *sb, u32 srch, u16 chanh);
 
 /*
+ * slim_connect_sink: Connect sink port(s) to channel.
+ * @sb: client handle
+ * @sinkh: sink handle(s) to be connected to this channel
+ * @nsink: number of sinks
+ * @chanh: Channel with which the ports need to be associated with.
+ * Per slimbus specification, a channel may have multiple sink-ports.
+ * Channel specified in chanh needs to be allocated first.
+ * Returns -EALREADY if sink is already configured for this channel.
+ * Returns -ENOTCONN if channel is not allocated
+ */
+extern int slim_connect_sink(struct slim_device *sb, u32 *sinkh, int nsink,
+				u16 chanh);
+/*
  * slim_disconnect_ports: Disconnect port(s) from channel
  * @sb: client handle
  * @ph: ports to be disconnected
@@ -784,18 +812,32 @@
  * slim_alloc_ch: Allocate a slimbus channel and return its handle.
  * @sb: client handle.
  * @chanh: return channel handle
- * Slimbus channels are limited to 256 per specification. LSB of the handle
- * indicates channel number and MSB of the handle is used by the slimbus
- * framework. -EXFULL is returned if all channels are in use.
+ * Slimbus channels are limited to 256 per specification.
+ * -EXFULL is returned if all channels are in use.
  * Although slimbus specification supports 256 channels, a controller may not
  * support that many channels.
  */
 extern int slim_alloc_ch(struct slim_device *sb, u16 *chanh);
 
 /*
+ * slim_query_ch: Get reference-counted handle for a channel number. Every
+ * channel is reference counted by one as producer and the others as
+ * consumer)
+ * @sb: client handle
+ * @chan: slimbus channel number
+ * @chanh: return channel handle
+ * If request channel number is not in use, it is allocated, and reference
+ * count is set to one. If the channel was was already allocated, this API
+ * will return handle to that channel and reference count is incremented.
+ * -EXFULL is returned if all channels are in use
+ */
+extern int slim_query_ch(struct slim_device *sb, u8 chan, u16 *chanh);
+/*
  * slim_dealloc_ch: Deallocate channel allocated using the API above
  * -EISCONN is returned if the channel is tried to be deallocated without
  *  being removed first.
+ *  -ENOTCONN is returned if deallocation is tried on a channel that's not
+ *  allocated.
  */
 extern int slim_dealloc_ch(struct slim_device *sb, u16 chanh);
 
@@ -813,8 +855,8 @@
  *	(e.g. 5.1 audio has 6 channels with same parameters. They will all be
  *	grouped and given 1 handle for simplicity and avoid repeatedly calling
  *	the API)
- * -EISCONN is returned if the channel is already connected. -EBUSY is
- * returned if the channel is already allocated to some other client.
+ * -EISCONN is returned if channel is already used with different parameters.
+ * -ENXIO is returned if the channel is not yet allocated.
  */
 extern int slim_define_ch(struct slim_device *sb, struct slim_ch *prop,
 				u16 *chanh, u8 nchan, bool grp, u16 *grph);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 9373064..2cbe6ce 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -149,7 +149,8 @@
  *              for msm_otg driver.
  * @phy_init_seq: PHY configuration sequence. val, reg pairs
  *              terminated by -1.
- * @vbus_power: VBUS power on/off routine.
+ * @vbus_power: VBUS power on/off routine.It should return result
+ *		as success(zero value) or failure(non-zero value).
  * @power_budget: VBUS power budget in mA (0 will be treated as 500mA).
  * @mode: Supported mode (OTG/peripheral/host).
  * @otg_control: OTG switch controlled by user/Id pin
@@ -160,10 +161,13 @@
  * @disable_reset_on_disconnect: perform USB PHY and LINK reset
  *              on USB cable disconnection.
  * @swfi_latency: miminum latency to allow swfi.
+ * @enable_dcd: Enable Data Contact Detection circuit. if not set
+ *              wait for 600msec before proceeding to primary
+ *              detection.
  */
 struct msm_otg_platform_data {
 	int *phy_init_seq;
-	void (*vbus_power)(bool on);
+	int (*vbus_power)(bool on);
 	unsigned power_budget;
 	enum usb_mode_type mode;
 	enum otg_control_type otg_control;
@@ -174,6 +178,7 @@
 	bool mhl_enable;
 	bool disable_reset_on_disconnect;
 	u32 swfi_latency;
+	bool enable_dcd;
 };
 
 /**
@@ -235,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.
@@ -281,8 +286,12 @@
 
 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;
 };
+
+enum usb_bam {
+	HSUSB_BAM = 0,
+	HSIC_BAM,
+};
 #endif
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/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index c97c664..9759b32 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -42,6 +42,7 @@
 				enum wcnss_opcode opcode);
 int req_riva_power_on_lock(char *driver_name);
 int free_riva_power_on_lock(char *driver_name);
+unsigned int wcnss_get_serial_number(void);
 #define wcnss_wlan_get_drvdata(dev) dev_get_drvdata(dev)
 #define wcnss_wlan_set_drvdata(dev, data) dev_set_drvdata((dev), (data))
 
diff --git a/include/media/gpio-ir-recv.h b/include/media/gpio-ir-recv.h
new file mode 100644
index 0000000..3eab611
--- /dev/null
+++ b/include/media/gpio-ir-recv.h
@@ -0,0 +1,23 @@
+/* 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 __GPIO_IR_RECV_H__
+#define __GPIO_IR_RECV_H__
+
+struct gpio_ir_recv_platform_data {
+	unsigned int gpio_nr;
+	bool active_low;
+	bool can_wakeup;
+};
+
+#endif /* __GPIO_IR_RECV_H__ */
+
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index a984943..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 */
@@ -401,6 +423,12 @@
 #define CMD_CONFIG_FREE_BUF_ADDR 48
 #define CMD_AXI_CFG_ZSL_ALL_CHNLS 49
 #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 {
@@ -494,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
@@ -639,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
@@ -1142,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 4694b78..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
@@ -41,6 +55,9 @@
 #define MSG_ID_BUS_OVERFLOW             36
 #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
@@ -172,6 +189,15 @@
 #define VFE_CMD_GET_RGB_G_TABLE                         126
 #define VFE_CMD_GET_LA_TABLE                            127
 #define VFE_CMD_DEMOSAICV3_UPDATE                       128
+#define VFE_CMD_ACTIVE_REGION_CFG                       129
+#define VFE_CMD_COLOR_PROCESSING_CONFIG                 130
+#define VFE_CMD_STATS_WB_AEC_CONFIG                     131
+#define VFE_CMD_STATS_WB_AEC_UPDATE                     132
+#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;
@@ -179,7 +205,6 @@
 	void     *value;
 };
 
-
 #define VPE_CMD_DUMMY_0                                 0
 #define VPE_CMD_INIT                                    1
 #define VPE_CMD_DEINIT                                  2
@@ -192,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 */
@@ -208,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
@@ -235,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;
@@ -280,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/include/media/radio-iris.h b/include/media/radio-iris.h
index 8b753bd..36139ba 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -129,7 +129,8 @@
 #define HCI_OCF_FM_EN_WAN_AVD_CTRL          0x0014
 #define HCI_OCF_FM_EN_NOTCH_CTRL            0x0015
 #define HCI_OCF_FM_SET_EVENT_MASK           0x0016
-
+#define HCI_OCF_FM_SET_CH_DET_THRESHOLD     0x0017
+#define HCI_OCF_FM_GET_CH_DET_THRESHOLD     0x0018
 /* HCI trans control commans opcode*/
 #define HCI_OCF_FM_ENABLE_TRANS_REQ         0x0001
 #define HCI_OCF_FM_DISABLE_TRANS_REQ        0x0002
@@ -199,7 +200,7 @@
 #define HCI_FM_ENABLE_TRANS_CMD 13
 #define HCI_FM_DISABLE_TRANS_CMD 14
 #define HCI_FM_GET_TX_CONFIG 15
-
+#define HCI_FM_GET_DET_CH_TH_CMD 16
 
 /* Defines for FM TX*/
 #define TX_PS_DATA_LENGTH 96
@@ -319,6 +320,14 @@
 	__u16 start_address;
 } __packed;
 
+struct hci_fm_ch_det_threshold {
+	char sinr;
+	__u8 sinr_samples;
+	__u8 low_th;
+	__u8 high_th;
+
+} __packed;
+
 /*HCI events*/
 #define HCI_EV_TUNE_STATUS              0x01
 #define HCI_EV_RDS_LOCK_STATUS          0x02
@@ -551,6 +560,10 @@
 	V4L2_CID_PRIVATE_IRIS_DO_CALIBRATION,
 	V4L2_CID_PRIVATE_IRIS_SRCH_ALGORITHM, /* TAVARUA specific command */
 	V4L2_CID_PRIVATE_IRIS_GET_SINR,
+	V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD,
+	V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD,
+	V4L2_CID_PRIVATE_SINR_THRESHOLD,
+	V4L2_CID_PRIVATE_SINR_SAMPLES,
 
 	/*using private CIDs under userclass*/
 	V4L2_CID_PRIVATE_IRIS_READ_DEFAULT = 0x00980928,
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index 4e1409e..226ea68 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -129,6 +129,7 @@
 #define RC_MAP_RC5_TV                    "rc-rc5-tv"
 #define RC_MAP_RC6_MCE                   "rc-rc6-mce"
 #define RC_MAP_REAL_AUDIO_220_32_KEYS    "rc-real-audio-220-32-keys"
+#define RC_MAP_SAMSUNG_NECX		 "rc-samsung-necx"
 #define RC_MAP_STREAMZAP                 "rc-streamzap"
 #define RC_MAP_TBS_NEC                   "rc-tbs-nec"
 #define RC_MAP_TECHNISAT_USB2            "rc-technisat-usb2"
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 857f654..8e66a25 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1047,6 +1047,8 @@
 /* LE SMP Management interface */
 int le_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, void *cp);
 int mgmt_remote_class(u16 index, bdaddr_t *bdaddr, u8 dev_class[3]);
+int mgmt_remote_version(u16 index, bdaddr_t *bdaddr, u8 ver, u16 mnf,
+							u16 sub_ver);
 
 /* HCI info for socket */
 #define hci_pi(sk) ((struct hci_pinfo *) sk)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index de61c32..9e79fb3 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -347,3 +347,11 @@
 	bdaddr_t bdaddr;
 	__u8 dev_class[3];
 } __packed;
+
+#define MGMT_EV_REMOTE_VERSION		0x0018
+struct mgmt_ev_remote_version {
+	bdaddr_t bdaddr;
+	__u8	lmp_ver;
+	__u16	manufacturer;
+	__u16	lmp_subver;
+} __packed;
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 798ed89..30f1a7c 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -1,7 +1,6 @@
-
 /*
  *
- * 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
@@ -353,6 +352,12 @@
 	struct afe_param_payload payload;
 } __attribute__ ((packed));
 
+struct afe_port_cmd_set_param_no_payload {
+	struct apr_hdr hdr;
+	u16 port_id;
+	u16 payload_size;
+	u32 payload_address;
+} __packed;
 
 #define AFE_EVENT_GET_ACTIVE_PORTS 0x00010100
 struct afe_get_active_ports_rsp {
diff --git a/include/sound/compress_offload.h b/include/sound/compress_offload.h
index 423264d..f746780 100644
--- a/include/sound/compress_offload.h
+++ b/include/sound/compress_offload.h
@@ -56,6 +56,7 @@
 	size_t decoded;
 	size_t rendered;
 	__u32 sampling_rate;
+	uint64_t timestamp;
 };
 
 /**
diff --git a/include/sound/jack.h b/include/sound/jack.h
index 5fedf19..ccdc341 100644
--- a/include/sound/jack.h
+++ b/include/sound/jack.h
@@ -51,6 +51,8 @@
 	SND_JACK_BTN_3		= 0x0800,
 	SND_JACK_BTN_4		= 0x0400,
 	SND_JACK_BTN_5		= 0x0200,
+	SND_JACK_BTN_6		= 0x0100,
+	SND_JACK_BTN_7		= 0x0080,
 };
 
 struct snd_jack {
@@ -59,7 +61,7 @@
 	int type;
 	const char *id;
 	char name[100];
-	unsigned int key[6];   /* Keep in sync with definitions above */
+	unsigned int key[8];   /* Keep in sync with definitions above */
 	void *private_data;
 	void (*private_free)(struct snd_jack *);
 };
diff --git a/include/sound/q6afe.h b/include/sound/q6afe.h
index 6206838..2d0f53f 100644
--- a/include/sound/q6afe.h
+++ b/include/sound/q6afe.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -76,7 +76,9 @@
 int afe_start_pseudo_port(u16 port_id);
 int afe_stop_pseudo_port(u16 port_id);
 int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz);
+int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz);
 int afe_cmd_memory_unmap(u32 dma_addr_p);
+int afe_cmd_memory_unmap_nowait(u32 dma_addr_p);
 
 int afe_register_get_events(u16 port_id,
 		void (*cb) (uint32_t opcode,
diff --git a/kernel/printk.c b/kernel/printk.c
index dbaa948..3c31395 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -41,7 +41,7 @@
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 #include <linux/rculist.h>
-
+#include <mach/msm_rtb.h>
 #include <asm/uaccess.h>
 
 /*
@@ -784,6 +784,11 @@
 {
 	va_list args;
 	int r;
+#ifdef CONFIG_MSM_RTB
+	void *caller = __builtin_return_address(0);
+
+	uncached_logk_pc(LOGK_LOGBUF, caller, (void *)log_end);
+#endif
 
 #ifdef CONFIG_KGDB_KDB
 	if (unlikely(kdb_trap_printk)) {
diff --git a/mm/ashmem.c b/mm/ashmem.c
index bc977ee..e4aab56 100644
--- a/mm/ashmem.c
+++ b/mm/ashmem.c
@@ -673,10 +673,28 @@
 	void (*cache_func)(unsigned long vstart, unsigned long length,
 				unsigned long pstart))
 {
+	int ret = 0;
+	struct vm_area_struct *vma;
 #ifdef CONFIG_OUTER_CACHE
 	unsigned long vaddr;
 #endif
-	mutex_lock(&ashmem_mutex);
+	if (!asma->vm_start)
+		return -EINVAL;
+
+	down_read(&current->mm->mmap_sem);
+	vma = find_vma(current->mm, asma->vm_start);
+	if (!vma) {
+		ret = -EINVAL;
+		goto done;
+	}
+	if (vma->vm_file != asma->file) {
+		ret = -EINVAL;
+		goto done;
+	}
+	if ((asma->vm_start + asma->size) > (vma->vm_start + vma->vm_end)) {
+		ret = -EINVAL;
+		goto done;
+	}
 #ifndef CONFIG_OUTER_CACHE
 	cache_func(asma->vm_start, asma->size, 0);
 #else
@@ -689,8 +707,11 @@
 		cache_func(vaddr, PAGE_SIZE, physaddr);
 	}
 #endif
-	mutex_unlock(&ashmem_mutex);
-	return 0;
+done:
+	up_read(&current->mm->mmap_sem);
+	if (ret)
+		asma->vm_start = 0;
+	return ret;
 }
 
 static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index e56fe35..b3b122f 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -686,6 +686,14 @@
 
 	bdi_unregister(bdi);
 
+	/*
+	 * If bdi_unregister() had already been called earlier, the
+	 * wakeup_timer could still be armed because bdi_prune_sb()
+	 * can race with the bdi_wakeup_thread_delayed() calls from
+	 * __mark_inode_dirty().
+	 */
+	del_timer_sync(&bdi->wb.wakeup_timer);
+
 	for (i = 0; i < NR_BDI_STAT_ITEMS; i++)
 		percpu_counter_destroy(&bdi->bdi_stat[i]);
 
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 70ea0df..f8cf37d 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -466,6 +466,7 @@
 
 	zone->present_pages += onlined_pages;
 	zone->zone_pgdat->node_present_pages += onlined_pages;
+	drain_all_pages();
 	if (need_zonelists_rebuild)
 		build_all_zonelists(zone);
 	else
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 f98a90e..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>
 
@@ -1606,12 +1606,12 @@
 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
 			conn->link_mode |= HCI_LM_ENCRYPT;
 
-		/* Get remote features */
+		/* Get remote version */
 		if (conn->type == ACL_LINK) {
-			struct hci_cp_read_remote_features cp;
+			struct hci_cp_read_remote_version cp;
 			cp.handle = ev->handle;
-			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
-							sizeof(cp), &cp);
+			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_VERSION,
+				sizeof(cp), &cp);
 		}
 
 		/* Set packet type for incoming connection */
@@ -1959,7 +1959,24 @@
 
 static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	BT_DBG("%s", hdev->name);
+	struct hci_ev_remote_version *ev = (void *) skb->data;
+	struct hci_cp_read_remote_features cp;
+	struct hci_conn *conn;
+	BT_DBG("%s status %d", hdev->name, ev->status);
+
+	hci_dev_lock(hdev);
+	cp.handle = ev->handle;
+	hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
+				sizeof(cp), &cp);
+
+	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
+	if (!conn)
+		goto unlock;
+	if (!ev->status)
+		mgmt_remote_version(hdev->id, &conn->dst, ev->lmp_ver,
+				ev->manufacturer, ev->lmp_subver);
+unlock:
+	hci_dev_unlock(hdev);
 }
 
 static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
@@ -2475,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))
@@ -2570,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/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 67a2900..2e4c47a 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2040,10 +2040,13 @@
 	if (err < 0)
 		mgmt_pending_remove(cmd);
 	else if (lmp_le_capable(hdev)) {
+		cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, index);
+		if (!cmd)
+			mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, index,
+								NULL, 0);
 		hdev->disco_int_phase = 1;
 		hdev->disco_int_count = 0;
 		hdev->disco_state = SCAN_BR;
-		mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, index, NULL, 0);
 		del_timer(&hdev->disco_le_timer);
 		del_timer(&hdev->disco_timer);
 		mod_timer(&hdev->disco_timer,
@@ -2893,3 +2896,18 @@
 
 	return mgmt_event(MGMT_EV_REMOTE_CLASS, index, &ev, sizeof(ev), NULL);
 }
+
+int mgmt_remote_version(u16 index, bdaddr_t *bdaddr, u8 ver, u16 mnf,
+							u16 sub_ver)
+{
+	struct mgmt_ev_remote_version ev;
+
+	memset(&ev, 0, sizeof(ev));
+
+	bacpy(&ev.bdaddr, bdaddr);
+	ev.lmp_ver = ver;
+	ev.manufacturer = mnf;
+	ev.lmp_subver = sub_ver;
+
+	return mgmt_event(MGMT_EV_REMOTE_VERSION, index, &ev, sizeof(ev), NULL);
+}
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/core/pcm_native.c b/sound/core/pcm_native.c
index 6dd815d..8c07206 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1530,8 +1530,6 @@
 	if (PCM_RUNTIME_CHECK(substream))
 		return -ENXIO;
 	runtime = substream->runtime;
-	if (runtime->status->state != SNDRV_PCM_STATE_OPEN)
-		return -EBADFD;
 	pr_err("%s called with cmd = %d\n", __func__, cmd);
 	err = substream->ops->ioctl(substream, cmd, arg);
 	return err;
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 cec01f1..d4e9ecf 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -23,7 +23,6 @@
 #include <linux/mfd/wcd9310/pdata.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
-#include <sound/jack.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/tlv.h>
@@ -54,6 +53,7 @@
 #define TABLA_MCLK_RATE_9600KHZ 9600000
 
 #define TABLA_FAKE_INS_THRESHOLD_MS 2500
+#define TABLA_FAKE_REMOVAL_MIN_PERIOD_MS 50
 
 static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
 static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
@@ -118,13 +118,19 @@
 	u16 v_brh;
 	u16 v_brl;
 	u16 v_no_mic;
-	u8 nready;
 	u8 npoll;
 	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;
@@ -595,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),
@@ -680,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"
@@ -1546,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;
@@ -1816,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;
@@ -1842,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 */
@@ -2067,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),
@@ -2202,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"},
@@ -2520,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];
 }
 
@@ -2611,14 +2650,15 @@
 	if ((tabla->bandgap_type == TABLA_BANDGAP_OFF) &&
 		(choice == TABLA_BANDGAP_AUDIO_MODE)) {
 		tabla_codec_enable_audio_mode_bandgap(codec);
-	} else if ((tabla->bandgap_type == TABLA_BANDGAP_AUDIO_MODE) &&
-		(choice == TABLA_BANDGAP_MBHC_MODE)) {
+	} else if (choice == TABLA_BANDGAP_MBHC_MODE) {
 		snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x2,
 			0x2);
 		snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
 			0x80);
 		snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x4,
 			0x4);
+		snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x01,
+			0x01);
 		usleep_range(1000, 1000);
 		snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
 			0x00);
@@ -2640,6 +2680,7 @@
 {
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
 
+	pr_debug("%s: enable = %d\n", __func__, enable);
 	if (enable) {
 		snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x10, 0);
 		snd_soc_write(codec, TABLA_A_BIAS_CONFIG_MODE_BG_CTL, 0x17);
@@ -2656,6 +2697,7 @@
 		snd_soc_update_bits(codec, TABLA_A_BIAS_CONFIG_MODE_BG_CTL, 0x1,
 			0);
 		snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x80, 0);
+		snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x08, 0x00);
 	}
 	tabla->config_mode_active = enable ? true : false;
 
@@ -2667,7 +2709,7 @@
 {
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
 
-	pr_debug("%s\n", __func__);
+	pr_debug("%s: config_mode = %d\n", __func__, config_mode);
 
 	if (config_mode) {
 		tabla_codec_enable_config_mode(codec, 1);
@@ -2703,9 +2745,21 @@
 	tabla->clock_active = false;
 }
 
+static int tabla_codec_mclk_index(const struct tabla_priv *tabla)
+{
+	if (tabla->mclk_freq == TABLA_MCLK_RATE_12288KHZ)
+		return 0;
+	else if (tabla->mclk_freq == TABLA_MCLK_RATE_9600KHZ)
+		return 1;
+	else {
+		BUG_ON(1);
+		return -EINVAL;
+	}
+}
+
 static void tabla_codec_calibrate_hs_polling(struct snd_soc_codec *codec)
 {
-	u8 *n_cic;
+	u8 *n_ready, *n_cic;
 	struct tabla_mbhc_btn_detect_cfg *btn_det;
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
 
@@ -2736,15 +2790,16 @@
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B12_CTL,
 		      (tabla->mbhc_data.v_brl >> 8) & 0xFF);
 
+	n_ready = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_N_READY);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B1_CTL,
-		      tabla->mbhc_data.nready);
+		      n_ready[tabla_codec_mclk_index(tabla)]);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B2_CTL,
 		      tabla->mbhc_data.npoll);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B3_CTL,
 		      tabla->mbhc_data.nbounce_wait);
-
 	n_cic = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_N_CIC);
-	snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B6_CTL, n_cic[0]);
+	snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B6_CTL,
+		      n_cic[tabla_codec_mclk_index(tabla)]);
 }
 
 static int tabla_startup(struct snd_pcm_substream *substream,
@@ -2779,6 +2834,10 @@
 			tabla_codec_enable_clock_block(codec, 0);
 			tabla_codec_calibrate_hs_polling(codec);
 			tabla_codec_start_hs_polling(codec);
+		} else {
+			tabla_codec_enable_bandgap(codec,
+					TABLA_BANDGAP_AUDIO_MODE);
+			tabla_codec_enable_clock_block(codec, 0);
 		}
 	} else {
 
@@ -2800,6 +2859,10 @@
 			}
 			snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1,
 					0x05, 0x01);
+		} else {
+			tabla_codec_disable_clock_block(codec);
+			tabla_codec_enable_bandgap(codec,
+				TABLA_BANDGAP_OFF);
 		}
 	}
 	return 0;
@@ -3104,7 +3167,6 @@
 	/* Turn off the override after measuring mic voltage */
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
 
-	pr_debug("read microphone bias value %04x\n", bias_value);
 	return bias_value;
 }
 
@@ -3261,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);
@@ -3386,7 +3449,7 @@
 	 */
 	btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
 	n_cic = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_N_CIC);
-	ncic = n_cic[0];
+	ncic = n_cic[tabla_codec_mclk_index(tabla)];
 	nmeas = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration)->n_meas;
 	navg = TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration)->mbhc_navg;
 	mclk_rate = tabla->mclk_freq;
@@ -3419,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);
@@ -3439,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);
@@ -3473,7 +3534,7 @@
 		ret += sizeof(btn_det->_n_cic);
 	case TABLA_BTN_DET_N_CIC:
 		ret += sizeof(btn_det->_n_ready);
-	case TABLA_BTN_DET_V_N_READY:
+	case TABLA_BTN_DET_N_READY:
 		ret += sizeof(btn_det->_v_btn_high[0]) * btn_det->num_btn;
 	case TABLA_BTN_DET_V_BTN_HIGH:
 		ret += sizeof(btn_det->_v_btn_low[0]) * btn_det->num_btn;
@@ -3494,25 +3555,25 @@
 	struct tabla_mbhc_btn_detect_cfg *btn_det;
 	struct tabla_mbhc_plug_type_cfg *plug_type;
 	u16 *btn_high;
+	u8 *n_ready;
 	int i;
 
 	tabla = snd_soc_codec_get_drvdata(codec);
 	btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
 	plug_type = TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla->calibration);
 
+	n_ready = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_N_READY);
 	if (tabla->mclk_freq == TABLA_MCLK_RATE_12288KHZ) {
-		tabla->mbhc_data.nready = 3;
 		tabla->mbhc_data.npoll = 9;
 		tabla->mbhc_data.nbounce_wait = 30;
 	} else if (tabla->mclk_freq == TABLA_MCLK_RATE_9600KHZ) {
-		tabla->mbhc_data.nready = 2;
 		tabla->mbhc_data.npoll = 7;
 		tabla->mbhc_data.nbounce_wait = 23;
-	} else
-		WARN(1, "Unsupported mclk freq %d\n", tabla->mclk_freq);
+	}
 
 	tabla->mbhc_data.t_sta_dce = ((1000 * 256) / (tabla->mclk_freq / 1000) *
-				      tabla->mbhc_data.nready) + 10;
+				      n_ready[tabla_codec_mclk_index(tabla)]) +
+				     10;
 	tabla->mbhc_data.v_ins_hu =
 	    tabla_codec_v_sta_dce(codec, STA, plug_type->v_hs_max);
 	tabla->mbhc_data.v_ins_h =
@@ -3571,10 +3632,11 @@
 
 	n_cic = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_N_CIC);
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_TIMER_B6_CTL, 0xFF,
-			    n_cic[0]);
+			    n_cic[tabla_codec_mclk_index(tabla)]);
 
 	gain = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_GAIN);
-	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B2_CTL, 0x78, gain[0] << 3);
+	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B2_CTL, 0x78,
+			    gain[tabla_codec_mclk_index(tabla)] << 3);
 
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_TIMER_B4_CTL, 0x70,
 			    generic->mbhc_nsa << 4);
@@ -3589,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);
 }
@@ -3693,6 +3756,16 @@
 		pr_err("Error: no codec or calibration\n");
 		return -EINVAL;
 	}
+
+	if (mclk_rate != TABLA_MCLK_RATE_12288KHZ) {
+		if (mclk_rate == TABLA_MCLK_RATE_9600KHZ)
+			pr_err("Error: clock rate %dHz is not yet supported\n",
+			       mclk_rate);
+		else
+			pr_err("Error: unsupported clock rate %d\n", mclk_rate);
+		return -EINVAL;
+	}
+
 	tabla = snd_soc_codec_get_drvdata(codec);
 	tabla->headset_jack = headset_jack;
 	tabla->button_jack = button_jack;
@@ -3736,39 +3809,139 @@
 }
 EXPORT_SYMBOL_GPL(tabla_hs_detect);
 
+static int tabla_determine_button(const struct tabla_priv *priv,
+				  const s32 bias_mv)
+{
+	s16 *v_btn_low, *v_btn_high;
+	struct tabla_mbhc_btn_detect_cfg *btn_det;
+	int i, btn = -1;
+
+	btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(priv->calibration);
+	v_btn_low = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_V_BTN_LOW);
+	v_btn_high = tabla_mbhc_cal_btn_det_mp(btn_det,
+					       TABLA_BTN_DET_V_BTN_HIGH);
+	for (i = 0; i < btn_det->num_btn; i++) {
+		if ((v_btn_low[i] <= bias_mv) && (v_btn_high[i] >= bias_mv)) {
+			btn = i;
+			break;
+		}
+	}
+
+	if (btn == -1)
+		pr_debug("%s: couldn't find button number for mic mv %d\n",
+			 __func__, bias_mv);
+
+	return btn;
+}
+
+static int tabla_get_button_mask(const int btn)
+{
+	int mask = 0;
+	switch (btn) {
+	case 0:
+		mask = SND_JACK_BTN_0;
+		break;
+	case 1:
+		mask = SND_JACK_BTN_1;
+		break;
+	case 2:
+		mask = SND_JACK_BTN_2;
+		break;
+	case 3:
+		mask = SND_JACK_BTN_3;
+		break;
+	case 4:
+		mask = SND_JACK_BTN_4;
+		break;
+	case 5:
+		mask = SND_JACK_BTN_5;
+		break;
+	case 6:
+		mask = SND_JACK_BTN_6;
+		break;
+	case 7:
+		mask = SND_JACK_BTN_7;
+		break;
+	}
+	return mask;
+}
+
 static irqreturn_t tabla_dce_handler(int irq, void *data)
 {
+	int i, mask;
+	short bias_value_dce;
+	s32 bias_mv_dce;
+	int btn = -1, meas = 0;
 	struct tabla_priv *priv = data;
+	const struct tabla_mbhc_btn_detect_cfg *d =
+	    TABLA_MBHC_CAL_BTN_DET_PTR(priv->calibration);
+	short btnmeas[d->n_btn_meas + 1];
 	struct snd_soc_codec *codec = priv->codec;
-	short bias_value;
 
 	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
 	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
 	tabla_lock_sleep(priv);
 
-	bias_value = tabla_codec_read_dce_result(codec);
-	pr_debug("%s: button press interrupt, DCE: %d,%d\n",
-		 __func__, bias_value,
-		 tabla_codec_sta_dce_v(codec, 1, bias_value));
+	bias_value_dce = tabla_codec_read_dce_result(codec);
+	bias_mv_dce = tabla_codec_sta_dce_v(codec, 1, bias_value_dce);
 
-	bias_value = tabla_codec_read_sta_result(codec);
-	pr_debug("%s: button press interrupt, STA: %d,%d\n",
-		 __func__, bias_value,
-		 tabla_codec_sta_dce_v(codec, 0, bias_value));
-	/*
-	 * TODO: If button pressed is not button 0,
-	 * report the button press event immediately.
-	 */
-	priv->buttons_pressed |= SND_JACK_BTN_0;
-
-	msleep(100);
-
-	if (schedule_delayed_work(&priv->btn0_dwork,
-				  msecs_to_jiffies(400)) == 0) {
-		WARN(1, "Button pressed twice without release event\n");
-		tabla_unlock_sleep(priv);
+	/* determine pressed button */
+	btnmeas[meas++] = tabla_determine_button(priv, bias_mv_dce);
+	pr_debug("%s: meas %d - DCE %d,%d, button %d\n", __func__,
+		 meas - 1, bias_value_dce, bias_mv_dce, btnmeas[meas - 1]);
+	if (d->n_btn_meas == 0)
+		btn = btnmeas[0];
+	for (; ((d->n_btn_meas) && (meas < (d->n_btn_meas + 1))); meas++) {
+		bias_value_dce = tabla_codec_sta_dce(codec, 1);
+		bias_mv_dce = tabla_codec_sta_dce_v(codec, 1, bias_value_dce);
+		btnmeas[meas] = tabla_determine_button(priv, bias_mv_dce);
+		pr_debug("%s: meas %d - DCE %d,%d, button %d\n",
+			 __func__, meas, bias_value_dce, bias_mv_dce,
+			 btnmeas[meas]);
+		/* if large enough measurements are collected,
+		 * start to check if last all n_btn_con measurements were
+		 * in same button low/high range */
+		if (meas + 1 >= d->n_btn_con) {
+			for (i = 0; i < d->n_btn_con; i++)
+				if ((btnmeas[meas] < 0) ||
+				    (btnmeas[meas] != btnmeas[meas - i]))
+					break;
+			if (i == d->n_btn_con) {
+				/* button pressed */
+				btn = btnmeas[meas];
+				break;
+			}
+		}
+		/* if left measurements are less than n_btn_con,
+		 * it's impossible to find button number */
+		if ((d->n_btn_meas - meas) < d->n_btn_con)
+			break;
 	}
 
+	if (btn >= 0) {
+		mask = tabla_get_button_mask(btn);
+		priv->buttons_pressed |= mask;
+
+		msleep(100);
+
+		/* XXX: assuming button 0 has the lowest micbias voltage */
+		if (btn == 0) {
+			if (schedule_delayed_work(&priv->btn0_dwork,
+						  msecs_to_jiffies(400)) == 0) {
+				WARN(1, "Button pressed twice without release"
+				     "event\n");
+				tabla_unlock_sleep(priv);
+			}
+		} else {
+			pr_debug("%s: Reporting short button %d(0x%x) press\n",
+				  __func__, btn, mask);
+			tabla_snd_soc_jack_report(priv, priv->button_jack, mask,
+						  mask);
+		}
+	} else
+		pr_debug("%s: bogus button press, too short press?\n",
+			 __func__);
+
 	return IRQ_HANDLED;
 }
 
@@ -3776,18 +3949,18 @@
 {
 	struct tabla_priv *priv = data;
 	struct snd_soc_codec *codec = priv->codec;
-	int ret, mb_v;
+	int ret;
+	short mb_v;
 
-	pr_debug("%s\n", __func__);
+	pr_debug("%s: enter\n", __func__);
 	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
 	tabla_lock_sleep(priv);
 
 	if (priv->buttons_pressed & SND_JACK_BTN_0) {
 		ret = cancel_delayed_work(&priv->btn0_dwork);
-
 		if (ret == 0) {
-			pr_debug("%s: Reporting long button release event\n",
-					__func__);
+			pr_debug("%s: Reporting long button 0 release event\n",
+				 __func__);
 			if (priv->button_jack)
 				tabla_snd_soc_jack_report(priv,
 							  priv->button_jack, 0,
@@ -3801,25 +3974,37 @@
 				 __func__, mb_v,
 				 tabla_codec_sta_dce_v(codec, 0, mb_v));
 
-			if (mb_v < -2000 || mb_v > -670)
+			if (mb_v < (short)priv->mbhc_data.v_b1_hu ||
+			    mb_v > (short)priv->mbhc_data.v_ins_hu)
 				pr_debug("%s: Fake buttton press interrupt\n",
-						__func__);
+					 __func__);
 			else if (priv->button_jack) {
-				pr_debug("%s:reporting short button "
+				pr_debug("%s: Reporting short button 0 "
 					 "press and release\n", __func__);
 				tabla_snd_soc_jack_report(priv,
 							  priv->button_jack,
 							  SND_JACK_BTN_0,
 							  SND_JACK_BTN_0);
 				tabla_snd_soc_jack_report(priv,
-							  priv->button_jack,
-							  0, SND_JACK_BTN_0);
+							  priv->button_jack, 0,
+							  SND_JACK_BTN_0);
 			}
 		}
 
 		priv->buttons_pressed &= ~SND_JACK_BTN_0;
 	}
 
+	if (priv->buttons_pressed) {
+		pr_debug("%s:reporting button release mask 0x%x\n", __func__,
+			 priv->buttons_pressed);
+		tabla_snd_soc_jack_report(priv, priv->button_jack, 0,
+					  priv->buttons_pressed);
+		/* hardware doesn't detect another button press until
+		 * already pressed button is released.
+		 * therefore buttons_pressed has only one button's mask. */
+		priv->buttons_pressed &= ~TABLA_JACK_BUTTON_MASK;
+	}
+
 	tabla_codec_start_hs_polling(codec);
 	tabla_unlock_sleep(priv);
 	return IRQ_HANDLED;
@@ -3857,8 +4042,8 @@
 
 	if (!tabla->mclk_enabled) {
 		snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0x00);
-		tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_AUDIO_MODE);
-		tabla_codec_enable_clock_block(codec, 0);
+		tabla_codec_disable_clock_block(codec);
+		tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_OFF);
 	}
 
 	tabla->mbhc_polling_active = false;
@@ -4129,12 +4314,15 @@
 
 static irqreturn_t tabla_hs_remove_irq(int irq, void *data)
 {
+	short bias_value;
 	struct tabla_priv *priv = data;
 	struct snd_soc_codec *codec = priv->codec;
 	const struct tabla_mbhc_general_cfg *generic =
 	    TABLA_MBHC_CAL_GENERAL_PTR(priv->calibration);
-	short bias_value;
+	int fake_removal = 0;
+	int min_us = TABLA_FAKE_REMOVAL_MIN_PERIOD_MS * 1000;
 
+	pr_debug("%s: enter, removal interrupt\n", __func__);
 	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
 	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
 	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
@@ -4143,11 +4331,18 @@
 	usleep_range(generic->t_shutdown_plug_rem,
 		     generic->t_shutdown_plug_rem);
 
-	bias_value = tabla_codec_sta_dce(codec, 1);
-	pr_debug("removal interrupt, DCE: %d,%d\n",
-		 bias_value, tabla_codec_sta_dce_v(codec, 1, bias_value));
+	do {
+		bias_value = tabla_codec_sta_dce(codec, 1);
+		pr_debug("%s: DCE %d,%d, %d us left\n", __func__, bias_value,
+			 tabla_codec_sta_dce_v(codec, 1, bias_value), min_us);
+		if (bias_value < (short)priv->mbhc_data.v_ins_h) {
+			fake_removal = 1;
+			break;
+		}
+		min_us -= priv->mbhc_data.t_dce;
+	} while (min_us > 0);
 
-	if (bias_value < (short) priv->mbhc_data.v_ins_h) {
+	if (fake_removal) {
 		pr_debug("False alarm, headset not actually removed\n");
 		tabla_codec_start_hs_polling(codec);
 	} else {
@@ -4263,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)) {
@@ -4323,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),
@@ -4362,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,
@@ -4378,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[] = {
@@ -4401,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},
 
@@ -4436,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)
@@ -4453,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;
@@ -4491,23 +4745,33 @@
 	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__);
 		goto err_pdata;
 	}
 
-	/* TODO only enable bandgap when necessary in order to save power */
-	tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_AUDIO_MODE);
-	tabla_codec_enable_clock_block(codec, 0);
-
 	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));
@@ -4516,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 77bfc73..6ddc471 100644
--- a/sound/soc/codecs/wcd9310.h
+++ b/sound/soc/codecs/wcd9310.h
@@ -10,14 +10,13 @@
  * GNU General Public License for more details.
  */
 #include <sound/soc.h>
-
-#define TABLA_VERSION_1_0	0
-#define TABLA_VERSION_1_1	1
-#define TABLA_VERSION_2_0	2
+#include <sound/jack.h>
 
 #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}
 
@@ -28,7 +27,14 @@
 #define STA 0
 #define DCE 1
 
+#define TABLA_JACK_BUTTON_MASK (SND_JACK_BTN_0 | SND_JACK_BTN_1 | \
+				SND_JACK_BTN_2 | SND_JACK_BTN_3 | \
+				SND_JACK_BTN_4 | SND_JACK_BTN_5 | \
+				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 {
@@ -66,7 +72,7 @@
 enum tabla_mbhc_btn_det_mem {
 	TABLA_BTN_DET_V_BTN_LOW,
 	TABLA_BTN_DET_V_BTN_HIGH,
-	TABLA_BTN_DET_V_N_READY,
+	TABLA_BTN_DET_N_READY,
 	TABLA_BTN_DET_N_CIC,
 	TABLA_BTN_DET_GAIN
 };
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index d0497b1..f0f17a9 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -450,8 +450,37 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct compr_audio *compr = runtime->private_data;
 	struct msm_audio *prtd = &compr->prtd;
+	uint64_t timestamp;
+	uint64_t temp;
 
 	switch (cmd) {
+	case SNDRV_COMPRESS_TSTAMP: {
+		struct snd_compr_tstamp tstamp;
+		pr_debug("SNDRV_COMPRESS_TSTAMP\n");
+
+		memset(&tstamp, 0x0, sizeof(struct snd_compr_tstamp));
+		timestamp = q6asm_get_session_time(prtd->audio_client);
+		if (timestamp < 0) {
+			pr_err("%s: Get Session Time return value =%lld\n",
+				__func__, timestamp);
+			return -EAGAIN;
+		}
+		temp = (timestamp * 2 * runtime->channels);
+		temp = temp * (runtime->rate/1000);
+		temp = div_u64(temp, 1000);
+		tstamp.sampling_rate = runtime->rate;
+		tstamp.rendered = (size_t)(temp & 0xFFFFFFFF);
+		tstamp.decoded  = (size_t)((temp >> 32) & 0xFFFFFFFF);
+		tstamp.timestamp = timestamp;
+		pr_debug("%s: bytes_consumed:lsb = %d, msb = %d,"
+			"timestamp = %lld,\n",
+			 __func__, tstamp.rendered, tstamp.decoded,
+			tstamp.timestamp);
+		if (copy_to_user((void *) arg, &tstamp,
+			sizeof(struct snd_compr_tstamp)))
+				return -EFAULT;
+		return 0;
+	}
 	case SNDRV_COMPRESS_GET_CAPS:
 		pr_debug("SNDRV_COMPRESS_GET_CAPS\n");
 		if (copy_to_user((void *) arg, &compr->info.compr_cap,
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index fea11d9..42e7935 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -249,6 +249,28 @@
 		.ops = &msm_fe_dai_ops,
 		.name = "HDMI_HOSTLESS"
 	},
+	{
+		.playback = {
+			.stream_name = "AUXPCM Hostless Playback",
+			.rates = SNDRV_PCM_RATE_8000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 1,
+			.rate_min =     8000,
+			.rate_max =     8000,
+		},
+		.capture = {
+			.stream_name = "AUXPCM Hostless Capture",
+			.rates = SNDRV_PCM_RATE_8000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 1,
+			.rate_min =     8000,
+			.rate_max =    48000,
+		},
+		.ops = &msm_fe_dai_ops,
+		.name = "AUXPCM_HOSTLESS",
+	},
 };
 
 static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 96260ab..c7d7004 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -23,7 +23,6 @@
 #include <sound/soc.h>
 #include <sound/apr_audio.h>
 #include <sound/q6afe.h>
-#include <sound/q6adm.h>
 #include <sound/msm-dai-q6.h>
 #include <mach/clk.h>
 
@@ -420,6 +419,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:
@@ -465,10 +465,6 @@
 	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
 	int rc = 0;
 
-	rc = adm_close(dai->id);
-	if (IS_ERR_VALUE(rc))
-		dev_err(dai->dev, "fail to close ADM COPP\n");
-
 	pr_debug("%s: dai->id = %d", __func__, dai->id);
 
 	if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
@@ -820,6 +816,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 +1083,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..2b4999f 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,
@@ -912,6 +937,18 @@
 	SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
 	MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
 	msm_routing_put_port_mixer),
+	SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+	MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+};
+
+static const struct snd_kcontrol_new auxpcm_rx_port_mixer_controls[] = {
+	SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_AUXPCM_RX,
+	MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+	SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_AUXPCM_RX,
+	MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
 };
 
 static const struct snd_kcontrol_new fm_switch_mixer_controls =
@@ -1129,11 +1166,17 @@
 	SND_SOC_DAPM_AIF_OUT("INTFM_UL_HL", "INT_FM_HOSTLESS Capture",
 		0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("HDMI_DL_HL", "HDMI_HOSTLESS Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("AUXPCM_DL_HL", "AUXPCM_HOSTLESS Playback",
+		0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AUXPCM_UL_HL", "AUXPCM_HOSTLESS Capture",
+		0, 0, 0, 0),
 
 	/* Backend AIF */
 	/* 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 +1209,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 +1231,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,
@@ -1221,6 +1270,9 @@
 	SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Port Mixer",
 	SND_SOC_NOPM, 0, 0, sbus_0_rx_port_mixer_controls,
 	ARRAY_SIZE(sbus_0_rx_port_mixer_controls)),
+	SND_SOC_DAPM_MIXER("AUXPCM_RX Port Mixer",
+	SND_SOC_NOPM, 0, 0, auxpcm_rx_port_mixer_controls,
+	ARRAY_SIZE(auxpcm_rx_port_mixer_controls)),
 };
 
 static const struct snd_soc_dapm_route intercon[] = {
@@ -1230,6 +1282,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 +1353,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"},
@@ -1334,9 +1396,16 @@
 	{"SLIM0_UL_HL", NULL, "SLIMBUS_0_TX"},
 	{"INT_FM_RX", NULL, "INTFM_DL_HL"},
 	{"INTFM_UL_HL", NULL, "INT_FM_TX"},
+	{"AUX_PCM_RX", NULL, "AUXPCM_DL_HL"},
+	{"AUXPCM_UL_HL", NULL, "AUX_PCM_TX"},
 	{"SLIMBUS_0_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
 	{"SLIMBUS_0_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+	{"SLIMBUS_0_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
 	{"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Port Mixer"},
+
+	{"AUXPCM_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
+	{"AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+	{"AUX_PCM_RX", NULL, "AUXPCM_RX Port Mixer"},
 };
 
 static int msm_pcm_routing_hw_params(struct snd_pcm_substream *substream,
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index 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,
 };
 
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 0dc3b57..578f819 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -55,7 +55,7 @@
 
 #define TABLA_EXT_CLK_RATE 12288000
 
-#define TABLA_MBHC_DEF_BUTTONS 3
+#define TABLA_MBHC_DEF_BUTTONS 8
 #define TABLA_MBHC_DEF_RLOADS 5
 
 static u32 top_spk_pamp_gpio  = PM8921_GPIO_PM_TO_SYS(18);
@@ -571,7 +571,7 @@
 	void *tabla_cal;
 	struct tabla_mbhc_btn_detect_cfg *btn_cfg;
 	u16 *btn_low, *btn_high;
-	u8 *n_cic, *gain;
+	u8 *n_ready, *n_cic, *gain;
 
 	tabla_cal = kzalloc(TABLA_MBHC_CAL_SIZE(TABLA_MBHC_DEF_BUTTONS,
 						TABLA_MBHC_DEF_RLOADS),
@@ -597,20 +597,16 @@
 #undef S
 #define S(X, Y) ((TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla_cal)->X) = (Y))
 	S(v_no_mic, 30);
-	S(v_hs_max, 1450);
+	S(v_hs_max, 1550);
 #undef S
 #define S(X, Y) ((TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal)->X) = (Y))
-	S(c[0], 6);
-	S(c[1], 10);
-	S(c[2], 10);
-	S(c[3], 14);
-	S(c[4], 14);
-	S(c[5], 16);
-	S(c[6], 0);
-	S(c[7], 0);
-	S(nc, 5);
-	S(n_meas, 11);
+	S(c[0], 62);
+	S(c[1], 124);
+	S(nc, 1);
+	S(n_meas, 3);
 	S(mbhc_nsc, 11);
+	S(n_btn_meas, 1);
+	S(n_btn_con, 2);
 	S(num_btn, TABLA_MBHC_DEF_BUTTONS);
 	S(v_btn_press_delta_sta, 100);
 	S(v_btn_press_delta_cic, 50);
@@ -618,15 +614,28 @@
 	btn_cfg = TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal);
 	btn_low = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_LOW);
 	btn_high = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_HIGH);
-	btn_low[0] = 0;
-	btn_high[0] = 40;
-	btn_low[1] = 60;
-	btn_high[1] = 140;
-	btn_low[2] = 160;
-	btn_high[2] = 240;
+	btn_low[0] = -50;
+	btn_high[0] = 10;
+	btn_low[1] = 11;
+	btn_high[1] = 38;
+	btn_low[2] = 39;
+	btn_high[2] = 64;
+	btn_low[3] = 65;
+	btn_high[3] = 91;
+	btn_low[4] = 92;
+	btn_high[4] = 115;
+	btn_low[5] = 116;
+	btn_high[5] = 141;
+	btn_low[6] = 142;
+	btn_high[6] = 163;
+	btn_low[7] = 164;
+	btn_high[7] = 250;
+	n_ready = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_READY);
+	n_ready[0] = 48;
+	n_ready[1] = 38;
 	n_cic = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_CIC);
-	n_cic[0] = 120;
-	n_cic[1] = 94;
+	n_cic[0] = 60;
+	n_cic[1] = 47;
 	gain = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_GAIN);
 	gain[0] = 11;
 	gain[1] = 9;
@@ -668,15 +677,16 @@
 	snd_soc_dapm_sync(dapm);
 
 	err = snd_soc_jack_new(codec, "Headset Jack",
-		(SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR),
-		&hs_jack);
+			       (SND_JACK_HEADSET | SND_JACK_OC_HPHL |
+				SND_JACK_OC_HPHR),
+			       &hs_jack);
 	if (err) {
 		pr_err("failed to create new jack\n");
 		return err;
 	}
 
 	err = snd_soc_jack_new(codec, "Button Jack",
-				SND_JACK_BTN_0, &button_jack);
+			       TABLA_JACK_BUTTON_MASK, &button_jack);
 	if (err) {
 		pr_err("failed to create new jack\n");
 		return err;
@@ -706,16 +716,8 @@
 	},
 };
 
-static struct snd_soc_dsp_link slimbus0_hl_media = {
-	.playback = true,
-	.capture = true,
-	.trigger = {
-		SND_SOC_DSP_TRIGGER_POST,
-		SND_SOC_DSP_TRIGGER_POST
-	},
-};
-
-static struct snd_soc_dsp_link int_fm_hl_media = {
+/* bi-directional media definition for hostless PCM device */
+static struct snd_soc_dsp_link bidir_hl_media = {
 	.playback = true,
 	.capture = true,
 	.trigger = {
@@ -975,7 +977,7 @@
 		.cpu_dai_name	= "SLIMBUS0_HOSTLESS",
 		.platform_name  = "msm-pcm-hostless",
 		.dynamic = 1,
-		.dsp_link = &slimbus0_hl_media,
+		.dsp_link = &bidir_hl_media,
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ignore_suspend = 1,
 		/* .be_id = do not care */
@@ -986,7 +988,7 @@
 		.cpu_dai_name	= "INT_FM_HOSTLESS",
 		.platform_name  = "msm-pcm-hostless",
 		.dynamic = 1,
-		.dsp_link = &int_fm_hl_media,
+		.dsp_link = &bidir_hl_media,
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ignore_suspend = 1,
 		/* .be_id = do not care */
@@ -1018,6 +1020,16 @@
 		.dsp_link = &lpa_fe_media,
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
 	},
+	{
+		.name = "AUXPCM Hostless",
+		.stream_name = "AUXPCM Hostless",
+		.cpu_dai_name	= "AUXPCM_HOSTLESS",
+		.platform_name  = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dsp_link = &bidir_hl_media,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+	},
 	/* HDMI Hostless */
 	{
 		.name = "HDMI_RX_HOSTLESS",
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index 18dfc01..177e1d8 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -457,7 +457,7 @@
 	int     i = 0;
 	int     cmd_size = 0;
 
-	pr_info("%s\n", __func__);
+	pr_debug("%s\n", __func__);
 	if (this_adm.apr == NULL) {
 		this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
 						0xFFFFFFFF, &this_adm);
@@ -532,7 +532,7 @@
 	int     i = 0;
 	int     cmd_size = 0;
 
-	pr_info("%s\n", __func__);
+	pr_debug("%s\n", __func__);
 
 	if (this_adm.apr == NULL) {
 		pr_err("%s APR handle NULL\n", __func__);
@@ -615,7 +615,7 @@
 	if (afe_validate_port(port_id) < 0)
 		return -EINVAL;
 
-	pr_info("%s port_id=%d index %d\n", __func__, port_id, index);
+	pr_debug("%s port_id=%d index %d\n", __func__, port_id, index);
 
 	if (!(atomic_read(&this_adm.copp_cnt[index]))) {
 		pr_err("%s: copp count for port[%d]is 0\n", __func__, port_id);
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index 74a66945..302ef57 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.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
@@ -17,6 +17,7 @@
 #include <linux/wait.h>
 #include <linux/jiffies.h>
 #include <linux/sched.h>
+#include <mach/qdsp6v2/audio_acdb.h>
 #include <sound/apr_audio.h>
 #include <sound/q6afe.h>
 
@@ -36,6 +37,8 @@
 
 static struct afe_ctl this_afe;
 
+static uint32_t afe_cal_addr[MAX_AUDPROC_TYPES];
+
 #define TIMEOUT_MS 1000
 #define Q6AFE_MAX_VOLUME 0x3FFF
 
@@ -314,6 +317,63 @@
 	return ret;
 }
 
+static void afe_send_cal_block(int32_t path, u16 port_id)
+{
+	int						result = 0;
+	struct acdb_cal_block				cal_block;
+	struct afe_port_cmd_set_param_no_payload	afe_cal;
+	pr_debug("%s: path %d\n", __func__, path);
+
+	get_afe_cal(path, &cal_block);
+	if (cal_block.cal_size <= 0) {
+		pr_debug("%s: No AFE cal to send!\n", __func__);
+		goto done;
+	}
+
+	if (afe_cal_addr[path] != cal_block.cal_paddr) {
+		if (afe_cal_addr[path] != 0)
+			afe_cmd_memory_unmap_nowait(afe_cal_addr[path]);
+		afe_cmd_memory_map_nowait(cal_block.cal_paddr,
+						cal_block.cal_size);
+		afe_cal_addr[path] = cal_block.cal_paddr;
+	}
+
+	afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	afe_cal.hdr.pkt_size = sizeof(afe_cal);
+	afe_cal.hdr.src_port = 0;
+	afe_cal.hdr.dest_port = 0;
+	afe_cal.hdr.token = 0;
+	afe_cal.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
+	afe_cal.port_id = port_id;
+	afe_cal.payload_size = cal_block.cal_size;
+	afe_cal.payload_address = cal_block.cal_paddr;
+
+	pr_debug("%s: AFE cal sent for device port = %d, path = %d, "
+		"cal size = %d, cal addr = 0x%x\n", __func__,
+		port_id, path, cal_block.cal_size, cal_block.cal_paddr);
+
+	result = apr_send_pkt(this_afe.apr, (uint32_t *) &afe_cal);
+	if (result < 0) {
+		pr_err("%s: AFE cal for port %d failed\n",
+			__func__, port_id);
+	}
+
+	pr_debug("%s: AFE cal sent for path %d device!\n", __func__, path);
+done:
+	return;
+}
+
+void afe_send_cal(u16 port_id)
+{
+	pr_debug("%s\n", __func__);
+
+	if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
+		afe_send_cal_block(TX_CAL, port_id);
+	else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
+		afe_send_cal_block(RX_CAL, port_id);
+}
+
 int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
 	u32 rate) /* This function is no blocking */
 {
@@ -326,7 +386,7 @@
 		ret = -EINVAL;
 		return ret;
 	}
-	pr_info("%s: %d %d\n", __func__, port_id, rate);
+	pr_debug("%s: %d %d\n", __func__, port_id, rate);
 
 	if ((port_id == RT_PROXY_DAI_001_RX) ||
 		(port_id == RT_PROXY_DAI_002_TX))
@@ -365,6 +425,10 @@
 		ret = -EINVAL;
 		goto fail_cmd;
 	}
+
+	/* send AFE cal */
+	afe_send_cal(port_id);
+
 	start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
 	start.hdr.pkt_size = sizeof(start);
@@ -875,6 +939,45 @@
 	return 0;
 }
 
+int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz)
+{
+	int ret = 0;
+	struct afe_cmd_memory_map mregion;
+
+	pr_debug("%s:\n", __func__);
+
+	if (this_afe.apr == NULL) {
+		this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
+					0xFFFFFFFF, &this_afe);
+		pr_debug("%s: Register AFE\n", __func__);
+		if (this_afe.apr == NULL) {
+			pr_err("%s: Unable to register AFE\n", __func__);
+			ret = -ENODEV;
+			return ret;
+		}
+	}
+
+	mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	mregion.hdr.pkt_size = sizeof(mregion);
+	mregion.hdr.src_port = 0;
+	mregion.hdr.dest_port = 0;
+	mregion.hdr.token = 0;
+	mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
+	mregion.phy_addr = dma_addr_p;
+	mregion.mem_sz = dma_buf_sz;
+	mregion.mem_id = 0;
+	mregion.rsvd = 0;
+
+	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
+	if (ret < 0) {
+		pr_err("%s: AFE memory map cmd failed %d\n",
+			__func__, ret);
+		ret = -EINVAL;
+	}
+	return 0;
+}
+
 int afe_cmd_memory_unmap(u32 dma_addr_p)
 {
 	int ret = 0;
@@ -905,7 +1008,7 @@
 	atomic_set(&this_afe.state, 1);
 	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
 	if (ret < 0) {
-		pr_err("%s: AFE memory map cmd failed %d\n",
+		pr_err("%s: AFE memory unmap cmd failed %d\n",
 		       __func__, ret);
 		ret = -EINVAL;
 		return ret;
@@ -919,7 +1022,42 @@
 		ret = -EINVAL;
 		return ret;
 	}
+	return 0;
+}
 
+int afe_cmd_memory_unmap_nowait(u32 dma_addr_p)
+{
+	int ret = 0;
+	struct afe_cmd_memory_unmap mregion;
+
+	pr_debug("%s:\n", __func__);
+
+	if (this_afe.apr == NULL) {
+		this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
+					0xFFFFFFFF, &this_afe);
+		pr_debug("%s: Register AFE\n", __func__);
+		if (this_afe.apr == NULL) {
+			pr_err("%s: Unable to register AFE\n", __func__);
+			ret = -ENODEV;
+			return ret;
+		}
+	}
+
+	mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	mregion.hdr.pkt_size = sizeof(mregion);
+	mregion.hdr.src_port = 0;
+	mregion.hdr.dest_port = 0;
+	mregion.hdr.token = 0;
+	mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
+	mregion.phy_addr = dma_addr_p;
+
+	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
+	if (ret < 0) {
+		pr_err("%s: AFE memory unmap cmd failed %d\n",
+			__func__, ret);
+		ret = -EINVAL;
+	}
 	return 0;
 }
 
@@ -1290,7 +1428,7 @@
 		ret = -EINVAL;
 		goto fail_cmd;
 	}
-	pr_info("%s: port_id=%d\n", __func__, port_id);
+	pr_debug("%s: port_id=%d\n", __func__, port_id);
 	port_id = afe_convert_virtual_to_portid(port_id);
 
 	stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -1328,7 +1466,7 @@
 		ret = -EINVAL;
 		goto fail_cmd;
 	}
-	pr_info("%s: port_id=%d\n", __func__, port_id);
+	pr_debug("%s: port_id=%d\n", __func__, port_id);
 	port_id = afe_convert_virtual_to_portid(port_id);
 
 	stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -1389,12 +1527,17 @@
 
 static void __exit afe_exit(void)
 {
+	int i;
 #ifdef CONFIG_DEBUG_FS
 	if (debugfs_afelb)
 		debugfs_remove(debugfs_afelb);
 	if (debugfs_afelb_gain)
 		debugfs_remove(debugfs_afelb_gain);
 #endif
+	for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
+		if (afe_cal_addr[i] != 0)
+			afe_cmd_memory_unmap_nowait(afe_cal_addr[i]);
+	}
 }
 
 device_initcall(afe_init);
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 2acf59e..532d92b 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -17,6 +17,7 @@
 #include <linux/wait.h>
 #include <linux/mutex.h>
 
+#include <asm/mach-types.h>
 #include <mach/qdsp6v2/audio_acdb.h>
 #include <mach/qdsp6v2/rtac.h>
 
@@ -2070,8 +2071,14 @@
 	mvm_set_voice_timing.hdr.opcode = VSS_ICOMMON_CMD_SET_VOICE_TIMING;
 	mvm_set_voice_timing.timing.mode = 0;
 	mvm_set_voice_timing.timing.enc_offset = 8000;
-	mvm_set_voice_timing.timing.dec_req_offset = 3300;
-	mvm_set_voice_timing.timing.dec_offset = 8300;
+	if (machine_is_apq8064_sim()) {
+		pr_debug("%s: Machine is apq8064 sim\n", __func__);
+		mvm_set_voice_timing.timing.dec_req_offset = 0;
+		mvm_set_voice_timing.timing.dec_offset = 18000;
+	} else {
+		mvm_set_voice_timing.timing.dec_req_offset = 3300;
+		mvm_set_voice_timing.timing.dec_offset = 8300;
+	}
 
 	v->mvm_state = CMD_STATUS_FAIL;